github.com/quay/claircore@v1.5.28/test/integration/lock_unix.go (about) 1 //go:build !windows 2 3 package integration 4 5 import ( 6 "os" 7 "syscall" 8 "testing" 9 ) 10 11 /* 12 Code below does some shenanigans to lock the directory that we extract to. This 13 has to be done because the `go test` will run package tests in parallel, so 14 different packages may see the extracted binaries in various states if there 15 was not any synchronization. We use an exclusive flock(2) as a write lock, and 16 obtain a shared lock as a read gate. 17 18 Without this, tests would flake on a cold cache. 19 */ 20 21 func lockDir(t testing.TB, dir string) (excl bool) { 22 t.Helper() 23 lf, err := os.Open(dir) 24 if err != nil { 25 t.Fatal(err) 26 } 27 fd := int(lf.Fd()) 28 t.Cleanup(func() { 29 if err := syscall.Flock(fd, syscall.LOCK_UN); err != nil { 30 t.Error(err) 31 } 32 if err := lf.Close(); err != nil { 33 t.Error(err) 34 } 35 }) 36 if err := syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB); err != nil { 37 // Failed to lock, wait for a shared lock, then return 38 t.Logf("waiting for lock on %q", dir) 39 if err := syscall.Flock(fd, syscall.LOCK_SH); err != nil { 40 t.Fatal(err) 41 } 42 return false 43 } 44 return true 45 } 46 47 func lockDirShared(t testing.TB, dir string) { 48 t.Helper() 49 lf, err := os.Open(dir) 50 if err != nil { 51 t.Fatal(err) 52 } 53 t.Cleanup(func() { 54 if err := lf.Close(); err != nil { 55 t.Error(err) 56 } 57 }) 58 if err := syscall.Flock(int(lf.Fd()), syscall.LOCK_SH); err != nil { 59 t.Fatal(err) 60 } 61 }