From 8617bf78134da699238f0c1756bde023e1711c0a Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 24 Feb 2026 17:10:09 -0400 Subject: [PATCH] WIP Signed-off-by: Juan Cruz Viotti --- .github/actions/sandbox/action.yml | 1 + .github/workflows/ci.yml | 7 ++++ Makefile | 3 ++ test/e2e/chaos/corruptions.hurl | 51 ++++++++++++++++++++++++++ test/sandbox/Dockerfile | 14 ++++++- test/sandbox/one-chaos-community.json | 3 ++ test/sandbox/one-chaos-enterprise.json | 3 ++ test/sandbox/postindex.sh | 50 +++++++++++++++++++++++++ 8 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 test/e2e/chaos/corruptions.hurl create mode 100644 test/sandbox/one-chaos-community.json create mode 100644 test/sandbox/one-chaos-enterprise.json create mode 100755 test/sandbox/postindex.sh diff --git a/.github/actions/sandbox/action.yml b/.github/actions/sandbox/action.yml index 48d21a2a..f1999c36 100644 --- a/.github/actions/sandbox/action.yml +++ b/.github/actions/sandbox/action.yml @@ -8,6 +8,7 @@ inputs: - html - headless - empty + - chaos edition: description: Edition required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 195eafc4..69fd832d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,13 @@ jobs: edition: ${{ matrix.edition.name }} port: 8000 + - name: Sandbox (chaos) + uses: ./.github/actions/sandbox + with: + configuration: chaos + edition: ${{ matrix.edition.name }} + port: 8000 + # Public instance - run: docker build . --file public/Dockerfile --progress plain if: matrix.edition.name == 'enterprise' diff --git a/Makefile b/Makefile index a0e87d74..ca156f6a 100644 --- a/Makefile +++ b/Makefile @@ -67,12 +67,14 @@ test: .PHONY: test-e2e HURL_TESTS += test/e2e/$(SANDBOX_CONFIGURATION)/*.hurl ifneq ($(SANDBOX_CONFIGURATION),empty) +ifneq ($(SANDBOX_CONFIGURATION),chaos) HURL_TESTS += test/e2e/populated/schemas/*.hurl HURL_TESTS += test/e2e/populated/api/common/*.hurl ifeq ($(ENTERPRISE),ON) HURL_TESTS += test/e2e/populated/api/enterprise/*.hurl endif endif +endif test-e2e: $(HURL) --test \ --variable base=$(SANDBOX_URL) \ @@ -93,6 +95,7 @@ sandbox-index: compile $(PREFIX)/bin/sourcemeta-one-index \ $(SANDBOX)/one-$(SANDBOX_CONFIGURATION)-$(EDITION).json \ $(OUTPUT)/sandbox --url $(SANDBOX_URL) --profile + ./test/sandbox/postindex.sh $(SANDBOX_CONFIGURATION) $(EDITION) $(OUTPUT)/sandbox .PHONY: sandbox sandbox: sandbox-index diff --git a/test/e2e/chaos/corruptions.hurl b/test/e2e/chaos/corruptions.hurl new file mode 100644 index 00000000..5acba821 --- /dev/null +++ b/test/e2e/chaos/corruptions.hurl @@ -0,0 +1,51 @@ +# The server MUST NOT crash on corrupted indexed data + +# Corrupted routes.bin node indices +GET {{base}}/self/v1/api/list +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +GET {{base}}/ +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +GET {{base}}/self/v1/api/schemas/metadata/test/schemas/string +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +GET {{base}}/does-not-exist/at/all +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +# Corrupted directory.metapack metadata with wrong types +GET {{base}}/self/v1/api/list +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +# Deleted search.metapack +GET {{base}}/self/v1/api/schemas/search?q=test +[Options] +retry: 3 +retry-interval: 1000 +HTTP * + +# Corrupted locations.metapack with empty object +POST {{base}}/self/v1/api/schemas/trace/test/schemas/string +Content-Type: application/json +[Options] +retry: 3 +retry-interval: 1000 +``` +"hello" +``` +HTTP * diff --git a/test/sandbox/Dockerfile b/test/sandbox/Dockerfile index 9129d9d1..a9f9962d 100644 --- a/test/sandbox/Dockerfile +++ b/test/sandbox/Dockerfile @@ -8,6 +8,11 @@ COPY one-headless-community.json . COPY one-headless-enterprise.json . COPY one-empty-community.json . COPY one-empty-enterprise.json . +COPY one-chaos-community.json . +COPY one-chaos-enterprise.json . + +# As the `sourcemeta` command wipes the working directory +COPY postindex.sh /usr/local/bin/sourcemeta-one-postindex COPY schemas schemas COPY rules rules @@ -16,8 +21,13 @@ RUN sourcemeta \ one-${SOURCEMETA_ONE_SANDBOX_CONFIGURATION}-${SOURCEMETA_ONE_SANDBOX_EDITION}.json \ --profile +RUN sourcemeta-one-postindex \ + "${SOURCEMETA_ONE_SANDBOX_CONFIGURATION}" \ + "${SOURCEMETA_ONE_SANDBOX_EDITION}" \ + "${SOURCEMETA_ONE_OUTPUT}" + # Check that by the end of the indexing, the workdir directory is empty -RUN test -d "$SOURCEMETA_ONE_WORKDIR" -a \ - "$(find "$SOURCEMETA_ONE_WORKDIR" -mindepth 1 -maxdepth 1 | wc -l)" -eq 0 +RUN set -e && test -d "$SOURCEMETA_ONE_WORKDIR" && \ + test -z "$(ls -A "$SOURCEMETA_ONE_WORKDIR")" RUN rm -rf "$SOURCEMETA_ONE_WORKDIR" diff --git a/test/sandbox/one-chaos-community.json b/test/sandbox/one-chaos-community.json new file mode 100644 index 00000000..08cad1fc --- /dev/null +++ b/test/sandbox/one-chaos-community.json @@ -0,0 +1,3 @@ +{ + "extends": [ "./one-html-community.json" ] +} diff --git a/test/sandbox/one-chaos-enterprise.json b/test/sandbox/one-chaos-enterprise.json new file mode 100644 index 00000000..659eb84f --- /dev/null +++ b/test/sandbox/one-chaos-enterprise.json @@ -0,0 +1,3 @@ +{ + "extends": [ "./one-html-enterprise.json" ] +} diff --git a/test/sandbox/postindex.sh b/test/sandbox/postindex.sh new file mode 100755 index 00000000..8faa64a0 --- /dev/null +++ b/test/sandbox/postindex.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +if [ "$#" -ne 3 ] +then + echo "Usage: $0 " 1>&2 + exit 1 +fi + +CONFIGURATION="$1" +EDITION="$2" +OUTPUT="$3" + +echo "Running prepare hook..." 1>&2 +echo " CONFIGURATION: $CONFIGURATION" 1>&2 +echo " EDITION: $EDITION" 1>&2 +echo " OUTPUT: $OUTPUT" 1>&2 + +if [ "$CONFIGURATION" != "chaos" ] +then + exit 0 +fi + +# To test how the server deals with corrupted data +echo "Applying chaos corruptions..." 1>&2 + +echo " Corrupting root node first_literal_child to an out-of-bounds index..." 1>&2 +test -f "$OUTPUT/routes.bin" +printf '\x00\x00\x10\x00' | \ + dd of="$OUTPUT/routes.bin" bs=1 seek=24 conv=notrunc 2>/dev/null + +echo " Corrupting second node string_offset to point past the file end..." 1>&2 +printf '\x00\x00\x00\x7f' | \ + dd of="$OUTPUT/routes.bin" bs=1 seek=40 conv=notrunc 2>/dev/null + +echo " Replacing directory.metapack metadata with wrong types..." 1>&2 +test -f "$OUTPUT/explorer/%/directory.metapack" +printf '{"version":1,"checksum":99999,"lastModified":0,"mime":false,"bytes":1,"duration":1,"encoding":"identity"}' \ + > "$OUTPUT/explorer/%/directory.metapack" + +echo " Deleting search.metapack to trigger missing file assert..." 1>&2 +test -f "$OUTPUT/explorer/%/search.metapack" +rm -f "$OUTPUT/explorer/%/search.metapack" + +echo " Replacing locations.metapack with empty object for test/schemas/string..." 1>&2 +test -f "$OUTPUT/schemas/test/schemas/string/%/locations.metapack" +printf '{"version":1,"checksum":"x","lastModified":"Thu, 01 Jan 2025 00:00:00 GMT","mime":"application/json","bytes":2,"duration":1,"encoding":"identity"}{}' \ + > "$OUTPUT/schemas/test/schemas/string/%/locations.metapack"