github.com/quay/claircore@v1.5.28/libvuln/updates/locks_test.go (about) 1 package updates 2 3 import ( 4 "context" 5 "errors" 6 "sync" 7 "sync/atomic" 8 "testing" 9 ) 10 11 func TestLocalLockUnlock(t *testing.T) { 12 ctx := context.Background() 13 l := NewLocalLockSource() 14 15 t.Log("lock") 16 c, done := l.Lock(ctx, t.Name()) 17 if err := c.Err(); err != nil { 18 t.Error(err) 19 } 20 t.Log("unlock") 21 done() 22 if l.peek(t.Name()) { 23 t.Error("lock held") 24 } 25 26 t.Log("lock") 27 c, done = l.Lock(ctx, t.Name()) 28 if err := c.Err(); err != nil { 29 t.Error(err) 30 } 31 t.Log("unlock") 32 done() 33 if l.peek(t.Name()) { 34 t.Error("lock held") 35 } 36 } 37 38 func TestLocalTryLock(t *testing.T) { 39 ctx := context.Background() 40 locks := NewLocalLockSource() 41 locked := make(chan struct{}) 42 unlock := make(chan struct{}) 43 unlocked := make(chan struct{}) 44 go func() { 45 ctx, done := locks.Lock(ctx, t.Name()) 46 if err := ctx.Err(); err != nil { 47 t.Error(err) 48 } 49 defer func() { 50 done() 51 close(unlocked) 52 t.Log("lock released") 53 }() 54 t.Log("lock held") 55 close(locked) 56 <-unlock 57 }() 58 59 <-locked 60 lc, done := locks.TryLock(ctx, t.Name()) 61 t.Logf("try: %v", lc.Err()) 62 if !errors.Is(lc.Err(), context.Canceled) { 63 t.Error("wanted TryLock to fail") 64 } 65 done() 66 close(unlock) 67 <-unlocked 68 lc, done = locks.TryLock(ctx, t.Name()) 69 t.Logf("try: %v", lc.Err()) 70 if !errors.Is(lc.Err(), nil) { 71 t.Error("wanted TryLock to succeed") 72 } 73 done() 74 t.Log("unlocked") 75 } 76 77 func TestLocalLockSequential(t *testing.T) { 78 ctx := context.Background() 79 locks := NewLocalLockSource() 80 var wg sync.WaitGroup 81 wg.Add(2) 82 var ct uint64 83 _, d1 := locks.Lock(ctx, t.Name()) 84 go func() { 85 _, d2 := locks.Lock(ctx, t.Name()) 86 defer func() { 87 d2() 88 wg.Done() 89 }() 90 t.Log("1 → 2") 91 if !atomic.CompareAndSwapUint64(&ct, 1, 2) { 92 t.Error("ordering error") 93 } 94 }() 95 go func() { 96 defer func() { 97 d1() 98 wg.Done() 99 }() 100 t.Log("0 → 1") 101 if !atomic.CompareAndSwapUint64(&ct, 0, 1) { 102 t.Error("ordering error") 103 } 104 }() 105 106 wg.Wait() 107 if got, want := ct, uint64(2); got != want { 108 t.Errorf("got: %d, want: %d", got, want) 109 } 110 }