app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

test_host.sh (6672B)


      1 #!/usr/bin/env bash
      2 set -euo pipefail
      3 
      4 script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
      5 platform_root="$(cd "${script_dir}/.." && pwd -P)"
      6 repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)"
      7 date_utc="$(date -u +%F)"
      8 
      9 require_command() {
     10   if command -v "$1" >/dev/null 2>&1; then
     11     return
     12   fi
     13   echo "missing required command: $1" >&2
     14   exit 1
     15 }
     16 
     17 require_command /usr/libexec/PlistBuddy
     18 require_command mktemp
     19 require_command readlink
     20 
     21 app_path="$("${script_dir}/build_host.sh")"
     22 plist_path="${app_path}/Contents/Info.plist"
     23 executable_name="$(
     24   /usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "${plist_path}"
     25 )"
     26 bundle_name="$(
     27   /usr/libexec/PlistBuddy -c 'Print :CFBundleName' "${plist_path}"
     28 )"
     29 bundle_id="$(
     30   /usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "${plist_path}"
     31 )"
     32 icon_name="$(
     33   /usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' "${plist_path}"
     34 )"
     35 
     36 [[ "${bundle_name}" == "Radroots" ]] || {
     37   echo "unexpected CFBundleName: ${bundle_name}" >&2
     38   exit 1
     39 }
     40 
     41 [[ "${bundle_id}" == "org.radroots.app.macos" ]] || {
     42   echo "unexpected CFBundleIdentifier: ${bundle_id}" >&2
     43   exit 1
     44 }
     45 
     46 [[ -x "${app_path}/Contents/MacOS/${executable_name}" ]] || {
     47   echo "missing bundle executable: ${app_path}/Contents/MacOS/${executable_name}" >&2
     48   exit 1
     49 }
     50 
     51 [[ -f "${app_path}/Contents/Resources/${icon_name}.icns" ]] || {
     52   echo "missing bundle icon: ${app_path}/Contents/Resources/${icon_name}.icns" >&2
     53   exit 1
     54 }
     55 
     56 release_app_path="$(
     57   CONFIGURATION=Release "${script_dir}/build_host.sh"
     58 )"
     59 [[ "${release_app_path}" == "${platform_root}/.derived-data/Build/Products/Release/Radroots.app" ]] || {
     60   echo "unexpected release bundle path: ${release_app_path}" >&2
     61   exit 1
     62 }
     63 [[ -x "${release_app_path}/Contents/MacOS/Radroots" ]] || {
     64   echo "missing release bundle executable: ${release_app_path}/Contents/MacOS/Radroots" >&2
     65   exit 1
     66 }
     67 
     68 tmp_root="$(mktemp -d)"
     69 runner_pid=""
     70 degraded_runner_pid=""
     71 startup_wait_attempts="${RADROOTS_APP_HOST_STARTUP_ATTEMPTS:-300}"
     72 
     73 wait_for_log_event() {
     74   local structured_log_file="$1"
     75   local expected_event="$2"
     76   local runner_pid="$3"
     77   local event_verified=false
     78 
     79   for _ in $(seq 1 "${startup_wait_attempts}"); do
     80     if [[ -f "${structured_log_file}" ]] && grep -q "\"event\":\"${expected_event}\"" "${structured_log_file}" 2>/dev/null; then
     81       event_verified=true
     82       break
     83     fi
     84 
     85     if ! kill -0 "${runner_pid}" 2>/dev/null; then
     86       wait "${runner_pid}"
     87       exit $?
     88     fi
     89 
     90     sleep 0.1
     91   done
     92 
     93   [[ "${event_verified}" == "true" ]] || {
     94     echo "${expected_event} was not recorded by run_host.sh" >&2
     95     exit 1
     96   }
     97 }
     98 
     99 assert_latest_alias() {
    100   local latest_log_path="$1"
    101 
    102   [[ -e "${latest_log_path}" ]] || {
    103     echo "missing latest structured log alias: ${latest_log_path}" >&2
    104     exit 1
    105   }
    106 
    107   [[ "$(readlink "${latest_log_path}")" == "${date_utc}.jsonl" ]] || {
    108     echo "latest structured log alias does not point at ${date_utc}.jsonl" >&2
    109     exit 1
    110   }
    111 }
    112 
    113 assert_raw_logs_exist() {
    114   local stdout_file="$1"
    115   local stderr_file="$2"
    116 
    117   [[ -f "${stdout_file}" ]] || {
    118     echo "missing raw stdout log: ${stdout_file}" >&2
    119     exit 1
    120   }
    121 
    122   [[ -f "${stderr_file}" ]] || {
    123     echo "missing raw stderr log: ${stderr_file}" >&2
    124     exit 1
    125   }
    126 }
    127 
    128 terminate_runner() {
    129   local runner_pid="$1"
    130 
    131   if [[ -n "${runner_pid}" ]] && kill -0 "${runner_pid}" 2>/dev/null; then
    132     kill "${runner_pid}" 2>/dev/null || true
    133   fi
    134 
    135   set +e
    136   wait "${runner_pid}"
    137   local exit_code="$?"
    138   set -e
    139   [[ "${exit_code}" == "0" ]] || [[ "${exit_code}" == "143" ]] || [[ "${exit_code}" == "130" ]] || {
    140     echo "unexpected runner exit code after termination: ${exit_code}" >&2
    141     exit 1
    142   }
    143 }
    144 
    145 cleanup() {
    146   if [[ -n "${runner_pid:-}" ]] && kill -0 "${runner_pid}" 2>/dev/null; then
    147     kill "${runner_pid}" 2>/dev/null || true
    148     wait "${runner_pid}" || true
    149   fi
    150   if [[ -n "${degraded_runner_pid:-}" ]] && kill -0 "${degraded_runner_pid}" 2>/dev/null; then
    151     kill "${degraded_runner_pid}" 2>/dev/null || true
    152     wait "${degraded_runner_pid}" || true
    153   fi
    154   rm -rf "${tmp_root}"
    155 }
    156 trap cleanup EXIT
    157 
    158 runtime_mode="localhost-dev"
    159 nostr_relay_urls="${RADROOTS_APP_NOSTR_RELAY_URLS:-ws://127.0.0.1:8080}"
    160 local_log_root="${tmp_root}/logs"
    161 structured_log_file="${local_log_root}/apps/local/app/app-macos-native/${date_utc}.jsonl"
    162 latest_log_path="${local_log_root}/apps/local/app/app-macos-native/latest.jsonl"
    163 stdout_file="${local_log_root}/apps/local/app/app-macos-native/raw/stdout.${date_utc}.log"
    164 stderr_file="${local_log_root}/apps/local/app/app-macos-native/raw/stderr.${date_utc}.log"
    165 
    166 RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \
    167 RADROOTS_APP_NOSTR_RELAY_URLS="${nostr_relay_urls}" \
    168 RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" \
    169 RADROOTS_APP_HOST_BUNDLE_PATH="${app_path}" \
    170 RADROOTS_APP_HOST_STARTUP_ATTEMPTS="${startup_wait_attempts}" \
    171 "${script_dir}/run_host.sh" &
    172 runner_pid="$!"
    173 
    174 wait_for_log_event "${structured_log_file}" "runtime.launch" "${runner_pid}"
    175 wait_for_log_event "${structured_log_file}" "logging.initialized" "${runner_pid}"
    176 assert_latest_alias "${latest_log_path}"
    177 assert_raw_logs_exist "${stdout_file}" "${stderr_file}"
    178 terminate_runner "${runner_pid}"
    179 runner_pid=""
    180 
    181 degraded_log_root="${tmp_root}/degraded-logs"
    182 degraded_structured_log_file="${degraded_log_root}/apps/local/app/app-macos-native/${date_utc}.jsonl"
    183 degraded_latest_log_path="${degraded_log_root}/apps/local/app/app-macos-native/latest.jsonl"
    184 degraded_stdout_file="${degraded_log_root}/apps/local/app/app-macos-native/raw/stdout.${date_utc}.log"
    185 degraded_stderr_file="${degraded_log_root}/apps/local/app/app-macos-native/raw/stderr.${date_utc}.log"
    186 
    187 env -u HOME \
    188   RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \
    189   RADROOTS_APP_NOSTR_RELAY_URLS="${nostr_relay_urls}" \
    190   RADROOTS_APP_LOCAL_LOG_ROOT="${degraded_log_root}" \
    191   RADROOTS_APP_HOST_BUNDLE_PATH="${app_path}" \
    192   RADROOTS_APP_HOST_STARTUP_ATTEMPTS="${startup_wait_attempts}" \
    193   "${script_dir}/run_host.sh" &
    194 degraded_runner_pid="$!"
    195 
    196 wait_for_log_event "${degraded_structured_log_file}" "runtime.launch" "${degraded_runner_pid}"
    197 wait_for_log_event "${degraded_structured_log_file}" "runtime.degraded" "${degraded_runner_pid}"
    198 wait_for_log_event "${degraded_structured_log_file}" "logging.initialized" "${degraded_runner_pid}"
    199 assert_latest_alias "${degraded_latest_log_path}"
    200 assert_raw_logs_exist "${degraded_stdout_file}" "${degraded_stderr_file}"
    201 grep -q '"startup_issue":"desktop runtime roots require HOME for macos"' "${degraded_structured_log_file}" || {
    202   echo "runtime.degraded did not record the expected startup issue" >&2
    203   exit 1
    204 }
    205 terminate_runner "${degraded_runner_pid}"
    206 degraded_runner_pid=""