diff --git a/internal/pkg/agent/install/testblocking/main.go b/internal/pkg/agent/install/testblocking/main.go new file mode 100644 index 00000000000..adbd771d22d --- /dev/null +++ b/internal/pkg/agent/install/testblocking/main.go @@ -0,0 +1,15 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package main + +import ( + "math" + "time" +) + +// Simple program that blocks forever to ensure exes running from a directory on Windows can be removed during uninstall. +func main() { + <-time.After(time.Duration(math.MaxInt64)) +} diff --git a/internal/pkg/agent/install/uninstall_windows_test.go b/internal/pkg/agent/install/uninstall_windows_test.go index 31812988b68..e029b471513 100644 --- a/internal/pkg/agent/install/uninstall_windows_test.go +++ b/internal/pkg/agent/install/uninstall_windows_test.go @@ -12,37 +12,34 @@ import ( "path/filepath" "testing" + "github.com/otiai10/copy" "github.com/stretchr/testify/require" ) -const simpleBlockForever = ` -package main - -import ( - "math" - "time" -) - -func main() { - <-time.After(time.Duration(math.MaxInt64)) -} -` - func TestRemovePath(t *testing.T) { - dir := filepath.Join(t.TempDir(), "subdir") - err := os.Mkdir(dir, 0644) + var ( + pkgName = "testblocking" + binaryName = pkgName + ".exe" + ) + + // Create a temporary directory that we can safely remove. The directory is created as a new + // sub-directory. This avoids having Microsoft Defender quarantine the file if it is exec'd from + // the default temporary directory. + destDir, err := os.MkdirTemp(pkgName, t.Name()) require.NoError(t, err) - src := filepath.Join(dir, "main.go") - err = os.WriteFile(src, []byte(simpleBlockForever), 0644) - require.NoError(t, err) + // Copy the test executable to the new temporary directory. + destpath, err := filepath.Abs(filepath.Join(destDir, binaryName)) + require.NoErrorf(t, err, "failed dest abs %s + %s", destDir, binaryName) + + srcPath, err := filepath.Abs(filepath.Join(pkgName, binaryName)) + require.NoErrorf(t, err, "failed src abs %s + %s", pkgName, binaryName) - binary := filepath.Join(dir, "main.exe") - cmd := exec.Command("go", "build", "-o", binary, src) - _, err = cmd.CombinedOutput() + err = copy.Copy(srcPath, destpath, copy.Options{Sync: true}) require.NoError(t, err) - cmd = exec.Command(binary) + // Execute the test executable asynchronously. + cmd := exec.Command(destpath) err = cmd.Start() require.NoError(t, err) defer func() { @@ -50,6 +47,7 @@ func TestRemovePath(t *testing.T) { _ = cmd.Wait() }() - err = RemovePath(dir) + // Ensure the directory containing the executable can be removed. + err = RemovePath(destDir) require.NoError(t, err) } diff --git a/magefile.go b/magefile.go index 33a03a818a0..86ed0bc10c9 100644 --- a/magefile.go +++ b/magefile.go @@ -260,16 +260,19 @@ func (Build) Clean() { // TestBinaries build the required binaries for the test suite. func (Build) TestBinaries() error { wd, _ := os.Getwd() - p := filepath.Join(wd, "pkg", "component", "fake") - for _, name := range []string{"component", "shipper"} { - binary := name + testBinaryPkgs := []string{ + filepath.Join(wd, "pkg", "component", "fake", "component"), + filepath.Join(wd, "pkg", "component", "fake", "shipper"), + filepath.Join(wd, "internal", "pkg", "agent", "install", "testblocking"), + } + for _, pkg := range testBinaryPkgs { + binary := filepath.Base(pkg) if runtime.GOOS == "windows" { binary += ".exe" } - fakeDir := filepath.Join(p, name) - outputName := filepath.Join(fakeDir, binary) - err := RunGo("build", "-o", outputName, filepath.Join(fakeDir)) + outputName := filepath.Join(pkg, binary) + err := RunGo("build", "-o", outputName, filepath.Join(pkg)) if err != nil { return err }