From 2a35d65d21b6fb081a24c1579ba9a93291d822b6 Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 30 Aug 2026 16:26:44 -0400 Subject: [PATCH] test(plugins): make the suite safe to run in parallel processes Two things broke when the suite ran across several Ginkgo processes. buildTestPlugins ran in every process, so N copies of make raced in the same directory. The packaging rule made that worse by staging every plugin through one shared plugin.wasm, so concurrent targets clobbered each other and left orphaned temp files behind. That also ruled out make -j. Stage each package under its own per-target directory, and move the build into SynchronizedBeforeSuite so process 1 does it once while the others wait. --- .gitignore | 1 + plugins/plugins_suite_test.go | 20 +++++++++----------- plugins/testdata/Makefile | 10 ++++++---- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 810074e72..4ed971491 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ zz_*_test.go # wazero compilation cache for the plugins test suite /plugins/testdata/.wazero-cache/ +/plugins/testdata/*.stage/ diff --git a/plugins/plugins_suite_test.go b/plugins/plugins_suite_test.go index c8585f2c1..2dae65d00 100644 --- a/plugins/plugins_suite_test.go +++ b/plugins/plugins_suite_test.go @@ -7,6 +7,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "fmt" "net/http" "os" "os/exec" @@ -39,7 +40,6 @@ var ( func TestPlugins(t *testing.T) { tests.Init(t, false) - buildTestPlugins(t, testDataDir) // Set globally so tests using configtest.SetupConfig inherit it. The cache // persists between runs; entries are content-addressed, so a stale one only misses. @@ -51,16 +51,11 @@ func TestPlugins(t *testing.T) { RunSpecs(t, "Plugins Suite") } -func buildTestPlugins(t *testing.T, path string) { - t.Helper() +func buildTestPlugins(path string) { start := time.Now() - t.Logf("[BeforeSuite] Current working directory: %s", path) - cmd := exec.Command("make", "-C", path) - out, err := cmd.CombinedOutput() - t.Logf("[BeforeSuite] Make output: %s elapsed: %s", string(out), time.Since(start)) - if err != nil { - t.Fatalf("Failed to build test plugins: %v", err) - } + out, err := exec.Command("make", "-C", path).CombinedOutput() + fmt.Fprintf(GinkgoWriter, "[BeforeSuite] built test plugins in %s:\n%s", time.Since(start), out) + Expect(err).ToNot(HaveOccurred(), "failed to build test plugins") } // createTestManager creates a new plugin Manager with the given plugin config. @@ -146,7 +141,10 @@ func createTestManagerWithPluginsAndMetrics(pluginConfig map[string]map[string]s return manager, tmpDir } -var _ = BeforeSuite(func() { +var _ = SynchronizedBeforeSuite(func() { + // Build once: the testdata Makefile is not safe to run concurrently. + buildTestPlugins(testDataDir) +}, func() { // Get testdata directory (where test plugin .ndp packages live) _, currentFile, _, ok := runtime.Caller(0) Expect(ok).To(BeTrue()) diff --git a/plugins/testdata/Makefile b/plugins/testdata/Makefile index 758497095..de948a2bb 100644 --- a/plugins/testdata/Makefile +++ b/plugins/testdata/Makefile @@ -10,17 +10,19 @@ all: $(PLUGINS:%=%.ndp) clean: rm -f $(PLUGINS:%=%.ndp) $(PLUGINS:%=%.wasm) - rm -rf .wazero-cache + rm -rf .wazero-cache $(PLUGINS:%=%.stage) # PDK source files that trigger rebuild when changed (recursive) PDK_SOURCES := $(shell find ../pdk/go -name '*.go' 2>/dev/null) # Build the .ndp package (zip containing manifest.json + plugin.wasm) +# Stage under a per-target name: a shared plugin.wasm breaks concurrent builds. %.ndp: %.wasm %/manifest.json @rm -f $@ - @cp $< plugin.wasm - zip -j $@ $*/manifest.json plugin.wasm - @rm -f plugin.wasm + @rm -rf $*.stage && mkdir -p $*.stage + @cp $< $*.stage/plugin.wasm + zip -j $@ $*/manifest.json $*.stage/plugin.wasm + @rm -rf $*.stage @mv $< $<.tmp && mv $<.tmp $< # Touch wasm to ensure it's older than ndp # Build the wasm binary. -buildvcs=false keeps the bytes stable across commits, so