@@ -37,12 +37,14 @@ import (
37
37
"gotest.tools/v3/icmd"
38
38
39
39
"github.com/containerd/containerd/v2/defaults"
40
+ "github.com/containerd/log"
40
41
41
42
"github.com/containerd/nerdctl/v2/pkg/buildkitutil"
42
43
"github.com/containerd/nerdctl/v2/pkg/imgutil"
43
44
"github.com/containerd/nerdctl/v2/pkg/infoutil"
44
45
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
45
46
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/native"
47
+ "github.com/containerd/nerdctl/v2/pkg/lockutil"
46
48
"github.com/containerd/nerdctl/v2/pkg/platformutil"
47
49
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
48
50
)
@@ -546,14 +548,63 @@ var (
546
548
flagTestKube bool
547
549
)
548
550
551
+ var (
552
+ testLockFile = filepath .Join (os .TempDir (), "nerdctl-test-prevent-concurrency" , ".lock" )
553
+ )
554
+
549
555
func M (m * testing.M ) {
550
556
flag .StringVar (& flagTestTarget , "test.target" , Nerdctl , "target to test" )
551
557
flag .BoolVar (& flagTestKillDaemon , "test.allow-kill-daemon" , false , "enable tests that kill the daemon" )
552
558
flag .BoolVar (& flagTestIPv6 , "test.only-ipv6" , false , "enable tests on IPv6" )
553
559
flag .BoolVar (& flagTestKube , "test.only-kubernetes" , false , "enable tests on Kubernetes" )
554
560
flag .Parse ()
555
- fmt .Fprintf (os .Stderr , "test target: %q\n " , flagTestTarget )
556
- os .Exit (m .Run ())
561
+
562
+ os .Exit (func () int {
563
+ // If there is a lockfile (no err), or if we error-ed stating it (permission), another test run is currently going.
564
+ // Note that this could be racy. The .lock file COULD get acquired after this and before we hit the lock section.
565
+ // This is not a big deal then: we will just wait for the lock to free.
566
+ if _ , err := os .Stat (testLockFile ); err == nil || ! errors .Is (err , os .ErrNotExist ) {
567
+ log .L .Errorf ("Another test binary is already running. If you think this is an error, manually remove %s" , testLockFile )
568
+ return 1
569
+ }
570
+
571
+ err := os .MkdirAll (filepath .Dir (testLockFile ), 0o777 )
572
+ if err != nil {
573
+ log .L .WithError (err ).Errorf ("failed creating testing lock directory %q" , filepath .Dir (testLockFile ))
574
+ return 1
575
+ }
576
+
577
+ // Ensure that permissions are set to 777 (regardless of umask value), so that we do not lock people out when
578
+ // switching between rootful and rootless locking
579
+ os .Chmod (filepath .Dir (testLockFile ), 0o777 )
580
+
581
+ // Acquire lock
582
+ lock , err := lockutil .Lock (filepath .Dir (testLockFile ))
583
+ if err != nil {
584
+ log .L .WithError (err ).Errorf ("failed acquiring testing lock %q" , filepath .Dir (testLockFile ))
585
+ return 1
586
+ }
587
+
588
+ // Release...
589
+ defer lockutil .Unlock (lock )
590
+
591
+ // Create marker file
592
+ err = os .WriteFile (testLockFile , []byte ("prevent testing from running in parallel for subpackages integration tests" ), 0o666 )
593
+ if err != nil {
594
+ log .L .WithError (err ).Errorf ("failed writing lock file %q" , testLockFile )
595
+ return 1
596
+ }
597
+
598
+ // Ensure cleanup
599
+ defer func () {
600
+ os .Remove (testLockFile )
601
+ }()
602
+
603
+ // Now, run the tests
604
+ fmt .Fprintf (os .Stderr , "test target: %q\n " , flagTestTarget )
605
+
606
+ return m .Run ()
607
+ }())
557
608
}
558
609
559
610
func GetTarget () string {
0 commit comments