Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions tests/annotations.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bats
# SUR-1881: annotations.sh — annotations::deprecated forwards args and logs.

setup() {
load 'helpers.bash'
helpers::isolate_home
}

@test "annotations::deprecated forwards args to new function" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include annotations
my_target() { echo \"called:\$*\"; }
annotations::deprecated my_target foo bar
"
[ "$status" -eq 0 ]
[[ "$output" == *"called:foo bar"* ]]
}

@test "annotations::deprecated emits debug log naming the deprecated caller" {
run bash -c "
LOG_LEVEL=3
source '$REPO_ROOT/bash/includer.sh'
@include annotations
my_caller() {
my_target() { :; }
annotations::deprecated my_target
}
my_caller
"
[ "$status" -eq 0 ]
[[ "$output" == *"my_caller"* ]]
[[ "$output" == *"deprecated"* ]]
}

@test "deprecated shim delegates to annotations::deprecated" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include annotations
my_target() { echo \"via-shim:\$*\"; }
deprecated my_target arg1
"
[ "$status" -eq 0 ]
[[ "$output" == *"via-shim:arg1"* ]]
}
30 changes: 30 additions & 0 deletions tests/aws.bats
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,33 @@ setup() {
"
[ "$status" -eq 0 ]
}

@test "aws::is_scan_complete returns 0 when scan status is COMPLETE" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include aws
aws::scan_status() { echo 'COMPLETE'; }
aws::is_scan_complete myrepo mytag
"
[ "$status" -eq 0 ]
}

@test "aws::is_scan_complete returns 1 when scan status is IN_PROGRESS" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include aws
aws::scan_status() { echo 'IN_PROGRESS'; }
aws::is_scan_complete myrepo mytag
"
[ "$status" -ne 0 ]
}

@test "aws::is_scan_complete returns 1 for any non-COMPLETE status" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include aws
aws::scan_status() { echo 'FAILED'; }
aws::is_scan_complete myrepo mytag
"
[ "$status" -ne 0 ]
}
45 changes: 45 additions & 0 deletions tests/changelog.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bats
# SUR-1882: changelog emits section headers for tagged commit history;
# with -l, includes commit URLs when origin is a GitHub remote.

setup() {
load 'helpers.bash'
helpers::isolate_home
helpers::set_git_identity
CHANGELOG="$REPO_ROOT/bash/changelog"
FIXTURE_DIR=$(mktemp -d)
helpers::make_fixture_repo "$FIXTURE_DIR" --tagged
# Add an untagged HEAD commit so git::tagsinhistory does not confuse the
# HEAD decoration with a tag and emits clean v0.1.0/v0.2.0/v0.3.0 names.
(
cd "$FIXTURE_DIR" || exit 1
echo "post" >>README
git add README
git -c commit.gpgsign=false commit -q -m "feat: post-tag change"
)
export FIXTURE_DIR CHANGELOG
}

teardown() {
rm -rf "$FIXTURE_DIR"
}

@test "changelog exits 0 and emits CHANGELOG header" {
run bash -c "cd '$FIXTURE_DIR' && '$CHANGELOG'"
[ "$status" -eq 0 ]
[[ "$output" == *"# CHANGELOG"* ]]
}

@test "changelog emits v0.3.0 and v0.2.0 section headers" {
run bash -c "cd '$FIXTURE_DIR' && '$CHANGELOG'"
[ "$status" -eq 0 ]
[[ "$output" == *"## v0.3.0"* ]]
[[ "$output" == *"## v0.2.0"* ]]
}

@test "changelog -l includes GitHub commit URLs when origin is a GitHub remote" {
git -C "$FIXTURE_DIR" remote add origin "git@github.com:testorg/testrepo.git"
run bash -c "cd '$FIXTURE_DIR' && '$CHANGELOG' -l"
[ "$status" -eq 0 ]
[[ "$output" == *"https://github.com/testorg/testrepo/commit"* ]]
}
27 changes: 27 additions & 0 deletions tests/error.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bats
# SUR-1881: error.sh — error::exit exits 1 with message on stderr.

setup() {
load 'helpers.bash'
helpers::isolate_home
}

@test "error::exit exits 1 with message" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include error
error::exit 'fail msg'
"
[ "$status" -eq 1 ]
[[ "$output" == *"fail msg"* ]]
}

@test "error::exit exits 1 with multi-word message" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include error
error::exit 'something went wrong: code 42'
"
[ "$status" -eq 1 ]
[[ "$output" == *"something went wrong: code 42"* ]]
}
53 changes: 53 additions & 0 deletions tests/find-squashable.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bats
# SUR-1882: find-squashable detects consecutive commits that touch the same
# file set and reports them as squashable candidates.

setup() {
load 'helpers.bash'
helpers::isolate_home
helpers::set_git_identity
SQUASHABLE="$REPO_ROOT/bash/find-squashable"

# Build history designed to trigger "could be squashed" output:
# c0: add file_a.txt (START_FROM — excluded from iteration)
# c1: add file_b.txt (different file set → resets squash run)
# c2: modify file_a.txt \
# c3: modify file_a.txt | three consecutive commits on file_a
# c4: modify file_a.txt /
# find-squashable iterates newest-first (c4, c3, c2, c1). When it reaches
# c1 (file_b.txt ≠ file_a.txt) after the same-file run (c4/c3/c2), it
# fires: "c4 to c2 could be squashed".
FIXTURE_DIR=$(mktemp -d)
(
cd "$FIXTURE_DIR" || exit 1
git init -q -b main .
helpers::set_git_identity
echo "initial" >file_a.txt
git add file_a.txt
git -c commit.gpgsign=false commit -q -m "feat: initial"
touch file_b.txt
git add file_b.txt
git -c commit.gpgsign=false commit -q -m "feat: add file_b"
echo "c1" >>file_a.txt
git add file_a.txt
git -c commit.gpgsign=false commit -q -m "feat: change file_a 1"
echo "c2" >>file_a.txt
git add file_a.txt
git -c commit.gpgsign=false commit -q -m "feat: change file_a 2"
echo "c3" >>file_a.txt
git add file_a.txt
git -c commit.gpgsign=false commit -q -m "feat: change file_a 3"
)
START_HASH=$(git -C "$FIXTURE_DIR" rev-list --reverse HEAD | head -1)
export FIXTURE_DIR START_HASH SQUASHABLE
}

teardown() {
rm -rf "$FIXTURE_DIR"
}

@test "find-squashable reports could be squashed for same-file consecutive commits" {
run bash -c "cd '$FIXTURE_DIR' && '$SQUASHABLE' -s '$START_HASH'"
[ "$status" -eq 0 ]
[[ "$output" == *"could be squashed"* ]]
}
60 changes: 60 additions & 0 deletions tests/fn.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bats
# SUR-1881: fn.sh — fn::if_exists and fn::wrapped dispatch contracts.

setup() {
load 'helpers.bash'
helpers::isolate_home
}

@test "fn::if_exists calls the function when it exists" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include fn
my_fn() { echo called; }
fn::if_exists my_fn
"
[ "$status" -eq 0 ]
[[ "$output" == *"called"* ]]
}

@test "fn::if_exists silently returns 0 when the function does not exist" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include fn
fn::if_exists nonexistent_fn_xyz_123
"
[ "$status" -eq 0 ]
}

@test "fn::if_exists passes additional args to the function" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include fn
my_fn() { echo \"called:\$*\"; }
fn::if_exists my_fn arg1 arg2
"
[ "$status" -eq 0 ]
[[ "$output" == *"called:arg1 arg2"* ]]
}

@test "fn::wrapped calls wrapper with remaining args when wrapper exists" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include fn
my_wrapper() { echo \"wrapper:\$*\"; }
fn::wrapped my_wrapper arg1 arg2
"
[ "$status" -eq 0 ]
[[ "$output" == *"wrapper:arg1 arg2"* ]]
}

@test "fn::wrapped falls through to direct call when wrapper is absent" {
run bash -c "
source '$REPO_ROOT/bash/includer.sh'
@include fn
actual_cmd() { echo \"direct:\$*\"; }
fn::wrapped nonexistent_wrapper_xyz actual_cmd hello
"
[ "$status" -eq 0 ]
[[ "$output" == *"direct:hello"* ]]
}
28 changes: 28 additions & 0 deletions tests/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@ helpers::set_git_identity() {
export GIT_COMMITTER_EMAIL="bats@example.invalid"
}

# helpers::make_fixture_repo <dir> [--tagged]
# Creates a minimal git repo at <dir> with one commit (or three tagged commits
# when --tagged is passed). Calls helpers::set_git_identity internally so
# callers need not do so first.
helpers::make_fixture_repo() {
local dir=${1:?dir required}
local tagged=${2:-}
git init -q -b main "$dir"
(
cd "$dir" || exit 1
helpers::set_git_identity
touch README
git add README
git -c commit.gpgsign=false commit -q -m "feat: initial"
if [[ "$tagged" == "--tagged" ]]; then
git tag v0.1.0
echo "a" >>README
git add README
git -c commit.gpgsign=false commit -q -m "feat: second"
git tag v0.2.0
echo "b" >>README
git add README
git -c commit.gpgsign=false commit -q -m "feat: third"
git tag v0.3.0
fi
)
}

# Source a library by its @include name. Forces a fresh include in the
# current shell so the cksum-keyed dedup guard cannot suppress it.
helpers::source_lib() {
Expand Down
43 changes: 43 additions & 0 deletions tests/pretty-labels.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bats
# SUR-1882: pretty-labels prints one label per line with the resource name
# column-padded, using a stubbed kubectl that returns fixture show-labels output.

setup() {
load 'helpers.bash'
helpers::isolate_home
STUB_BIN=$(mktemp -d)
cat >"$STUB_BIN/kubectl" <<'STUB'
#!/usr/bin/env bash
printf "NAME READY STATUS RESTARTS AGE LABELS\n"
printf "mypod-1 1/1 Running 0 1d app=myapp,tier=frontend\n"
STUB
chmod +x "$STUB_BIN/kubectl"
PATH="$STUB_BIN:$PATH"
unset _kubectl
export STUB_BIN PATH
}

teardown() {
rm -rf "$STUB_BIN"
}

@test "pretty-labels prints resource name on each label line" {
run bash -c "
LOGFILE_DISABLE=true
unset _kubectl
'$REPO_ROOT/bash/pretty-labels' -t pod
"
[ "$status" -eq 0 ]
[[ "$output" == *"mypod-1"* ]]
}

@test "pretty-labels prints one label per line" {
run bash -c "
LOGFILE_DISABLE=true
unset _kubectl
'$REPO_ROOT/bash/pretty-labels' -t pod
"
[ "$status" -eq 0 ]
[[ "$output" == *"app=myapp"* ]]
[[ "$output" == *"tier=frontend"* ]]
}
Loading
Loading