diff --git a/hack/bats b/hack/bats index e416f82d15..505b890440 100755 --- a/hack/bats +++ b/hack/bats @@ -12,7 +12,7 @@ $0 is a wrapper for invoking podman system tests. --root Run only as root --rootless Run only as user (i.e. you) - --remote Run with podman-remote (see below) + --remote Run with podman-remote FILENAME-PATTERN Run only test files that match 'test/system/*name*', e.g. '500' or 'net' will match 500-networking.bats. @@ -36,16 +36,6 @@ By default, tests ./bin/podman. To test a different podman, do: \$ env PODMAN=/abs/path/to/podman $0 .... -To test podman-remote, start your own servers (root and rootless) via: - - \$ bin/podman system service --timeout=0 & - \$ sudo !! - -...then invoke this script with --remote. (This script can't start the -servers, because we can sudo *starting* the service but can't sudo -stopping it: by the time the bats tests finish, the sudo timeout will -have expired. We apologize for the inconvenience.) - Examples: \$ $0 220:\"restart cleans up\" @@ -113,13 +103,7 @@ if [[ "$REMOTE" ]]; then if ! [[ $PODMAN =~ -remote ]]; then PODMAN=${PODMAN}-remote fi - - if [[ -n "$TEST_ROOT" ]]; then - sudo $PODMAN info >/dev/null || exit 1 - fi - if [[ -n "$TEST_ROOTLESS" ]]; then - $PODMAN info >/dev/null || exit 1 - fi + export REMOTESYSTEM_TRANSPORT=unix fi # END initialization and command-line arg checking diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 4d7fd57a4c..40b498be78 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -12,6 +12,7 @@ import ( . "github.com/containers/podman/v5/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var pruneImage = fmt.Sprintf(` @@ -601,7 +602,7 @@ var _ = Describe("Podman prune", func() { err := os.WriteFile(containerFilePath, []byte(longBuildImage), 0o755) Expect(err).ToNot(HaveOccurred()) - build := podmanTest.Podman([]string{"build", "-f", containerFilePath, "-t", "podmanleaker"}) + build := podmanTest.Podman([]string{"build", "--network=none", "-f", containerFilePath, "-t", "podmanleaker"}) // Build will never finish so let's wait for build to ask for SIGKILL to simulate a failed build that leaves stage containers. matchedOutput := false for range 900 { @@ -616,6 +617,10 @@ var _ = Describe("Podman prune", func() { Fail("Did not match special string in podman build") } + // kill is async, wait for process exit here and make sure it was killed (137). + build.WaitWithDefaultTimeout() + Expect(build).To(Exit(137)) + // Check Intermediate image of stage container none := podmanTest.Podman([]string{"images", "-a"}) none.WaitWithDefaultTimeout() diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats index 630f4d016e..b19eb88d61 100644 --- a/test/system/520-checkpoint.bats +++ b/test/system/520-checkpoint.bats @@ -22,15 +22,17 @@ function setup() { skip "checkpoint does not work rootless" fi + basic_setup + + # Note basic_setup defines $PODMAN_RUNTIME so this must be after it + # As of 2024-05, crun on Debian is not built with criu support: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1008249 - runtime=$(podman_runtime) + runtime="$PODMAN_RUNTIME" run $runtime checkpoint --help if [[ $status -ne 0 ]]; then skip "runtime $runtime does not support checkpoint/restore" fi - - basic_setup } # bats test_tags=ci:parallel @@ -236,6 +238,12 @@ function setup() { # bats test_tags=ci:parallel @test "podman checkpoint/restore ip and mac handling" { + # Broken only debian as it seems the host's /etc/hosts file keeps changing + # which causes false positives in the before/after restore comparison. + OS_RELEASE_ID="${OS_RELEASE_ID:-$(source /etc/os-release; echo $ID)}" + if [[ "$OS_RELEASE_ID" == "debian" ]]; then + skip "Test flakes on debian in CI" + fi # Refer to https://github.com/containers/podman/issues/16666#issuecomment-1337860545 # for the correct behavior, this should cover all cases listed there. local netname="net-$(safename)" diff --git a/test/system/700-artifact.bats b/test/system/700-artifact.bats deleted file mode 100644 index 19116f3083..0000000000 --- a/test/system/700-artifact.bats +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bats -*- bats -*- -# -# Tests for podman artifact functionality -# - -load helpers - -function setup() { - basic_setup -} - -function teardown() { - basic_teardown -} - -# Helper function to create a test artifact file -create_test_file() { - local size=${1:-1024} - local filename=$(mktemp --tmpdir="${PODMAN_TMPDIR}" artifactfile.XXXXXX) - dd if=/dev/urandom of="$filename" bs=1 count="$size" 2>/dev/null - echo "$filename" -} - -# bats test_tags=ci:parallel -@test "podman artifact add --replace basic functionality" { - local artifact_name="localhost/test/replace-artifact" - local file1 file2 - - file1=$(create_test_file 1024) - file2=$(create_test_file 2048) - - # Add initial artifact - run_podman artifact add "$artifact_name" "$file1" - local first_digest="$output" - - # Verify initial artifact exists - run_podman artifact inspect "$artifact_name" - - # Replace with different file - run_podman artifact add --replace "$artifact_name" "$file2" - local second_digest="$output" - - # Verify artifact was replaced (different digest) - assert "$first_digest" != "$second_digest" "Replace should create different digest" - - # Verify artifact still exists and is accessible - run_podman artifact inspect "$artifact_name" - - # Cleanup - run_podman artifact rm "$artifact_name" - rm -f "$file1" "$file2" -} - -# bats test_tags=ci:parallel -@test "podman artifact add --replace nonexistent artifact" { - local artifact_name="localhost/test/nonexistent-artifact" - local file1 - - file1=$(create_test_file 1024) - - # Using --replace on nonexistent artifact should succeed - run_podman artifact add --replace "$artifact_name" "$file1" - - # Verify artifact was created - run_podman artifact inspect "$artifact_name" - - # Cleanup - run_podman artifact rm "$artifact_name" - rm -f "$file1" -} - -# bats test_tags=ci:parallel -@test "podman artifact add --replace and --append conflict" { - local artifact_name="localhost/test/conflict-artifact" - local file1 - - file1=$(create_test_file 1024) - - # Using --replace and --append together should fail - run_podman 125 artifact add --replace --append "$artifact_name" "$file1" - assert "$output" =~ "--append and --replace options cannot be used together" - - rm -f "$file1" -} - -# bats test_tags=ci:parallel -@test "podman artifact add --replace with existing artifact" { - local artifact_name="localhost/test/existing-artifact" - local file1 file2 - - file1=$(create_test_file 512) - file2=$(create_test_file 1024) - - # Create initial artifact - run_podman artifact add "$artifact_name" "$file1" - - # Verify initial artifact exists - run_podman artifact inspect "$artifact_name" - - # Adding same name without --replace should fail - run_podman 125 artifact add "$artifact_name" "$file2" - assert "$output" =~ "artifact already exists" - - # Replace should succeed - run_podman artifact add --replace "$artifact_name" "$file2" - - # Verify artifact was replaced - run_podman artifact inspect "$artifact_name" - - # Cleanup - run_podman artifact rm "$artifact_name" - rm -f "$file1" "$file2" -} diff --git a/test/system/701-artifact-created.bats b/test/system/701-artifact-created.bats deleted file mode 100644 index be0c396cba..0000000000 --- a/test/system/701-artifact-created.bats +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bats -*- bats -*- -# -# Tests for podman artifact created date functionality -# - -load helpers - -# Create temporary artifact file for testing -function create_test_file() { - local content="$1" - local filename=$(random_string 12) - local filepath="$PODMAN_TMPDIR/$filename.txt" - echo "$content" > "$filepath" - echo "$filepath" -} - -function setup() { - basic_setup - skip_if_remote "artifacts are not remote" -} - -function teardown() { - run_podman artifact rm --all --ignore || true - basic_teardown -} - -@test "podman artifact inspect shows created date in RFC3339" { - local content="test content for created date" - local testfile=$(create_test_file "$content") - local artifact_name="localhost/test/created-test" - - # Record time before creation (in seconds for comparison) - local before_epoch=$(date +%s) - - # Create artifact - run_podman artifact add $artifact_name "$testfile" - - # Record time after creation (in seconds for comparison) - local after_epoch=$(date +%s) - - # Inspect the artifact - run_podman artifact inspect $artifact_name - local output="$output" - - # Parse the JSON output to get the created annotation - local created_annotation - created_annotation=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]') - - # Verify created annotation exists and is not null - assert "$created_annotation" != "null" "Should have org.opencontainers.image.created annotation" - assert "$created_annotation" != "" "Created annotation should not be empty" - - # Verify it's a valid RFC3339 timestamp by trying to parse it - # Convert to epoch for comparison - local created_epoch - created_epoch=$(date -d "$created_annotation" +%s 2>/dev/null) - - # Verify parsing succeeded - assert "$?" -eq 0 "Created timestamp should be valid RFC3339 format" - - # Verify timestamp is within reasonable bounds - assert "$created_epoch" -ge "$before_epoch" "Created time should be after before_epoch" - assert "$created_epoch" -le "$after_epoch" "Created time should be before after_epoch" - - # Clean up - rm -f "$testfile" -} - -@test "podman artifact append preserves original created date" { - local content1="initial content" - local content2="appended content" - local testfile1=$(create_test_file "$content1") - local testfile2=$(create_test_file "$content2") - local artifact_name="localhost/test/append-test" - - # Create initial artifact - run_podman artifact add $artifact_name "$testfile1" - - # Get the original created timestamp - run_podman artifact inspect $artifact_name - local original_created - original_created=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]') - - # Wait a bit to ensure timestamps would differ if created new - sleep 1 - - # Append to artifact - run_podman artifact add --append $artifact_name "$testfile2" - - # Get the created timestamp after append - run_podman artifact inspect $artifact_name - local current_created - current_created=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]') - - # Verify the created timestamp is preserved - assert "$current_created" = "$original_created" "Created timestamp should be preserved during append" - - # Verify we have 2 layers now - local layer_count - layer_count=$(echo "$output" | jq '.Manifest.layers | length') - assert "$layer_count" -eq 2 "Should have 2 layers after append" - - # Clean up - rm -f "$testfile1" "$testfile2" -} - -# vim: filetype=sh diff --git a/test/system/702-artifact-created.bats b/test/system/702-artifact-created.bats deleted file mode 100644 index ffa10d4f25..0000000000 --- a/test/system/702-artifact-created.bats +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env bats -*- bats -*- -# -# Tests for podman artifact created date functionality -# - -load helpers - -# Create temporary artifact file for testing -function create_test_file() { - local content="$1" - local filename=$(random_string 12) - local filepath="$PODMAN_TMPDIR/$filename.txt" - echo "$content" > "$filepath" - echo "$filepath" -} - -function setup() { - basic_setup - skip_if_remote "artifacts are not remote" -} - -function teardown() { - run_podman artifact rm --all --ignore || true - basic_teardown -} - -@test "podman artifact inspect shows created date in RFC3339 format" { - local content="test content for created date" - local testfile1=$(create_test_file "$content") - local artifact_name="localhost/test/created-test" - local content2="appended content" - local testfile2=$(create_test_file "$content2") - - # Record time before creation (in seconds for comparison) - local before_epoch=$(date +%s) - - # Create artifact - run_podman artifact add $artifact_name "$testfile1" - - # Record time after creation (in seconds for comparison) - local after_epoch=$(date +%s) - after_epoch=$((after_epoch + 1)) - - # Inspect the artifact - run_podman artifact inspect $artifact_name - local output="$output" - - # Parse the JSON output to get the created annotation - local created_annotation - created_annotation=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]') - - # Verify created annotation exists and is not null - assert "$created_annotation" != "null" "Should have org.opencontainers.image.created annotation" - assert "$created_annotation" != "" "Created annotation should not be empty" - - # Verify it's a valid RFC3339 timestamp by trying to parse it - # Convert to epoch for comparison - local created_epoch - created_epoch=$(date -d "$created_annotation" +%s 2>/dev/null) - - # Verify parsing succeeded - assert "$?" -eq 0 "Created timestamp should be valid RFC3339 format" - - # Verify timestamp is within reasonable bounds - assert "$created_epoch" -ge "$before_epoch" "Created time should be after before_epoch" - assert "$created_epoch" -le "$after_epoch" "Created time should be before after_epoch" - - # Wait a bit to ensure timestamps would differ if created new - sleep 1 - - # Append to artifact - run_podman artifact add --append $artifact_name "$testfile2" - - # Get the created timestamp after append - run_podman artifact inspect $artifact_name - local current_created - current_created=$(echo "$output" | jq -r '.Manifest.annotations["org.opencontainers.image.created"]') - - # Verify the created timestamp is preserved - assert "$current_created" = "$created_annotation" "Created timestamp should be preserved during append" - - # Verify we have 2 layers now - local layer_count - layer_count=$(echo "$output" | jq '.Manifest.layers | length') - assert "$layer_count" -eq 2 "Should have 2 layers after append" - - # Clean up - rm -f "$testfile1" "$testfile2" -} - -# vim: filetype=sh diff --git a/test/system/702-artifact.bats b/test/system/702-artifact.bats new file mode 100644 index 0000000000..df23645d27 --- /dev/null +++ b/test/system/702-artifact.bats @@ -0,0 +1,155 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Tests for podman artifact created date functionality +# + +load helpers + +# FIXME #27264: Artifact store does not seem to work properly with concurrent access. Do not the ci:parallel tags here! + +# Create temporary artifact file for testing +function create_test_file() { + local content="$(random_string 100)" + local filename=$(random_string 12) + local filepath="$PODMAN_TMPDIR/$filename.txt" + echo "$content" > "$filepath" + echo "$filepath" +} + +function teardown() { + run_podman artifact rm --all --ignore + basic_teardown +} + +@test "podman artifact inspect shows created date in RFC3339 format" { + local testfile1=$(create_test_file) + local artifact_name="localhost/test/created-test" + local testfile2=$(create_test_file) + + # Record time before creation (in nanoseconds for comparison) + local before_epoch=$(date +%s%N) + + # Create artifact + run_podman artifact add $artifact_name "$testfile1" + + # Record time after creation + local after_epoch=$(date +%s%N) + + # Inspect the artifact + run_podman artifact inspect --format '{{index .Manifest.Annotations "org.opencontainers.image.created" }}' $artifact_name + local created_annotation="$output" + assert "$created_annotation" != "" "Created annotation should not be empty" + + # Verify it's a valid RFC3339 timestamp by trying to parse it + # Convert to epoch for comparison + local created_epoch=$(date -d "$created_annotation" +%s%N 2>/dev/null) + + # Verify parsing succeeded + assert "$?" -eq 0 "Created timestamp should be valid RFC3339 format" + + # Verify timestamp is within reasonable bounds + assert "$created_epoch" -ge "$before_epoch" "Created time should be after before_epoch" + assert "$created_epoch" -le "$after_epoch" "Created time should be before after_epoch" + + # Append to artifact + run_podman artifact add --append $artifact_name "$testfile2" + + # Get the created timestamp after append + run_podman artifact inspect --format '{{index .Manifest.Annotations "org.opencontainers.image.created" }}\n{{len .Manifest.Layers}}' $artifact_name + local current_created="${lines[0]}" + local layer_count="${lines[1]}" + + # Verify the created timestamp is preserved + assert "$current_created" = "$created_annotation" "Created timestamp should be preserved during append" + + # Verify we have 2 layers now + assert "$layer_count" -eq 2 "Should have 2 layers after append" + + run_podman artifact rm "$artifact_name" +} + + +@test "podman artifact add --replace basic functionality" { + local artifact_name="localhost/test/replace-artifact" + local file1 file2 + + file1=$(create_test_file) + file2=$(create_test_file) + + # Add initial artifact + run_podman artifact add "$artifact_name" "$file1" + local first_digest="$output" + + # Verify initial artifact exists + run_podman artifact inspect "$artifact_name" + + # Replace with different file + run_podman artifact add --replace "$artifact_name" "$file2" + local second_digest="$output" + + # Verify artifact was replaced (different digest) + assert "$first_digest" != "$second_digest" "Replace should create different digest" + + # Verify artifact still exists and is accessible + run_podman artifact inspect "$artifact_name" + + # Cleanup + run_podman artifact rm "$artifact_name" +} + +@test "podman artifact add --replace nonexistent artifact" { + local artifact_name="localhost/test/nonexistent-artifact" + local file1 + + file1=$(create_test_file) + + # Using --replace on nonexistent artifact should succeed + run_podman artifact add --replace "$artifact_name" "$file1" + + # Verify artifact was created + run_podman artifact inspect "$artifact_name" + + # Cleanup + run_podman artifact rm "$artifact_name" +} + +@test "podman artifact add --replace and --append conflict" { + local artifact_name="localhost/test/conflict-artifact" + local file1 + + file1=$(create_test_file) + + # Using --replace and --append together should fail + run_podman 125 artifact add --replace --append "$artifact_name" "$file1" + assert "$output" =~ "--append and --replace options cannot be used together" +} + +@test "podman artifact add --replace with existing artifact" { + local artifact_name="localhost/test/existing-artifact" + local file1 file2 + + file1=$(create_test_file) + file2=$(create_test_file) + + # Create initial artifact + run_podman artifact add "$artifact_name" "$file1" + + # Verify initial artifact exists + run_podman artifact inspect "$artifact_name" + + # Adding same name without --replace should fail + run_podman 125 artifact add "$artifact_name" "$file2" + assert "$output" =~ "artifact already exists" + + # Replace should succeed + run_podman artifact add --replace "$artifact_name" "$file2" + + # Verify artifact was replaced + run_podman artifact inspect "$artifact_name" + + # Cleanup + run_podman artifact rm "$artifact_name" +} + + +# vim: filetype=sh diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 5abfe872d3..d6bfa31b32 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -185,6 +185,9 @@ function basic_setup() { # ancient BATS (v1.1) in RHEL gating tests.) PODMAN_TMPDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-/tmp} podman_bats.XXXXXX) + PODMAN_CMD=("${PODMAN}") + add_podman_args PODMAN_CMD + # runtime is not likely to change if [[ -z "$PODMAN_RUNTIME" ]]; then PODMAN_RUNTIME=$(podman_runtime) @@ -208,9 +211,6 @@ function basic_setup() { # idea being that a large number of failures can show patterns. ASSERTION_FAILURES= immediate-assertion-failures - - PODMAN_CMD=("${PODMAN}") - add_podman_args PODMAN_CMD } # bail-now is how we terminate a test upon assertion failure. @@ -560,7 +560,7 @@ function run_podman() { # stdout is only emitted upon error; this printf is to help in debugging - printf "\n%s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" $PODMAN "${podman_args[@]}" "$*" + printf "\n%s %s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" $PODMAN "${podman_args[*]}" "$*" # BATS hangs if a subprocess remains and keeps FD 3 open; this happens # if podman crashes unexpectedly without cleaning up subprocesses. @@ -790,7 +790,7 @@ function selinux_enabled() { function podman_runtime() { # This function is intended to be used as '$(podman_runtime)', i.e. # our caller wants our output. It's unsafe to use run_podman(). - runtime=$($PODMAN $_PODMAN_TEST_OPTS info --format '{{ .Host.OCIRuntime.Name }}' 2>/dev/null) + runtime=$("${PODMAN_CMD[@]}" info --format '{{ .Host.OCIRuntime.Name }}' 2>/dev/null) basename "${runtime:-[null]}" }