diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bc0f177f..014e45bc 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -12,8 +12,13 @@ jobs: # needed for codecov fetch-depth: 0 - name: Install tools - run: sudo apt-get install -qqy bats + run: | + sudo apt-get install -qqy bats + # Add PPA for CRIU + sudo add-apt-repository ppa:criu/ppa + sudo apt-get update + sudo apt-get install -qqy criu - name: Run make coverage - run: make coverage + run: sudo -E make coverage - name: Run make codecov run: make codecov diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 004c8864..5ffc2254 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,18 +7,19 @@ jobs: runs-on: ubuntu-latest container: image: registry.fedoraproject.org/fedora:latest + options: --privileged steps: - uses: actions/checkout@v3 - name: Install tools - run: sudo dnf -y install ShellCheck bats golang + run: sudo dnf -y install ShellCheck bats golang criu - name: Run make shellcheck run: make shellcheck - name: Run make all run: make all - name: Run make test - run: make test + run: sudo -E make test - name: Run make test-junit - run: make test-junit + run: sudo -E make test-junit - name: Upload Test Results # To display test results from forked repositories they need to # be uploaded and then analyzed. @@ -27,7 +28,7 @@ jobs: with: name: test-results retention-days: 1 - path: junit.xml + path: test/junit.xml - name: Run make install/uninstall run: test/uninstall.sh diff --git a/.gitignore b/.gitignore index 85058235..87ddda7c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ checkpointctl checkpointctl.coverage .coverage junit.xml +test/piggie/piggie +test/test-imgs diff --git a/Makefile b/Makefile index 9a2f9324..ee843f4d 100644 --- a/Makefile +++ b/Makefile @@ -68,14 +68,14 @@ shellcheck: lint: golang-lint shellcheck test: $(NAME) - bats test/*bats + make -C test test-junit: $(NAME) - bats -F junit test/*bats > junit.xml + make -C test test-junit clean coverage: check-go-version $(NAME).coverage mkdir -p $(COVERAGE_PATH) - COVERAGE_PATH=$(COVERAGE_PATH) COVERAGE=1 bats test/*bats + COVERAGE_PATH=$(COVERAGE_PATH) COVERAGE=1 make -C test # Print coverage from this run $(GO) tool covdata percent -i=${COVERAGE_PATH} $(GO) tool covdata textfmt -i=${COVERAGE_PATH} -o ${COVERAGE_PATH}/coverage.out diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000..5dc1ad1f --- /dev/null +++ b/test/Makefile @@ -0,0 +1,26 @@ +CRIU ?= criu +CC ?= gcc + +all: test clean + +test: test-imgs + @echo "Running BATS tests..." + bats checkpointctl.bats + +test-junit: test-imgs + @echo "Running BATS tests with JUnit results..." + bats -F junit checkpointctl.bats > junit.xml + +test-imgs: piggie/piggie + $(eval PID := $(shell piggie/piggie)) + mkdir -p $@ + $(CRIU) dump -v4 -o dump.log -D $@ -t $(PID) + +piggie/piggie: piggie/piggie.c + $(CC) $^ -o $@ + +clean: + @echo "Cleaning up test files..." + @rm -rf test-imgs piggie/piggie + +.PHONY: all test test-junit clean diff --git a/test/checkpointctl.bats b/test/checkpointctl.bats index 8e84a0e1..6146028a 100644 --- a/test/checkpointctl.bats +++ b/test/checkpointctl.bats @@ -1,9 +1,10 @@ if [ -n "$COVERAGE" ]; then export GOCOVERDIR="${COVERAGE_PATH}" - CHECKPOINTCTL="./checkpointctl.coverage" + CHECKPOINTCTL="../checkpointctl.coverage" else - CHECKPOINTCTL="./checkpointctl" + CHECKPOINTCTL="../checkpointctl" fi + TEST_TMP_DIR1="" TEST_TMP_DIR2="" @@ -57,7 +58,7 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and no spec.dump" { - cp test/config.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar @@ -66,7 +67,7 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and empty spec.dump" { - cp test/config.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint touch "$TEST_TMP_DIR1"/spec.dump ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) @@ -76,8 +77,8 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and valid spec.dump and no checkpoint directory" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar [ "$status" -eq 1 ] @@ -85,8 +86,8 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and valid spec.dump and checkpoint directory" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar @@ -95,7 +96,7 @@ function teardown() { } @test "Run checkpointctl show with tar file from containerd with valid config.dump and valid spec.dump and checkpoint directory" { - cp test/config.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint echo "{}" > "$TEST_TMP_DIR1"/status echo "{}" > "$TEST_TMP_DIR1"/spec.dump @@ -106,8 +107,8 @@ function teardown() { } @test "Run checkpointctl show with tar file and --stats and missing stats-dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --stats @@ -116,9 +117,9 @@ function teardown() { } @test "Run checkpointctl show with tar file and --stats and invalid stats-dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1"/stats-dump + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1"/stats-dump mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --stats @@ -127,21 +128,21 @@ function teardown() { } @test "Run checkpointctl show with tar file and --stats and valid stats-dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" - cp test/stats-dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" + cp test-imgs/stats-dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --stats [ "$status" -eq 0 ] [[ ${lines[6]} == *"CRIU dump statistics"* ]] [[ ${lines[8]} == *"MEMWRITE TIME"* ]] - [[ ${lines[10]} == *"446571 us"* ]] + [[ ${lines[10]} =~ [1-9]+" us" ]] } @test "Run checkpointctl show with tar file and --mounts and valid spec.dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --mounts @@ -152,8 +153,8 @@ function teardown() { } @test "Run checkpointctl show with tar file and --mounts and --full-paths and valid spec.dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --mounts --full-paths @@ -164,9 +165,9 @@ function teardown() { } @test "Run checkpointctl show with tar file and --all and valid spec.dump and valid stats-dump" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" - cp test/stats-dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" + cp test-imgs/stats-dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --all @@ -177,12 +178,12 @@ function teardown() { [[ ${lines[11]} == *"/etc/hostname"* ]] [[ ${lines[13]} == *"CRIU dump statistics"* ]] [[ ${lines[15]} == *"MEMWRITE TIME"* ]] - [[ ${lines[17]} == *"446571 us"* ]] + [[ ${lines[17]} =~ [1-9]+" us" ]] } @test "Run checkpointctl show with tar file and missing --mounts/--all and --full-paths" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar --full-paths @@ -191,8 +192,8 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and valid spec.dump (CRI-O) and no checkpoint directory" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump.cri-o "$TEST_TMP_DIR1"/spec.dump + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump.cri-o "$TEST_TMP_DIR1"/spec.dump ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar [ "$status" -eq 1 ] @@ -200,8 +201,8 @@ function teardown() { } @test "Run checkpointctl show with tar file with valid config.dump and valid spec.dump (CRI-O) and checkpoint directory" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump.cri-o "$TEST_TMP_DIR1"/spec.dump + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump.cri-o "$TEST_TMP_DIR1"/spec.dump mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar @@ -210,8 +211,8 @@ function teardown() { } @test "Run checkpointctl show with tar file compressed" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar czf "$TEST_TMP_DIR2"/test.tar.gz . ) checkpointctl show "$TEST_TMP_DIR2"/test.tar.gz @@ -220,8 +221,8 @@ function teardown() { } @test "Run checkpointctl show with tar file corrupted" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar cf "$TEST_TMP_DIR2"/test.tar . ) dd if=/dev/urandom of="$TEST_TMP_DIR2"/test.tar bs=1 count=10 seek=2 conv=notrunc @@ -231,8 +232,8 @@ function teardown() { } @test "Run checkpointctl show with tar file compressed and corrupted" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint ( cd "$TEST_TMP_DIR1" && tar czf "$TEST_TMP_DIR2"/test.tar.gz . ) dd if=/dev/urandom of="$TEST_TMP_DIR2"/test.tar.gz bs=1 count=10 seek=2 conv=notrunc @@ -242,8 +243,8 @@ function teardown() { } @test "Run checkpointctl show with tar file and rootfs-diff tar file" { - cp test/config.dump "$TEST_TMP_DIR1" - cp test/spec.dump "$TEST_TMP_DIR1" + cp data/config.dump "$TEST_TMP_DIR1" + cp data/spec.dump "$TEST_TMP_DIR1" mkdir "$TEST_TMP_DIR1"/checkpoint echo 1 > "$TEST_TMP_DIR1"/test.pid tar -cf "$TEST_TMP_DIR1"/rootfs-diff.tar -C "$TEST_TMP_DIR1" test.pid diff --git a/test/config.dump b/test/data/config.dump similarity index 100% rename from test/config.dump rename to test/data/config.dump diff --git a/test/spec.dump b/test/data/spec.dump similarity index 100% rename from test/spec.dump rename to test/data/spec.dump diff --git a/test/spec.dump.cri-o b/test/data/spec.dump.cri-o similarity index 100% rename from test/spec.dump.cri-o rename to test/data/spec.dump.cri-o diff --git a/test/piggie/piggie.c b/test/piggie/piggie.c new file mode 100644 index 00000000..bcab2138 --- /dev/null +++ b/test/piggie/piggie.c @@ -0,0 +1,61 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#define STKS (4*4096) + +#ifndef CLONE_NEWPID +#define CLONE_NEWPID 0x20000000 +#endif + +static int do_test(void *logf) +{ + int fd, i = 0; + + setsid(); + + close(0); + close(1); + close(2); + + fd = open("/dev/null", O_RDONLY); + if (fd != 0) { + dup2(fd, 0); + close(fd); + } + + fd = open(logf, O_WRONLY | O_TRUNC | O_CREAT, 0600); + dup2(fd, 1); + dup2(fd, 2); + if (fd != 1 && fd != 2) + close(fd); + + while (1) { + sleep(1); + printf("%d\n", i++); + fflush(stdout); + } + + return 0; +} + +int main(int argc, char **argv) +{ + int pid; + void *stk; + + stk = mmap(NULL, STKS, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, 0, 0); + pid = clone(do_test, stk + STKS, SIGCHLD | CLONE_NEWPID, argv[1]); + if (pid < 0) { + fprintf(stderr, "clone() failed: %m\n"); + return 1; + } + printf("%d\n", pid); + + return 0; +} diff --git a/test/stats-dump b/test/stats-dump deleted file mode 100644 index 455fe98b..00000000 Binary files a/test/stats-dump and /dev/null differ