@@ -277,6 +277,55 @@ func TestTryReadLockFile(t *testing.T) {
277277 assert .Nil (t , <- errChan )
278278}
279279
280+ func TestTryLockState (t * testing.T ) {
281+ l , err := getTempLockfile ()
282+ require .NoError (t , err , "creating lock" )
283+ defer os .Remove (l .name )
284+
285+ // Take a write lock somewhere.
286+ cmd , wc , rc , err := subLock (l )
287+ require .NoError (t , err )
288+ _ , err = io .Copy (io .Discard , rc )
289+ require .NoError (t , err )
290+
291+ err = l .TryRLock ()
292+ assert .NotNil (t , err )
293+
294+ // Lock and hold state mutex.
295+ locked := make (chan bool )
296+ go func () {
297+ locked <- false
298+ l .RLock ()
299+ locked <- true
300+ l .Unlock ()
301+ locked <- false
302+ }()
303+
304+ assert .False (t , <- locked )
305+
306+ // Wait state mutex is locked.
307+ for l .stateMutex .TryLock () {
308+ l .stateMutex .Unlock ()
309+ time .Sleep (100 * time .Millisecond )
310+ }
311+
312+ // Try locks should fail without blocking.
313+ errChan := make (chan error )
314+ go func () {
315+ errChan <- l .TryRLock ()
316+ errChan <- l .TryLock ()
317+ }()
318+ assert .NotNil (t , <- errChan )
319+ assert .NotNil (t , <- errChan )
320+
321+ wc .Close ()
322+ err = cmd .Wait ()
323+ require .NoError (t , err )
324+
325+ assert .True (t , <- locked )
326+ assert .False (t , <- locked )
327+ }
328+
280329func TestLockfileRead (t * testing.T ) {
281330 l , err := getTempLockfile ()
282331 require .Nil (t , err , "error getting temporary lock file" )
0 commit comments