github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/pkg/locker/locker_test.go (about) 1 package locker 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 ) 8 9 func TestLockCounter(t *testing.T) { 10 l := &lockCtr{} 11 l.inc() 12 13 if l.waiters != 1 { 14 t.Fatal("counter inc failed") 15 } 16 17 l.dec() 18 if l.waiters != 0 { 19 t.Fatal("counter dec failed") 20 } 21 } 22 23 func TestLockerLock(t *testing.T) { 24 l := New() 25 l.Lock("test") 26 ctr := l.locks["test"] 27 28 if ctr.count() != 0 { 29 t.Fatalf("expected waiters to be 0, got :%d", ctr.waiters) 30 } 31 32 chDone := make(chan struct{}) 33 go func() { 34 l.Lock("test") 35 close(chDone) 36 }() 37 38 chWaiting := make(chan struct{}) 39 go func() { 40 for range time.Tick(1 * time.Millisecond) { 41 if ctr.count() == 1 { 42 close(chWaiting) 43 break 44 } 45 } 46 }() 47 48 select { 49 case <-chWaiting: 50 case <-time.After(3 * time.Second): 51 t.Fatal("timed out waiting for lock waiters to be incremented") 52 } 53 54 select { 55 case <-chDone: 56 t.Fatal("lock should not have returned while it was still held") 57 default: 58 } 59 60 if err := l.Unlock("test"); err != nil { 61 t.Fatal(err) 62 } 63 64 select { 65 case <-chDone: 66 case <-time.After(3 * time.Second): 67 t.Fatalf("lock should have completed") 68 } 69 70 if ctr.count() != 0 { 71 t.Fatalf("expected waiters to be 0, got: %d", ctr.count()) 72 } 73 } 74 75 func TestLockerUnlock(t *testing.T) { 76 l := New() 77 78 l.Lock("test") 79 l.Unlock("test") 80 81 chDone := make(chan struct{}) 82 go func() { 83 l.Lock("test") 84 close(chDone) 85 }() 86 87 select { 88 case <-chDone: 89 case <-time.After(3 * time.Second): 90 t.Fatalf("lock should not be blocked") 91 } 92 } 93 94 func TestLockerConcurrency(t *testing.T) { 95 l := New() 96 97 var wg sync.WaitGroup 98 for i := 0; i <= 10000; i++ { 99 wg.Add(1) 100 go func() { 101 l.Lock("test") 102 // if there is a concurrency issue, will very likely panic here 103 l.Unlock("test") 104 wg.Done() 105 }() 106 } 107 108 chDone := make(chan struct{}) 109 go func() { 110 wg.Wait() 111 close(chDone) 112 }() 113 114 select { 115 case <-chDone: 116 case <-time.After(10 * time.Second): 117 t.Fatal("timeout waiting for locks to complete") 118 } 119 120 // Since everything has unlocked this should not exist anymore 121 if ctr, exists := l.locks["test"]; exists { 122 t.Fatalf("lock should not exist: %v", ctr) 123 } 124 }