#!/usr/bin/env bash # Sibling test for b32_utils.sh. Asserts the pure helpers behave # as documented: profile parsing populates the PROFILE_* arrays, # the file classifiers split on .test extension correctly, and # the line counter matches the TS "split('\n').length" semantics. # # A minimal in-file harness (no bats dependency): each test calls # `assert_eq` which prints PASS/FAIL and increments counters. # Exit 0 if all assertions pass, 1 otherwise. Run from any cwd. SAMA_SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" # shellcheck disable=SC1091 . "$SAMA_SRC_DIR/a31_constants.sh" # shellcheck disable=SC1091 . "$SAMA_SRC_DIR/b32_utils.sh" TESTS_RUN=0 TESTS_FAILED=0 assert_eq() { local expected="$1" actual="$2" label="$3" TESTS_RUN=$((TESTS_RUN + 1)) if [ "$expected" = "$actual" ]; then printf " ok %s\n" "$label" else TESTS_FAILED=$((TESTS_FAILED + 1)) printf " FAIL %s\n expected: %s\n actual: %s\n" "$label" "$expected" "$actual" fi } assert_contains() { local haystack="$1" needle="$2" label="$3" TESTS_RUN=$((TESTS_RUN + 1)) case "$haystack" in *"$needle"*) printf " ok %s\n" "$label" ;; *) TESTS_FAILED=$((TESTS_FAILED + 1)) printf " FAIL %s\n haystack: %s\n needle: %s\n" "$label" "$haystack" "$needle" ;; esac } mkfile() { local content="$1" path="$2" printf "%s" "$content" > "$path" } # Run tests in a temp dir so we don't touch the real repo profile. TMP_DIR="$(mktemp -d)" trap 'rm -rf "$TMP_DIR"' EXIT # — parse_profile ------------------------------------------------- PROFILE_PATH="$TMP_DIR/test.profile.toml" cat > "$PROFILE_PATH" <<'EOF' sama_version = "2.0" profile = "test-profile" extension = ".sh" [layers.0] prefixes = ["a_"] [layers.1] sublayers = [ { name = "core", prefix = "b_" }, ] [layers.2] prefixes = ["c_"] [layers.3] prefixes = ["d_"] EOF parse_profile "$PROFILE_PATH" assert_eq "test-profile" "$PROFILE_NAME" "parse_profile: PROFILE_NAME" assert_eq "2.0" "$PROFILE_SAMA_VERSION" "parse_profile: PROFILE_SAMA_VERSION" assert_eq ".sh" "$PROFILE_EXTENSION" "parse_profile: PROFILE_EXTENSION" assert_eq "4" "${#PROFILE_PREFIXES[@]}" "parse_profile: 4 prefixes" assert_eq "a_" "${PROFILE_PREFIXES[0]}" "parse_profile: layer-0 prefix" assert_eq "b_" "${PROFILE_PREFIXES[1]}" "parse_profile: layer-1 prefix from sublayer" assert_eq "core" "${PROFILE_SUBLAYER_NAMES[1]}" "parse_profile: layer-1 sublayer name" # — file classifiers ---------------------------------------------- PROFILE_EXTENSION=".ts" is_sama_file "src/a31_foo.ts" && r=0 || r=1 assert_eq "0" "$r" "is_sama_file: src/a31_foo.ts" is_sama_file "src/a31_foo.test.ts" && r=0 || r=1 assert_eq "1" "$r" "is_sama_file rejects .test.ts" is_test_file "src/a31_foo.test.ts" && r=0 || r=1 assert_eq "0" "$r" "is_test_file: .test.ts" is_test_file "src/a31_foo.ts" && r=0 || r=1 assert_eq "1" "$r" "is_test_file rejects plain .ts" # — declared_layer ------------------------------------------------ PROFILE_LAYERS=("0" "1" "1" "2" "3") PROFILE_PREFIXES=("a31_" "b32_" "b51_" "c14_" "d21_") PROFILE_SUBLAYER_NAMES=("default" "logic" "render" "io" "handlers") PROFILE_SUBLAYER_INDEXES=("0" "0" "1" "0" "0") result="$(declared_layer "src/b51_render_admin.ts")" assert_eq "1 render 1 b51_" "$result" "declared_layer: b51_ → Layer 1 render" result="$(declared_layer "src/unprefixed.ts")" assert_eq "" "$result" "declared_layer: unprefixed returns empty" # — count_lines --------------------------------------------------- mkfile "a" "$TMP_DIR/one_no_nl.txt" assert_eq "1" "$(count_lines "$TMP_DIR/one_no_nl.txt")" "count_lines: 'a' = 1" mkfile "a\nb\n" "$TMP_DIR/two_with_nl.txt" # printf %s doesn't interpret \n; use printf for real newlines printf "a\nb\n" > "$TMP_DIR/two_with_nl.txt" assert_eq "3" "$(count_lines "$TMP_DIR/two_with_nl.txt")" "count_lines: 'a\\nb\\n' = 3 (matches TS split)" printf "" > "$TMP_DIR/empty.txt" assert_eq "1" "$(count_lines "$TMP_DIR/empty.txt")" "count_lines: empty = 1" # — strip_strings_and_comments ----------------------------------- PROFILE_EXTENSION=".ts" mkfile "const x = \"hello\"; // a comment" "$TMP_DIR/strip.ts" stripped="$(strip_strings_and_comments_file "$TMP_DIR/strip.ts")" assert_contains "$stripped" "const x = " "strip preserves code" # After stripping, "hello" should be whitespace and // ... should be whitespace. case "$stripped" in *"hello"*) TESTS_FAILED=$((TESTS_FAILED + 1)) printf " FAIL strip removes string content\n leaked: %s\n" "$stripped" ;; *) TESTS_RUN=$((TESTS_RUN + 1)) printf " ok strip removes string content\n" ;; esac # — Summary ------------------------------------------------------- echo if [ "$TESTS_FAILED" -eq 0 ]; then printf "b32_utils.test.sh: %d/%d passed ✓\n" "$TESTS_RUN" "$TESTS_RUN" exit 0 else printf "b32_utils.test.sh: %d/%d passed, %d FAILED ✗\n" \ "$((TESTS_RUN - TESTS_FAILED))" "$TESTS_RUN" "$TESTS_FAILED" exit 1 fi