Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Unified Diff: go/src/infra/gae/libs/memlock/memlock_test.go

Issue 1159173004: Non racy tests for memlock. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « go/src/infra/gae/libs/memlock/memlock.infra_testing ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/gae/libs/memlock/memlock_test.go
diff --git a/go/src/infra/gae/libs/memlock/memlock_test.go b/go/src/infra/gae/libs/memlock/memlock_test.go
index 49b892b763715e3036b4af2baa50b1d66c8563df..6d86249507ea8ca3316bb2f45f7af8e1362e5b83 100644
--- a/go/src/infra/gae/libs/memlock/memlock_test.go
+++ b/go/src/infra/gae/libs/memlock/memlock_test.go
@@ -8,6 +8,9 @@ import (
"fmt"
"infra/gae/libs/wrapper"
"infra/gae/libs/wrapper/memory"
+ "infra/libs/clock"
+ "infra/libs/clock/testclock"
+ "runtime"
"testing"
"time"
@@ -25,16 +28,28 @@ func init() {
func TestSimple(t *testing.T) {
// TODO(riannucci): Mock time.After so that we don't have to delay for real.
+ const key = memlockKeyPrefix + "testkey"
+
Convey("basic locking", t, func() {
- c := memory.Use(context.Background())
- mc := wrapper.GetMC(c).(interface {
+ start := time.Date(1986, time.October, 26, 1, 20, 00, 00, time.UTC)
+ ctx, clk := testclock.UseTime(context.Background(), start)
+ blocker := make(chan struct{})
+ clk.SetTimerCallback(func(clock.Timer) {
+ clk.Add(delay)
+ select {
+ case blocker <- struct{}{}:
+ default:
+ }
+ })
+ ctx = memory.Use(ctx)
+ mc := wrapper.GetMC(ctx).(interface {
wrapper.Testable
wrapper.MCSingleReadWriter
})
Convey("fails to acquire when memcache is down", func() {
mc.BreakFeatures(nil, "Add")
- err := TryWithLock(c, "testkey", "id", func(check func() bool) error {
+ err := TryWithLock(ctx, "testkey", "id", func(check func() bool) error {
// should never reach here
So(false, ShouldBeTrue)
return nil
@@ -44,48 +59,59 @@ func TestSimple(t *testing.T) {
Convey("returns the inner error", func() {
toRet := fmt.Errorf("sup")
- err := TryWithLock(c, "testkey", "id", func(check func() bool) error {
+ err := TryWithLock(ctx, "testkey", "id", func(check func() bool) error {
+ return toRet
+ })
+ So(err, ShouldEqual, toRet)
+ })
+
+ Convey("returns the error", func() {
+ toRet := fmt.Errorf("sup")
+ err := TryWithLock(ctx, "testkey", "id", func(check func() bool) error {
return toRet
})
So(err, ShouldEqual, toRet)
})
Convey("can acquire when empty", func() {
- err := TryWithLock(c, "testkey", "id", func(check func() bool) error {
+ err := TryWithLock(ctx, "testkey", "id", func(check func() bool) error {
So(check(), ShouldBeTrue)
+ waitFalse := func() {
+ <-blocker
+ for i := 0; i < 3; i++ {
+ if check() {
+ runtime.Gosched()
+ }
+ }
+ So(check(), ShouldBeFalse)
+ }
+
Convey("waiting for a while keeps refreshing the lock", func() {
- time.Sleep(memcacheLockTime * 8)
+ // simulate waiting for 64*delay time, and ensuring that checkLoop
+ // runs that many times.
+ for i := 0; i < 64; i++ {
+ <-blocker
+ clk.Add(delay)
+ }
So(check(), ShouldBeTrue)
})
Convey("but sometimes we might lose it", func() {
Convey("because it was evicted", func() {
- mc.Delete(memlockKeyPrefix + "testkey")
- time.Sleep(memcacheLockTime)
- So(check(), ShouldBeFalse)
- })
-
- Convey("because it got evicted (but we race)", func() {
- mc.Set(&memcache.Item{
- Key: memlockKeyPrefix + "testkey",
- Value: []byte(""),
- })
+ mc.Delete(key)
+ clk.Add(memcacheLockTime)
+ waitFalse()
})
Convey("or because it was stolen", func() {
- mc.Set(&memcache.Item{
- Key: memlockKeyPrefix + "testkey",
- Value: []byte("wat"),
- })
- time.Sleep(memcacheLockTime)
- So(check(), ShouldBeFalse)
+ mc.Set(&memcache.Item{Key: key, Value: []byte("wat")})
+ waitFalse()
})
Convey("or because of service issues", func() {
mc.BreakFeatures(nil, "CompareAndSwap")
- time.Sleep(memcacheLockTime)
- So(check(), ShouldBeFalse)
+ waitFalse()
})
})
return nil
@@ -94,7 +120,7 @@ func TestSimple(t *testing.T) {
})
Convey("an empty context id is an error", func() {
- So(TryWithLock(c, "testkey", "", nil), ShouldEqual, ErrEmptyClientID)
+ So(TryWithLock(ctx, "testkey", "", nil), ShouldEqual, ErrEmptyClientID)
})
})
}
« no previous file with comments | « go/src/infra/gae/libs/memlock/memlock.infra_testing ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698