Skip to content

Commit b9b9aa6

Browse files
authored
Merge pull request #3969 from jandubois/bats
Use BATS for integration tests
2 parents 37ac1fd + 0ead7b0 commit b9b9aa6

File tree

10 files changed

+302
-0
lines changed

10 files changed

+302
-0
lines changed

.github/workflows/test.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ jobs:
301301
- ../hack/test-templates/test-misc.yaml # TODO: merge net-user-v2 into test-misc
302302
steps:
303303
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
304+
with:
305+
# BATS tests don't expect lima version warnings like:
306+
# msg="treating lima version \"ea336ae\" from \"/Users/runner/.lima-bats/dummy/lima-version\" as very latest release"
307+
fetch-depth: 0
308+
submodules: true
304309
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
305310
with:
306311
go-version: 1.25.x
@@ -319,6 +324,9 @@ jobs:
319324
sudo modprobe kvm
320325
# `sudo usermod -aG kvm $(whoami)` does not take an effect on GHA
321326
sudo chown $(whoami) /dev/kvm
327+
- name: "Run BATS integration tests"
328+
run: make bats
329+
if: matrix.template == '../hack/test-templates/test-misc.yaml'
322330
- name: Install ansible-playbook
323331
run: |
324332
sudo apt-get install -y --no-install-recommends ansible

.gitmodules

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[submodule "hack/bats/lib/bats-core"]
2+
path = hack/bats/lib/bats-core
3+
url = https://github.com/lima-vm/bats-core.git
4+
branch = master
5+
[submodule "hack/bats/lib/bats-file"]
6+
path = hack/bats/lib/bats-file
7+
url = https://github.com/lima-vm/bats-file.git
8+
branch = master
9+
[submodule "hack/bats/lib/bats-assert"]
10+
path = hack/bats/lib/bats-assert
11+
url = https://github.com/lima-vm/bats-assert.git
12+
branch = master
13+
[submodule "hack/bats/lib/bats-support"]
14+
path = hack/bats/lib/bats-support
15+
url = https://github.com/lima-vm/bats-support.git
16+
branch = master

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,10 @@ check-generated:
504504
git diff --exit-code || \
505505
(echo "Please run 'make generate' when making changes to proto files and check-in the generated file changes" && false)
506506

507+
.PHONY: bats
508+
bats: native
509+
PATH=$$PWD/_output/bin:$$PATH ./hack/bats/lib/bats-core/bin/bats --timing ./hack/bats/tests
510+
507511
.PHONY: lint
508512
lint: check-generated
509513
golangci-lint run ./...

hack/bats/helpers/load.bash

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
set -o errexit -o nounset -o pipefail
2+
3+
# Don't run the tests in ~/.lima because they may destroy _config, _templates etc.
4+
export LIMA_HOME=${LIMA_BATS_LIMA_HOME:-$HOME/.lima-bats}
5+
6+
absolute_path() {
7+
(
8+
cd "$1"
9+
pwd
10+
)
11+
}
12+
13+
PATH_BATS_HELPERS=$(absolute_path "$(dirname "${BASH_SOURCE[0]}")")
14+
PATH_BATS_ROOT=$(absolute_path "$PATH_BATS_HELPERS/..")
15+
16+
source "$PATH_BATS_ROOT/lib/bats-support/load.bash"
17+
source "$PATH_BATS_ROOT/lib/bats-assert/load.bash"
18+
source "$PATH_BATS_ROOT/lib/bats-file/load.bash"
19+
20+
bats_require_minimum_version 1.5.0
21+
22+
# If called from foo() this function will call local_foo() if it exist.
23+
call_local_function() {
24+
local func
25+
func="local_${FUNCNAME[1]}"
26+
if [ "$(type -t "$func")" = "function" ]; then
27+
"$func"
28+
fi
29+
}
30+
31+
setup_file() {
32+
if [[ ${CI:-} == true ]]; then
33+
# Without a terminal the output is using TAP formatting, which does not include the filename
34+
local TEST_FILENAME=${BATS_TEST_FILENAME#"$PATH_BATS_ROOT/tests/"}
35+
TEST_FILENAME=${TEST_FILENAME%.bats}
36+
echo "# ===== ${TEST_FILENAME} =====" >&3
37+
fi
38+
call_local_function
39+
}
40+
teardown_file() {
41+
call_local_function
42+
}
43+
setup() {
44+
call_local_function
45+
}
46+
teardown() {
47+
call_local_function
48+
}

hack/bats/lib/bats-assert

Submodule bats-assert added at 3be0fb7

hack/bats/lib/bats-core

Submodule bats-core added at 397c4a5

hack/bats/lib/bats-file

Submodule bats-file added at 0f24d00

hack/bats/lib/bats-support

Submodule bats-support added at 0954abb

hack/bats/tests/preserve-env.bats

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
load "../helpers/load"
2+
3+
NAME=bats
4+
5+
local_setup_file() {
6+
unset LIMA_SHELLENV_ALLOW
7+
unset LIMA_SHELLENV_BLOCK
8+
9+
if [[ -n "${LIMA_BATS_REUSE_INSTANCE:-}" ]]; then
10+
run limactl list --format '{{.Status}}' "$NAME"
11+
[[ $status == 0 ]] && [[ $output == "Running" ]] && return
12+
fi
13+
limactl unprotect "$NAME" || :
14+
limactl delete --force "$NAME" || :
15+
# Make sure that the host agent doesn't inherit file handles 3 or 4.
16+
# Otherwise bats will not finish until the host agent exits.
17+
limactl start --yes --name "$NAME" template://default 3>&- 4>&-
18+
}
19+
20+
local_teardown_file() {
21+
if [[ -z "${LIMA_BATS_REUSE_INSTANCE:-}" ]]; then
22+
limactl delete --force "$NAME"
23+
fi
24+
}
25+
26+
local_setup() {
27+
# make sure changes from previous tests are removed
28+
limactl shell "$NAME" sh -c '[ ! -f ~/.bash_profile ] || sed -i -E "/^export (FOO|BAR|SSH_)/d" ~/.bash_profile'
29+
}
30+
31+
@test 'there are no FOO*, BAR*, or SSH_FOO* variables defined in the VM' {
32+
# just to confirm because the other tests depend on these being unused
33+
run -0 limactl shell "$NAME" printenv
34+
refute_line --regexp '^FOO'
35+
refute_line --regexp '^BAR'
36+
refute_line --regexp '^SSH_FOO'
37+
}
38+
39+
@test 'environment is not preserved by default' {
40+
export FOO=foo
41+
run -0 limactl shell "$NAME" printenv
42+
refute_line --regexp '^FOO='
43+
}
44+
45+
@test 'environment is preserved with --preserve-env' {
46+
export FOO=foo
47+
run -0 limactl shell --preserve-env "$NAME" printenv
48+
assert_line FOO=foo
49+
}
50+
51+
@test 'profile settings inside the VM take precedence over preserved variables' {
52+
limactl shell "$NAME" sh -c 'echo "export FOO=bar" >>~/.bash_profile'
53+
export FOO=foo
54+
run -0 limactl shell --preserve-env "$NAME" printenv
55+
assert_line FOO=bar
56+
}
57+
58+
@test 'builtin block list is used when LIMA_SHELLENV_BLOCK is not set' {
59+
# default block list includes SSH_*
60+
export SSH_FOO=ssh_foo
61+
run -0 limactl shell --preserve-env "$NAME" printenv
62+
refute_line --regexp '^SSH_FOO='
63+
}
64+
65+
@test 'custom block list replaces builtin block list' {
66+
export LIMA_SHELLENV_BLOCK=FOO
67+
export FOO=foo
68+
export SSH_FOO=foo
69+
run -0 limactl shell --preserve-env "$NAME" printenv
70+
refute_line --regexp '^FOO='
71+
assert_line SSH_FOO=foo
72+
}
73+
74+
@test 'custom block list starting with + appends to builtin block list' {
75+
export LIMA_SHELLENV_BLOCK=+FOO
76+
export FOO=foo
77+
export SSH_FOO=foo
78+
run -0 limactl shell --preserve-env "$NAME" printenv
79+
refute_line --regexp '^FOO='
80+
refute_line --regexp '^SSH_FOO='
81+
}
82+
83+
@test 'block list entries can use * wildcard at the end' {
84+
export LIMA_SHELLENV_BLOCK="FOO*"
85+
export FOO=foo
86+
export FOOBAR=foobar
87+
export BAR=bar
88+
run -0 limactl shell --preserve-env "$NAME" printenv
89+
refute_line --regexp '^FOO'
90+
assert_line BAR=bar
91+
}
92+
93+
@test 'wildcard does only work at the end of the pattern' {
94+
export LIMA_SHELLENV_BLOCK="*FOO"
95+
export FOO=foo
96+
export BARFOO=barfoo
97+
run -0 limactl shell --preserve-env "$NAME" printenv
98+
assert_line FOO=foo
99+
assert_line BARFOO=barfoo
100+
}
101+
102+
@test 'block list can use a , separated list with whitespace ignored' {
103+
export LIMA_SHELLENV_BLOCK="FOO*, , BAR"
104+
export FOO=foo
105+
export FOOBAR=foobar
106+
export BAR=bar
107+
export BARBAZ=barbaz
108+
run -0 limactl shell --preserve-env "$NAME" printenv
109+
refute_line --regexp '^FOO'
110+
refute_line --regexp '^BAR='
111+
assert_line BARBAZ=barbaz
112+
}
113+
114+
@test 'allow list overrides block list but blocks everything else' {
115+
export LIMA_SHELLENV_ALLOW=SSH_FOO
116+
export SSH_FOO=ssh_foo
117+
export SSH_BAR=ssh_bar
118+
export BAR=bar
119+
run -0 limactl shell --preserve-env "$NAME" printenv
120+
assert_line SSH_FOO=ssh_foo
121+
refute_line --regexp '^SSH_BAR='
122+
refute_line --regexp '^BAR='
123+
}
124+
125+
@test 'allow list can use a , separated list with whitespace ignored' {
126+
export LIMA_SHELLENV_ALLOW="FOO*, , BAR"
127+
export FOO=foo
128+
export FOOBAR=foobar
129+
export BAR=bar
130+
export BARBAZ=barbaz
131+
run -0 limactl shell --preserve-env "$NAME" printenv
132+
assert_line FOO=foo
133+
assert_line FOOBAR=foobar
134+
assert_line BAR=bar
135+
refute_line --regexp '^BARBAZ='
136+
}
137+
138+
@test 'setting both allow list and block list generates a warning' {
139+
export LIMA_SHELLENV_ALLOW=FOO
140+
export LIMA_SHELLENV_BLOCK=BAR
141+
export FOO=foo
142+
run -0 --separate-stderr limactl shell --preserve-env "$NAME" printenv FOO
143+
assert_output foo
144+
assert_stderr --regexp 'level=warning msg="Both LIMA_SHELLENV_BLOCK and LIMA_SHELLENV_ALLOW are set'
145+
}
146+
147+
@test 'limactl info includes the default block list' {
148+
run -0 limactl info
149+
run -0 limactl yq '.shellEnvBlock[]' <<<"$output"
150+
assert_line PATH
151+
assert_line "SSH_*"
152+
assert_line USER
153+
}

hack/bats/tests/protect.bats

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
load "../helpers/load"
2+
3+
NAME=dummy
4+
CLONE=clone
5+
NOTEXIST=notexist
6+
7+
local_setup_file() {
8+
for INSTANCE in "$NAME" "$CLONE" "$NOTEXIST"; do
9+
limactl unprotect "$INSTANCE" || :
10+
limactl delete --force "$INSTANCE" || :
11+
done
12+
}
13+
14+
@test 'create dummy instance' {
15+
# needs an image that clonefile() can process; /dev/null doesn't work
16+
limactl create --name "$NAME" - <<<"{images: [location: /etc/profile], disk: 1M}"
17+
}
18+
19+
@test 'protecting a non-existing instance fails' {
20+
run -1 limactl protect "${NOTEXIST}"
21+
assert_output --partial 'failed to inspect instance'
22+
}
23+
24+
@test 'protecting the dummy instance succeeds' {
25+
run -0 limactl protect "$NAME"
26+
assert_output --regexp "Protected \\\\\"$NAME\\\\\""
27+
assert_file_exists "$LIMA_HOME/$NAME/protected"
28+
}
29+
30+
@test 'protecting it again shows a warning, but succeeds' {
31+
run -0 limactl protect "$NAME"
32+
assert_output --partial 'already protected. Skipping'
33+
assert_file_exists "$LIMA_HOME/$NAME/protected"
34+
}
35+
36+
@test 'cloning a protected instance creates an unprotected clone' {
37+
run -0 limactl clone --yes "$NAME" "$CLONE"
38+
# TODO there is currently no output from the clone command, which feels wrong
39+
refute_output
40+
assert_file_not_exists "$LIMA_HOME/$CLONE/protected"
41+
}
42+
43+
@test 'deleting the unprotected clone instance succeeds' {
44+
run -0 limactl delete --force "$CLONE"
45+
assert_output --regexp "Deleted \\\\\"$CLONE\\\\\""
46+
}
47+
48+
@test 'deleting protected dummy instance fails' {
49+
run -1 limactl delete --force "$NAME"
50+
assert_output --partial 'instance is protected'
51+
assert_file_exists "$LIMA_HOME/$NAME/protected"
52+
}
53+
54+
@test 'unprotecting the dummy instance succeeds' {
55+
run -0 limactl unprotect "$NAME"
56+
assert_output --regexp "Unprotected \\\\\"$NAME\\\\\""
57+
assert_file_not_exists "$LIMA_HOME/$NAME/protected"
58+
}
59+
60+
@test 'unprotecting it again shows a warning, but succeeds' {
61+
run -0 limactl unprotect "$NAME"
62+
assert_output --partial "isn't protected. Skipping"
63+
assert_file_not_exists "$LIMA_HOME/$NAME/protected"
64+
}
65+
66+
@test 'deleting unprotected dummy instance succeeds' {
67+
run -0 limactl delete --force "$NAME"
68+
assert_output --regexp "Deleted \\\\\"$NAME\\\\\""
69+
}

0 commit comments

Comments
 (0)