|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# Sourced by test harnesses. Host paths stay separate from paths exported to a |
| 4 | +# native Windows product binary. |
| 5 | +CBM_TEST_RUNTIME_ROOT="" |
| 6 | +CBM_TEST_RUNTIME_DIR_HOST="" |
| 7 | +CBM_TEST_CACHE_DIR_HOST="" |
| 8 | +_CBM_TEST_RUNTIME_CREATED_ROOT="" |
| 9 | +_CBM_TEST_RUNTIME_PRODUCT_RUNTIME="" |
| 10 | +_CBM_TEST_RUNTIME_PRODUCT_CACHE="" |
| 11 | + |
| 12 | +_cbm_test_runtime_error() { |
| 13 | + echo "test-runtime: $*" >&2 |
| 14 | +} |
| 15 | + |
| 16 | +_cbm_test_runtime_discard_partial() { |
| 17 | + local root="$1" parent="$2" name="${1##*/}" |
| 18 | + [[ -n "$root" && "$root" != "$name" && "${root%/*}" == "$parent" && ! -L "$root" ]] || return 0 |
| 19 | + case "$name" in cbmrt.?*|cbmrt-?*) rm -rf -- "$root" >/dev/null 2>&1 || true ;; esac |
| 20 | +} |
| 21 | + |
| 22 | +cbm_test_runtime_init() { |
| 23 | + [[ -z "$_CBM_TEST_RUNTIME_CREATED_ROOT" ]] || |
| 24 | + { _cbm_test_runtime_error "runtime already initialized"; return 1; } |
| 25 | + local platform windows=0 parent root="" runtime_host cache_host |
| 26 | + local product_runtime product_cache helper_dir helper_native root_native |
| 27 | + platform="$(uname -s)" || |
| 28 | + { _cbm_test_runtime_error "cannot identify the host platform"; return 1; } |
| 29 | + case "$platform" in |
| 30 | + MINGW*|MSYS*|CYGWIN*) windows=1 ;; |
| 31 | + Darwin) parent="/private/tmp" ;; |
| 32 | + *) parent="/tmp" ;; |
| 33 | + esac |
| 34 | + if (( windows )); then |
| 35 | + command -v cygpath >/dev/null 2>&1 || |
| 36 | + { _cbm_test_runtime_error "cygpath is required on Windows"; return 1; } |
| 37 | + if [[ -n "${CBM_CI_TEMP_ROOT:-}" ]]; then |
| 38 | + parent="$(cygpath -u "$CBM_CI_TEMP_ROOT")" || |
| 39 | + { _cbm_test_runtime_error "cannot convert CBM_CI_TEMP_ROOT"; return 1; } |
| 40 | + [[ -d "$parent" && ! -L "$parent" ]] || |
| 41 | + { _cbm_test_runtime_error "CBM_CI_TEMP_ROOT is not a real directory"; return 1; } |
| 42 | + root="$(mktemp -d "${parent%/}/cbmrt.XXXXXX")" || |
| 43 | + { _cbm_test_runtime_error "cannot create a private Windows CI root"; return 1; } |
| 44 | + else |
| 45 | + helper_dir="$(CDPATH= cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || return 1 |
| 46 | + helper_native="$(cygpath -w "$helper_dir/ci/new-protected-temp-root.ps1")" || |
| 47 | + { _cbm_test_runtime_error "cannot convert protected-root helper"; return 1; } |
| 48 | + root_native="$(MSYS2_ARG_CONV_EXCL='*' powershell.exe -NoProfile \ |
| 49 | + -ExecutionPolicy Bypass -File "$helper_native" -Prefix 'cbmrt-')" || |
| 50 | + { _cbm_test_runtime_error "protected Windows root creation failed"; return 1; } |
| 51 | + root_native="${root_native//$'\r'/}" |
| 52 | + [[ -n "$root_native" && "$root_native" != *$'\n'* ]] || |
| 53 | + { _cbm_test_runtime_error "protected-root helper returned an invalid path"; return 1; } |
| 54 | + root="$(cygpath -u "$root_native")" || |
| 55 | + { _cbm_test_runtime_error "cannot convert protected Windows root"; return 1; } |
| 56 | + parent="${root%/*}" |
| 57 | + fi |
| 58 | + else |
| 59 | + root="$(mktemp -d "${parent%/}/cbmrt.XXXXXX")" || |
| 60 | + { _cbm_test_runtime_error "cannot create private root under $parent"; return 1; } |
| 61 | + chmod 700 "$root" || { |
| 62 | + _cbm_test_runtime_discard_partial "$root" "$parent" |
| 63 | + _cbm_test_runtime_error "cannot protect runtime root $root" |
| 64 | + return 1 |
| 65 | + } |
| 66 | + fi |
| 67 | + runtime_host="$root/runtime" |
| 68 | + cache_host="$root/cache" |
| 69 | + mkdir "$runtime_host" "$cache_host" || { |
| 70 | + _cbm_test_runtime_discard_partial "$root" "$parent" |
| 71 | + _cbm_test_runtime_error "cannot create runtime/cache directories" |
| 72 | + return 1 |
| 73 | + } |
| 74 | + if (( ! windows )); then |
| 75 | + chmod 700 "$runtime_host" "$cache_host" || { |
| 76 | + _cbm_test_runtime_discard_partial "$root" "$parent" |
| 77 | + _cbm_test_runtime_error "cannot protect runtime/cache directories" |
| 78 | + return 1 |
| 79 | + } |
| 80 | + product_runtime="$runtime_host" |
| 81 | + product_cache="$cache_host" |
| 82 | + else |
| 83 | + product_runtime="$(cygpath -m "$runtime_host")" || { |
| 84 | + _cbm_test_runtime_discard_partial "$root" "$parent" |
| 85 | + _cbm_test_runtime_error "cannot convert the runtime directory" |
| 86 | + return 1 |
| 87 | + } |
| 88 | + product_cache="$(cygpath -m "$cache_host")" || { |
| 89 | + _cbm_test_runtime_discard_partial "$root" "$parent" |
| 90 | + _cbm_test_runtime_error "cannot convert the cache directory" |
| 91 | + return 1 |
| 92 | + } |
| 93 | + fi |
| 94 | + CBM_TEST_RUNTIME_ROOT="$root" |
| 95 | + CBM_TEST_RUNTIME_DIR_HOST="$runtime_host" |
| 96 | + CBM_TEST_CACHE_DIR_HOST="$cache_host" |
| 97 | + _CBM_TEST_RUNTIME_CREATED_ROOT="$root" |
| 98 | + _CBM_TEST_RUNTIME_PRODUCT_RUNTIME="$product_runtime" |
| 99 | + _CBM_TEST_RUNTIME_PRODUCT_CACHE="$product_cache" |
| 100 | + export CBM_RUNTIME_DIR="$product_runtime" CBM_CACHE_DIR="$product_cache" |
| 101 | +} |
| 102 | + |
| 103 | +_cbm_test_runtime_daemon() { |
| 104 | + CBM_RUNTIME_DIR="$_CBM_TEST_RUNTIME_PRODUCT_RUNTIME" \ |
| 105 | + CBM_CACHE_DIR="$_CBM_TEST_RUNTIME_PRODUCT_CACHE" "$1" daemon "$2" |
| 106 | +} |
| 107 | + |
| 108 | +cbm_test_runtime_cleanup() { |
| 109 | + local binary="${1:-}" root="$_CBM_TEST_RUNTIME_CREATED_ROOT" |
| 110 | + local name="${_CBM_TEST_RUNTIME_CREATED_ROOT##*/}" runtime_entry="" active=0 |
| 111 | + [[ -n "$root" ]] || return 0 |
| 112 | + case "$name" in |
| 113 | + cbmrt.?*|cbmrt-?*) ;; |
| 114 | + *) _cbm_test_runtime_error "refusing cleanup for unexpected basename: $name"; return 0 ;; |
| 115 | + esac |
| 116 | + if [[ "$root" != "$CBM_TEST_RUNTIME_ROOT" || -L "$root" ]]; then |
| 117 | + _cbm_test_runtime_error "refusing cleanup for an unexpected runtime root: $root" |
| 118 | + return 0 |
| 119 | + fi |
| 120 | + if [[ ! -e "$root" ]]; then |
| 121 | + _CBM_TEST_RUNTIME_CREATED_ROOT="" |
| 122 | + return 0 |
| 123 | + fi |
| 124 | + if [[ ! -d "$root" || "$CBM_TEST_RUNTIME_DIR_HOST" != "$root/runtime" || |
| 125 | + "$CBM_TEST_CACHE_DIR_HOST" != "$root/cache" || |
| 126 | + -L "$CBM_TEST_RUNTIME_DIR_HOST" || -L "$CBM_TEST_CACHE_DIR_HOST" ]]; then |
| 127 | + _cbm_test_runtime_error "refusing cleanup after runtime path replacement: $root" |
| 128 | + return 0 |
| 129 | + fi |
| 130 | + if [[ -d "$CBM_TEST_RUNTIME_DIR_HOST" ]] && |
| 131 | + ! runtime_entry="$(find "$CBM_TEST_RUNTIME_DIR_HOST" -mindepth 1 -print -quit 2>/dev/null)"; then |
| 132 | + _cbm_test_runtime_error "cannot inspect runtime state; leaving $root" |
| 133 | + return 0 |
| 134 | + fi |
| 135 | + if [[ -n "$runtime_entry" ]]; then |
| 136 | + [[ -x "$binary" ]] || { |
| 137 | + _cbm_test_runtime_error "cannot check the private daemon; leaving $root" |
| 138 | + return 0 |
| 139 | + } |
| 140 | + if _cbm_test_runtime_daemon "$binary" status >/dev/null 2>&1; then |
| 141 | + active=1 |
| 142 | + _cbm_test_runtime_daemon "$binary" stop >/dev/null 2>&1 || true |
| 143 | + for _attempt in {1..50}; do |
| 144 | + if ! _cbm_test_runtime_daemon "$binary" status >/dev/null 2>&1; then |
| 145 | + active=0 |
| 146 | + break |
| 147 | + fi |
| 148 | + sleep 0.1 |
| 149 | + done |
| 150 | + fi |
| 151 | + fi |
| 152 | + if (( active )); then |
| 153 | + _cbm_test_runtime_error "private daemon is still active; leaving $root" |
| 154 | + return 0 |
| 155 | + fi |
| 156 | + if rm -rf -- "$root"; then |
| 157 | + _CBM_TEST_RUNTIME_CREATED_ROOT="" |
| 158 | + else |
| 159 | + _cbm_test_runtime_error "cleanup failed; leaving $root" |
| 160 | + fi |
| 161 | + return 0 |
| 162 | +} |
0 commit comments