github.com/brass-software/os@v0.0.0-20240129060254-960f457a5dea/exec_windows_test.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build windows 6 7 package os_test 8 9 import ( 10 "internal/testenv" 11 "io" 12 . "os" 13 "path/filepath" 14 "sync" 15 "testing" 16 ) 17 18 func TestRemoveAllWithExecutedProcess(t *testing.T) { 19 // Regression test for golang.org/issue/25965. 20 if testing.Short() { 21 t.Skip("slow test; skipping") 22 } 23 testenv.MustHaveExec(t) 24 25 name, err := Executable() 26 if err != nil { 27 t.Fatal(err) 28 } 29 r, err := Open(name) 30 if err != nil { 31 t.Fatal(err) 32 } 33 defer r.Close() 34 const n = 100 35 var execs [n]string 36 // First create n executables. 37 for i := 0; i < n; i++ { 38 // Rewind r. 39 if _, err := r.Seek(0, io.SeekStart); err != nil { 40 t.Fatal(err) 41 } 42 name := filepath.Join(t.TempDir(), "test.exe") 43 execs[i] = name 44 w, err := Create(name) 45 if err != nil { 46 t.Fatal(err) 47 } 48 if _, err = io.Copy(w, r); err != nil { 49 w.Close() 50 t.Fatal(err) 51 } 52 if err := w.Sync(); err != nil { 53 w.Close() 54 t.Fatal(err) 55 } 56 if err = w.Close(); err != nil { 57 t.Fatal(err) 58 } 59 } 60 // Then run each executable and remove its directory. 61 // Run each executable in a separate goroutine to add some load 62 // and increase the chance of triggering the bug. 63 var wg sync.WaitGroup 64 wg.Add(n) 65 for i := 0; i < n; i++ { 66 go func(i int) { 67 defer wg.Done() 68 name := execs[i] 69 dir := filepath.Dir(name) 70 // Run test.exe without executing any test, just to make it do something. 71 cmd := testenv.Command(t, name, "-test.run=^$") 72 if err := cmd.Run(); err != nil { 73 t.Errorf("exec failed: %v", err) 74 } 75 // Remove dir and check that it doesn't return `ERROR_ACCESS_DENIED`. 76 err = RemoveAll(dir) 77 if err != nil { 78 t.Errorf("RemoveAll failed: %v", err) 79 } 80 }(i) 81 } 82 wg.Wait() 83 }