#!/usr/bin/env sh # Offline behavioral checks for deploy/docker/mirror-base-images.sh. set -eu repo_root="$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)" script="$repo_root/deploy/docker/mirror-base-images.sh" test_dir="$(mktemp -d)" case_env="$test_dir/mirror.env" case_log="$test_dir/calls.log" case_out="$test_dir/output.log" copy_count_file="$test_dir/copy-count" cleanup() { rm -f "$test_dir/docker" "$test_dir/sleep" "$case_env" "$case_log" "$case_out" "$copy_count_file" rmdir "$test_dir" } trap cleanup EXIT cat > "$test_dir/docker" <<'EOF' #!/usr/bin/env sh set -eu case "$1 $2 $3" in 'buildx imagetools inspect') if [ "${4:-}" = '--format' ]; then printf 'digest %s\n' "$6" >> "$CASE_LOG" [ "$TEST_BAD_DIGEST" = 0 ] || exit 1 printf 'sha256:%s\n' 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' else printf 'inspect %s\n' "$4" >> "$CASE_LOG" [ "$TEST_EXISTING" = 1 ] fi ;; 'buildx imagetools create') n="$(cat "$COPY_COUNT_FILE")" n="$((n + 1))" printf '%s\n' "$n" > "$COPY_COUNT_FILE" printf 'copy %s\n' "$8" >> "$CASE_LOG" [ "$TEST_COPY_ALWAYS_FAIL" = 0 ] && [ "$n" -gt "$TEST_FAIL_FIRST" ] ;; *) printf 'unexpected docker call: %s\n' "$*" >&2 exit 2 ;; esac EOF cat > "$test_dir/sleep" <<'EOF' #!/usr/bin/env sh printf 'sleep %s\n' "$1" >> "$CASE_LOG" EOF chmod +x "$test_dir/docker" "$test_dir/sleep" fail() { printf 'FAIL: %s\n' "$1" >&2 cat "$case_out" >&2 exit 1 } count_calls() { awk -v kind="$1" '$1 == kind { count++ } END { print count + 0 }' "$case_log" } run_case() { label="$1" TEST_EXISTING="$2" MIRROR_REFRESH="$3" TEST_FAIL_FIRST="$4" TEST_COPY_ALWAYS_FAIL="$5" TEST_BAD_DIGEST="$6" expected_status="$7" export TEST_EXISTING MIRROR_REFRESH TEST_FAIL_FIRST TEST_COPY_ALWAYS_FAIL TEST_BAD_DIGEST : > "$case_log" printf '0\n' > "$copy_count_file" rm -f "$case_env" if REGISTRY=example.test/owner MIRROR_ENV_FILE="$case_env" MIRROR_RETRIES=2 \ CASE_LOG="$case_log" COPY_COUNT_FILE="$copy_count_file" PATH="$test_dir:$PATH" \ sh "$script" > "$case_out" 2>&1; then status=0 else status=$? fi if [ "$expected_status" = success ] && [ "$status" -ne 0 ]; then fail "$label returned $status, expected success" fi if [ "$expected_status" = failure ] && [ "$status" -eq 0 ]; then fail "$label succeeded, expected failure" fi } assert_calls() { kind="$1" expected="$2" actual="$(count_calls "$kind")" [ "$actual" -eq "$expected" ] || fail "expected $expected $kind calls, got $actual" } assert_immutable_refs() { [ -f "$case_env" ] || fail 'mirror env file missing' lines="$(wc -l < "$case_env" | tr -d ' ')" [ "$lines" -eq 6 ] || fail "expected 6 mirror refs, got $lines" if grep -v -E '^BASE_[A-Z_]+=example\.test/owner/evobgp-buildcache@sha256:[a-f0-9]{64}$' "$case_env"; then fail 'mirror env contains mutable or malformed image ref' fi } run_case existing 1 0 0 0 0 success assert_calls copy 0 assert_calls sleep 0 assert_immutable_refs run_case new 0 0 0 0 0 success assert_calls copy 6 assert_calls sleep 0 assert_immutable_refs run_case retry 0 0 1 0 0 success assert_calls copy 7 assert_calls sleep 1 assert_immutable_refs run_case refresh 1 1 0 0 0 success assert_calls copy 6 assert_calls sleep 0 assert_immutable_refs run_case refresh_copy_failure 1 1 0 1 0 failure assert_calls copy 2 assert_calls sleep 1 [ ! -f "$case_env" ] || fail 'failed refresh wrote mirror refs' run_case refresh_digest_failure 1 1 0 0 1 failure assert_calls copy 1 assert_calls sleep 0 [ ! -f "$case_env" ] || fail 'failed digest lookup wrote mirror refs' run_case fallback 0 0 0 1 0 success assert_calls copy 12 assert_calls sleep 6 [ ! -s "$case_env" ] || fail 'fallback wrote stale mirror refs' run_case digest_fallback 1 0 0 0 1 success assert_calls copy 0 assert_calls sleep 0 [ ! -s "$case_env" ] || fail 'digest fallback wrote mutable mirror refs' printf 'mirror-base-images offline tests passed\n'