|
|
|
@ -287,3 +287,70 @@ func TestLock_Conflict(t *testing.T) {
|
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestLock_ReclaimLock(t *testing.T) { |
|
|
|
|
c, s := makeClient(t) |
|
|
|
|
defer s.stop() |
|
|
|
|
|
|
|
|
|
session, _, err := c.Session().Create(&SessionEntry{}, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
lock, err := c.LockOpts(&LockOptions{Key: "test/lock", Session: session}) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Should work
|
|
|
|
|
leaderCh, err := lock.Lock(nil) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
if leaderCh == nil { |
|
|
|
|
t.Fatalf("not leader") |
|
|
|
|
} |
|
|
|
|
defer lock.Unlock() |
|
|
|
|
|
|
|
|
|
l2, err := c.LockOpts(&LockOptions{Key: "test/lock", Session: session}) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
reclaimed := make(chan (<-chan struct{}), 1) |
|
|
|
|
go func() { |
|
|
|
|
l2Ch, err := l2.Lock(nil) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("not locked: %v", err) |
|
|
|
|
} |
|
|
|
|
reclaimed <- l2Ch |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
// Should reclaim the lock
|
|
|
|
|
var leader2Ch <-chan struct{} |
|
|
|
|
|
|
|
|
|
select { |
|
|
|
|
case leader2Ch = <-reclaimed: |
|
|
|
|
case <-time.After(time.Second): |
|
|
|
|
t.Fatalf("should have locked") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// unlock should work
|
|
|
|
|
err = l2.Unlock() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("err: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//Both locks should see the unlock
|
|
|
|
|
select { |
|
|
|
|
case <-leader2Ch: |
|
|
|
|
case <-time.After(time.Second): |
|
|
|
|
t.Fatalf("should not be leader") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
select { |
|
|
|
|
case <-leaderCh: |
|
|
|
|
case <-time.After(time.Second): |
|
|
|
|
t.Fatalf("should not be leader") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|