From 2fe11fb96705f6c51cf52092b1930df508943aa8 Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Mon, 5 Aug 2024 10:41:35 -0400 Subject: [PATCH] packer_test: move compiledPlugins to attribute The compiledPlugins map used to be a global variable, which can be problematic as we move to independent test suites, since those test suites run in the same process space, the global variable could point to now deleted plugin versions/paths in separate suites, which would make tests fail with random errors. To avoid this, the map is now scoped to the test suite, and a new copy is created lazily if used by the test suite. --- packer_test/lib/plugin.go | 31 ++++++++++++++++++------------- packer_test/lib/suite.go | 11 +++++++++-- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/packer_test/lib/plugin.go b/packer_test/lib/plugin.go index c3a4b0fe7..28afb1adf 100644 --- a/packer_test/lib/plugin.go +++ b/packer_test/lib/plugin.go @@ -15,24 +15,29 @@ import ( "github.com/hashicorp/packer-plugin-sdk/plugin" ) -var compiledPlugins = struct { +type compiledPlugins struct { pluginVersions map[string]string - RWMutex sync.RWMutex -}{ - pluginVersions: map[string]string{}, + mutex sync.Mutex } -func StorePluginVersion(pluginVersion, path string) { - compiledPlugins.RWMutex.Lock() - defer compiledPlugins.RWMutex.Unlock() - compiledPlugins.pluginVersions[pluginVersion] = path +func (ts *PackerTestSuite) StorePluginVersion(pluginVersion, path string) { + ts.compiledPlugins.mutex.Lock() + defer ts.compiledPlugins.mutex.Unlock() + if ts.compiledPlugins.pluginVersions == nil { + ts.compiledPlugins.pluginVersions = map[string]string{} + } + + ts.compiledPlugins.pluginVersions[pluginVersion] = path } -func LoadPluginVersion(pluginVersion string) (string, bool) { - compiledPlugins.RWMutex.RLock() - defer compiledPlugins.RWMutex.RUnlock() +func (ts *PackerTestSuite) LoadPluginVersion(pluginVersion string) (string, bool) { + ts.compiledPlugins.mutex.Lock() + defer ts.compiledPlugins.mutex.Unlock() + if ts.compiledPlugins.pluginVersions == nil { + ts.compiledPlugins.pluginVersions = map[string]string{} + } - path, ok := compiledPlugins.pluginVersions[pluginVersion] + path, ok := ts.compiledPlugins.pluginVersions[pluginVersion] return path, ok } @@ -129,7 +134,7 @@ func (ts *PackerTestSuite) MakePluginDir(pluginVersions ...string) (pluginTempDi } for _, pluginVersion := range pluginVersions { - path, ok := LoadPluginVersion(pluginVersion) + path, ok := ts.LoadPluginVersion(pluginVersion) if !ok { err = fmt.Errorf("failed to get path to version %q, was it compiled?", pluginVersion) } diff --git a/packer_test/lib/suite.go b/packer_test/lib/suite.go index f597c712c..2b8d10b7a 100644 --- a/packer_test/lib/suite.go +++ b/packer_test/lib/suite.go @@ -24,6 +24,13 @@ type PackerTestSuite struct { // Since we don't necessarily want to manually compile Packer beforehand, // we compile it on demand, and use this executable for the tests. packerPath string + // compiledPlugins is the map of each compiled plugin to its path. + // + // This used to be global, but should be linked to the suite instead, as + // we may have multiple suites that exist, each with its own repo of + // plugins compiled for the purposes of the test, so as they all run + // within the same process space, they should be separate instances. + compiledPlugins compiledPlugins } func (ts *PackerTestSuite) buildPluginVersion(waitgroup *sync.WaitGroup, versionString string, t *testing.T) { @@ -58,7 +65,7 @@ func (ts *PackerTestSuite) CompileTestPluginVersions(t *testing.T, versions ...s // though, deletion is the caller's responsibility. func (ts *PackerTestSuite) BuildSimplePlugin(versionString string, t *testing.T) string { // Only build plugin binary if not already done beforehand - path, ok := LoadPluginVersion(versionString) + path, ok := ts.LoadPluginVersion(versionString) if ok { return path } @@ -81,7 +88,7 @@ func (ts *PackerTestSuite) BuildSimplePlugin(versionString string, t *testing.T) t.Fatalf("failed to compile plugin binary: %s\ncompiler logs: %s", err, logs) } - StorePluginVersion(v.String(), outBin) + ts.StorePluginVersion(v.String(), outBin) return outBin }