|
| 1 | +#!/usr/bin/env bats |
| 2 | + |
| 3 | +# Stubbed UUID returned by the cat shim when create-uuid.sh reads |
| 4 | +# /proc/sys/kernel/random/uuid. Lets generation tests assert exact equality |
| 5 | +# instead of just regex shape. |
| 6 | +STUB_UUID="11111111-2222-3333-4444-555555555555" |
| 7 | +VALID_UUID_A="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" |
| 8 | +VALID_UUID_B="bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" |
| 9 | +VALID_UUID_C="cccccccc-cccc-cccc-cccc-cccccccccccc" |
| 10 | + |
| 11 | +setup() { |
| 12 | + SCRIPT="$BATS_TEST_DIRNAME/../create-uuid.sh" |
| 13 | + HELPER="$BATS_TEST_DIRNAME/../scripts/lib/install-update-common.sh" |
| 14 | + ROOT_DIR="$(mktemp -d)" |
| 15 | + STUB_DIR="$ROOT_DIR/bin" |
| 16 | + mkdir -p "$STUB_DIR" |
| 17 | + |
| 18 | + # Resolve the same path variables the script does so tests don't hardcode |
| 19 | + # them. |
| 20 | + export AIRPLANES_ROOT="$ROOT_DIR" |
| 21 | + # shellcheck source=../scripts/lib/install-update-common.sh |
| 22 | + source "$HELPER" |
| 23 | + airplanes_init_paths |
| 24 | + |
| 25 | + # Determinism: replace generate_uuid's two `sleep 0.$RANDOM` waits with |
| 26 | + # no-ops, and short-circuit the /proc UUID read to a known value. cat is |
| 27 | + # stubbed for that one path and delegates everything else to /bin/cat. |
| 28 | + cat > "$STUB_DIR/sleep" <<'SH' |
| 29 | +#!/usr/bin/env bash |
| 30 | +exit 0 |
| 31 | +SH |
| 32 | + chmod +x "$STUB_DIR/sleep" |
| 33 | + |
| 34 | + cat > "$STUB_DIR/cat" <<SH |
| 35 | +#!/usr/bin/env bash |
| 36 | +if [[ "\$1" == "/proc/sys/kernel/random/uuid" ]]; then |
| 37 | + printf '%s\\n' "$STUB_UUID" |
| 38 | + exit 0 |
| 39 | +fi |
| 40 | +exec /bin/cat "\$@" |
| 41 | +SH |
| 42 | + chmod +x "$STUB_DIR/cat" |
| 43 | +} |
| 44 | + |
| 45 | +teardown() { |
| 46 | + rm -rf "$ROOT_DIR" |
| 47 | +} |
| 48 | + |
| 49 | +# Run create-uuid.sh with the stub PATH and AIRPLANES_BUILD_MODE explicitly |
| 50 | +# unset so an inherited shell value never silently routes a non-build-mode |
| 51 | +# test through the skip branch. |
| 52 | +run_create_uuid() { |
| 53 | + run env -u AIRPLANES_BUILD_MODE \ |
| 54 | + PATH="$STUB_DIR:/usr/bin:/bin" \ |
| 55 | + AIRPLANES_ROOT="$ROOT_DIR" \ |
| 56 | + bash "$SCRIPT" "$@" |
| 57 | +} |
| 58 | + |
| 59 | +write_uuid_source() { |
| 60 | + local file="$1" |
| 61 | + local content="$2" |
| 62 | + mkdir -p "$(dirname "$file")" |
| 63 | + printf '%s\n' "$content" > "$file" |
| 64 | +} |
| 65 | + |
| 66 | +file_mode() { |
| 67 | + stat -c '%a' "$1" |
| 68 | +} |
| 69 | + |
| 70 | +@test "--build-mode skips per-device generation and leaves source files untouched" { |
| 71 | + write_uuid_source "$FEEDER_ID_FILE" "garbage-not-a-uuid" |
| 72 | + write_uuid_source "$LEGACY_UUID_FILE" "$VALID_UUID_A" |
| 73 | + write_uuid_source "$BOOT_UUID_FILE" "$VALID_UUID_B" |
| 74 | + |
| 75 | + run_create_uuid --build-mode |
| 76 | + |
| 77 | + [ "$status" -eq 0 ] |
| 78 | + [[ "$output" == *"Build mode: skipping"* ]] |
| 79 | + [ "$(cat "$FEEDER_ID_FILE")" = "garbage-not-a-uuid" ] |
| 80 | + [ "$(cat "$LEGACY_UUID_FILE")" = "$VALID_UUID_A" ] |
| 81 | + [ "$(cat "$BOOT_UUID_FILE")" = "$VALID_UUID_B" ] |
| 82 | + [ ! -L "$LEGACY_UUID_FILE" ] |
| 83 | +} |
| 84 | + |
| 85 | +@test "generates a new UUID when no source file exists" { |
| 86 | + run_create_uuid |
| 87 | + |
| 88 | + [ "$status" -eq 0 ] |
| 89 | + [ -f "$FEEDER_ID_FILE" ] |
| 90 | + [ "$(cat "$FEEDER_ID_FILE")" = "$STUB_UUID" ] |
| 91 | + [ "$(file_mode "$FEEDER_ID_FILE")" = "644" ] |
| 92 | + [ -L "$LEGACY_UUID_FILE" ] |
| 93 | + [[ "$output" == *"New Feeder ID: $STUB_UUID"* ]] |
| 94 | + # write_feeder_id uses "$FEEDER_ID_FILE.$$" as a temp before mv -f. After a |
| 95 | + # successful rename, no feeder-id.* siblings should remain. |
| 96 | + ! ls "$ETC_AIRPLANES"/feeder-id.* >/dev/null 2>&1 |
| 97 | +} |
| 98 | + |
| 99 | +@test "reuses a valid existing UUID from FEEDER_ID_FILE" { |
| 100 | + write_uuid_source "$FEEDER_ID_FILE" "$VALID_UUID_A" |
| 101 | + |
| 102 | + run_create_uuid |
| 103 | + |
| 104 | + [ "$status" -eq 0 ] |
| 105 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_A" ] |
| 106 | + [[ "$output" == *"Using existing valid Feeder ID ($VALID_UUID_A) from $FEEDER_ID_FILE"* ]] |
| 107 | +} |
| 108 | + |
| 109 | +@test "reuses LEGACY_UUID_FILE and replaces it with a symlink to FEEDER_ID_FILE" { |
| 110 | + write_uuid_source "$LEGACY_UUID_FILE" "$VALID_UUID_A" |
| 111 | + [ ! -L "$LEGACY_UUID_FILE" ] |
| 112 | + |
| 113 | + run_create_uuid |
| 114 | + |
| 115 | + [ "$status" -eq 0 ] |
| 116 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_A" ] |
| 117 | + [ -L "$LEGACY_UUID_FILE" ] |
| 118 | + [ "$(readlink "$LEGACY_UUID_FILE")" = "../../../../etc/airplanes/feeder-id" ] |
| 119 | +} |
| 120 | + |
| 121 | +@test "reuses BOOT_UUID_FILE as the lowest-priority fallback" { |
| 122 | + write_uuid_source "$BOOT_UUID_FILE" "$VALID_UUID_A" |
| 123 | + |
| 124 | + run_create_uuid |
| 125 | + |
| 126 | + [ "$status" -eq 0 ] |
| 127 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_A" ] |
| 128 | + [[ "$output" == *"from $BOOT_UUID_FILE"* ]] |
| 129 | +} |
| 130 | + |
| 131 | +@test "FEEDER_ID_FILE wins over LEGACY_UUID_FILE and BOOT_UUID_FILE" { |
| 132 | + write_uuid_source "$FEEDER_ID_FILE" "$VALID_UUID_A" |
| 133 | + write_uuid_source "$LEGACY_UUID_FILE" "$VALID_UUID_B" |
| 134 | + write_uuid_source "$BOOT_UUID_FILE" "$VALID_UUID_C" |
| 135 | + |
| 136 | + run_create_uuid |
| 137 | + |
| 138 | + [ "$status" -eq 0 ] |
| 139 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_A" ] |
| 140 | +} |
| 141 | + |
| 142 | +@test "invalid FEEDER_ID_FILE falls through to LEGACY_UUID_FILE" { |
| 143 | + write_uuid_source "$FEEDER_ID_FILE" "not-a-uuid-at-all" |
| 144 | + write_uuid_source "$LEGACY_UUID_FILE" "$VALID_UUID_B" |
| 145 | + |
| 146 | + run_create_uuid |
| 147 | + |
| 148 | + [ "$status" -eq 0 ] |
| 149 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_B" ] |
| 150 | + [[ "$output" == *"WARNING: Data in UUID file $FEEDER_ID_FILE was invalid"* ]] |
| 151 | +} |
| 152 | + |
| 153 | +@test "invalid FEEDER_ID_FILE and LEGACY_UUID_FILE fall through to BOOT_UUID_FILE" { |
| 154 | + write_uuid_source "$FEEDER_ID_FILE" "garbage-1" |
| 155 | + write_uuid_source "$LEGACY_UUID_FILE" "garbage-2" |
| 156 | + write_uuid_source "$BOOT_UUID_FILE" "$VALID_UUID_C" |
| 157 | + |
| 158 | + run_create_uuid |
| 159 | + |
| 160 | + [ "$status" -eq 0 ] |
| 161 | + [ "$(cat "$FEEDER_ID_FILE")" = "$VALID_UUID_C" ] |
| 162 | + [[ "$output" == *"WARNING: Data in UUID file $FEEDER_ID_FILE was invalid"* ]] |
| 163 | + [[ "$output" == *"WARNING: Data in UUID file $LEGACY_UUID_FILE was invalid"* ]] |
| 164 | +} |
| 165 | + |
| 166 | +@test "invalid in every source triggers fresh generation with the stubbed UUID" { |
| 167 | + write_uuid_source "$FEEDER_ID_FILE" "garbage-1" |
| 168 | + write_uuid_source "$LEGACY_UUID_FILE" "garbage-2" |
| 169 | + write_uuid_source "$BOOT_UUID_FILE" "garbage-3" |
| 170 | + |
| 171 | + run_create_uuid |
| 172 | + |
| 173 | + [ "$status" -eq 0 ] |
| 174 | + [ "$(cat "$FEEDER_ID_FILE")" = "$STUB_UUID" ] |
| 175 | + [[ "$output" == *"WARNING: Data in UUID file $FEEDER_ID_FILE was invalid"* ]] |
| 176 | + [[ "$output" == *"WARNING: Data in UUID file $LEGACY_UUID_FILE was invalid"* ]] |
| 177 | + [[ "$output" == *"WARNING: Data in UUID file $BOOT_UUID_FILE was invalid"* ]] |
| 178 | + [[ "$output" == *"No valid Feeder ID found"* ]] |
| 179 | +} |
| 180 | + |
| 181 | +@test "normalize_uuid strips uppercase and surrounding braces" { |
| 182 | + write_uuid_source "$FEEDER_ID_FILE" "{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}" |
| 183 | + |
| 184 | + run_create_uuid |
| 185 | + |
| 186 | + [ "$status" -eq 0 ] |
| 187 | + [ "$(cat "$FEEDER_ID_FILE")" = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" ] |
| 188 | +} |
| 189 | + |
| 190 | +@test "normalize_uuid is permissive: embedded braces are stripped (current behavior)" { |
| 191 | + # tr -d '{}' is unanchored, so a stray brace anywhere in the source gets |
| 192 | + # silently removed and the result still passes valid_uuid. Locked in as a |
| 193 | + # behavior-documenting test, not an endorsement. |
| 194 | + write_uuid_source "$FEEDER_ID_FILE" "aaaa{aaaa-bbbb-cccc-dddd-eeeeeeeeeeee" |
| 195 | + |
| 196 | + run_create_uuid |
| 197 | + |
| 198 | + [ "$status" -eq 0 ] |
| 199 | + [ "$(cat "$FEEDER_ID_FILE")" = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" ] |
| 200 | +} |
0 commit comments