@@ -6,61 +6,54 @@ package backend
66import (
77 "context"
88 "testing"
9+ "testing/synctest"
910 "time"
1011)
1112
1213func TestMutexMap (t * testing.T ) {
13- // Prevent this test from blocking past the test deadline.
14- ctx := context .Background ()
15- if deadline , ok := t .Deadline (); ok {
16- var cancel context.CancelFunc
17- ctx , cancel = context .WithDeadline (ctx , deadline )
18- defer cancel ()
19- }
20-
21- mm := new (mutexMap [int ])
22- unlock1 , err := mm .lock (ctx , 1 )
23- if err != nil {
24- t .Fatal ("lock(ctx, 1) on new map failed:" , err )
25- }
26-
27- // Verify that we can acquire a lock on an independent key.
28- unlock2 , err := mm .lock (ctx , 2 )
29- if err != nil {
30- t .Fatal ("lock(ctx, 2) after lock(ctx, 1) failed:" , err )
31- }
32-
33- // Verify that attempting a lock on the same key blocks until Done.
34- failFastCtx , cancelFailFast := context .WithTimeout (ctx , 100 * time .Millisecond )
35- unlock1b , err := mm .lock (failFastCtx , 1 )
36- cancelFailFast ()
37- if err == nil {
38- t .Error ("lock(ctx, 1) acquired without releasing unlock1" )
39- unlock1b ()
40- }
41-
42- // Verify that unlocking a key allows a subsequent lock to succeed.
43- unlock1 ()
44- unlock1 , err = mm .lock (ctx , 1 )
45- if err != nil {
46- t .Fatal ("lock(ctx, 1) after unlock1 failed:" , err )
47- }
48-
49- // Verify that unlocking a key allows a concurrent lock to succeed.
50- lock2Done := make (chan error )
51- go func () {
52- _ , err := mm .lock (ctx , 2 )
53- lock2Done <- err
54- }()
55- // Wait for a little bit to make it more likely that the other goroutine hit lock(2).
56- timer := time .NewTimer (10 * time .Millisecond )
57- select {
58- case <- timer .C :
59- case <- ctx .Done ():
60- timer .Stop ()
61- }
62- unlock2 ()
63- if err := <- lock2Done ; err != nil {
64- t .Error ("lock(ctx, 2) with concurrent unlock2 failed:" , err )
65- }
14+ synctest .Test (t , func (t * testing.T ) {
15+ ctx := context .Background ()
16+
17+ mm := new (mutexMap [int ])
18+ unlock1 , err := mm .lock (ctx , 1 )
19+ if err != nil {
20+ t .Fatal ("lock(ctx, 1) on new map failed:" , err )
21+ }
22+
23+ // Verify that we can acquire a lock on an independent key.
24+ unlock2 , err := mm .lock (ctx , 2 )
25+ if err != nil {
26+ t .Fatal ("lock(ctx, 2) after lock(ctx, 1) failed:" , err )
27+ }
28+
29+ // Verify that attempting a lock on the same key blocks until Done.
30+ failFastCtx , cancelFailFast := context .WithTimeout (ctx , 100 * time .Millisecond )
31+ unlock1b , err := mm .lock (failFastCtx , 1 )
32+ cancelFailFast ()
33+ if err == nil {
34+ t .Error ("lock(ctx, 1) acquired without releasing unlock1" )
35+ unlock1b ()
36+ }
37+
38+ // Verify that unlocking a key allows a subsequent lock to succeed.
39+ unlock1 ()
40+ unlock1 , err = mm .lock (ctx , 1 )
41+ if err != nil {
42+ t .Fatal ("lock(ctx, 1) after unlock1 failed:" , err )
43+ }
44+ unlock1 ()
45+
46+ // Verify that unlocking a key allows a concurrent lock to succeed.
47+ lock2Done := make (chan error )
48+ go func () {
49+ _ , err := mm .lock (ctx , 2 )
50+ lock2Done <- err
51+ }()
52+ // Sleep to make other goroutine hit lock(2). (Yay synctest!)
53+ time .Sleep (10 * time .Millisecond )
54+ unlock2 ()
55+ if err := <- lock2Done ; err != nil {
56+ t .Error ("lock(ctx, 2) with concurrent unlock2 failed:" , err )
57+ }
58+ })
6659}
0 commit comments