diff --git a/README.md b/README.md index ef7347b..9eebfa4 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,12 @@ are outside `make check`. Neither opens the popup from the toolbar button: both load its page in an ordinary tab, so what the toolbar popup itself adds, its size and its closing when it loses focus, is covered by neither. +Each run builds its image under a tag of its own, `autistmask-e2e-chrome:` or +`autistmask-e2e-firefox:` followed by twelve random hex digits, and removes that +image when it exits, an interrupt included. Two clones can therefore run the +same suite at once without one build taking the other's image away, and no run +leaves an image behind. + ### Chrome (`make test-e2e`) `make test-e2e` builds `dist/chrome/` and drives the **real popup in a real diff --git a/script/test-e2e b/script/test-e2e index 2246905..43a3450 100755 --- a/script/test-e2e +++ b/script/test-e2e @@ -22,13 +22,18 @@ set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" -IMAGE="$("$SCRIPT_DIR/projectname")-e2e-chrome" - -IIDFILE="" +# Each run builds, runs and then removes an image under a tag of its own. +# Under one tag shared by every run, a second clone's build moves the tag +# off this run's image, and the image store can then delete that untagged +# image before or while this run uses it. The tag is random rather than +# $$ because CI jobs share one docker daemon, but each job's container +# numbers its processes from scratch. +IMAGE="$("$SCRIPT_DIR/projectname")-e2e-chrome:$(od -An -N6 -tx1 /dev/urandom | tr -d ' \n')" cleanup() { - if [ -n "$IIDFILE" ]; then - rm -f "$IIDFILE" + # No image to remove when the build failed or was interrupted. + if docker image inspect "$IMAGE" >/dev/null 2>&1; then + docker image rm "$IMAGE" >/dev/null fi } @@ -40,22 +45,15 @@ main() { exit 1 fi - IIDFILE="$(mktemp)" trap cleanup EXIT trap 'cleanup; exit 130' INT TERM echo "Building the Chrome e2e image (extension included)..." # --no-cache: the image build runs make build and its checks, and a # cached layer is a check that did not run. - docker build --no-cache --iidfile "$IIDFILE" -t "$IMAGE" \ - -f tests/e2e/Dockerfile . + docker build --no-cache -t "$IMAGE" -f tests/e2e/Dockerfile . echo "Running e2e suite in the pinned Playwright container..." - # The image is run by ID, not by tag: where two clones of this repo run - # the suite at once, the other build can move the tag between this - # build and this run, and the suite would then silently test the other - # checkout. - # # --ipc=host: Chromium's shared-memory needs more than the default # 64MB /dev/shm or renderers crash. # HOME=/tmp: the image's root home is not a reliable place for the @@ -79,7 +77,7 @@ main() { -e HOME=/tmp \ -e PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 \ -e "E2E_TRACE_NETWORK=${E2E_TRACE_NETWORK:-0}" \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/run.js # Where chrome.storage.local lives, and what moves it: two unpacked loads @@ -95,7 +93,7 @@ main() { docker run --rm \ --ipc=host \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/storagePartition.js } diff --git a/script/test-e2e-firefox b/script/test-e2e-firefox index 892e7e1..6058ba3 100755 --- a/script/test-e2e-firefox +++ b/script/test-e2e-firefox @@ -21,13 +21,13 @@ set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" -IMAGE="$("$SCRIPT_DIR/projectname")-e2e-firefox" - -IIDFILE="" +# A tag of this run's own, as in script/test-e2e, which says why. +IMAGE="$("$SCRIPT_DIR/projectname")-e2e-firefox:$(od -An -N6 -tx1 /dev/urandom | tr -d ' \n')" cleanup() { - if [ -n "$IIDFILE" ]; then - rm -f "$IIDFILE" + # No image to remove when the build failed or was interrupted. + if docker image inspect "$IMAGE" >/dev/null 2>&1; then + docker image rm "$IMAGE" >/dev/null fi } @@ -39,22 +39,15 @@ main() { exit 1 fi - IIDFILE="$(mktemp)" trap cleanup EXIT trap 'cleanup; exit 130' INT TERM echo "Building the pinned Firefox e2e image (extension included)..." # --no-cache: the image build runs make build and its checks, and a # cached layer is a check that did not run. - docker build --no-cache --iidfile "$IIDFILE" -t "$IMAGE" \ - -f tests/e2e/firefox/Dockerfile . + docker build --no-cache -t "$IMAGE" -f tests/e2e/firefox/Dockerfile . echo "Running the Firefox e2e suite..." - # The image is run by ID, not by tag: where two clones of this repo run - # the suite at once, the other build can move the tag between this - # build and this run, and the suite would then silently test the other - # checkout. - # # --shm-size=1g: Firefox needs more than the default 64MB /dev/shm. # --network none: the suite stubs nothing, so this is what keeps the # run offline and deterministic. The extension swallows its own @@ -72,7 +65,7 @@ main() { --shm-size=1g \ --network none \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/firefox/run.js dist/firefox # The install/uninstall/re-install property, against the packaged XPI @@ -85,7 +78,7 @@ main() { --shm-size=1g \ --network none \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/firefox/reinstall.js }