func TestKVTxnBlockNonTxnOperations(t *testing.T) { b, tmpPath := backend.NewDefaultTmpBackend() s := NewStore(b, &lease.FakeLessor{}, nil) tests := []func(){ func() { s.Range([]byte("foo"), nil, 0, 0) }, func() { s.Put([]byte("foo"), nil, lease.NoLease) }, func() { s.DeleteRange([]byte("foo"), nil) }, } for i, tt := range tests { id := s.TxnBegin() done := make(chan struct{}, 1) go func() { tt() done <- struct{}{} }() select { case <-done: t.Fatalf("#%d: operation failed to be blocked", i) case <-time.After(10 * time.Millisecond): } s.TxnEnd(id) select { case <-done: case <-time.After(10 * time.Second): testutil.FatalStack(t, fmt.Sprintf("#%d: operation failed to be unblocked", i)) } } // only close backend when we know all the tx are finished cleanup(s, b, tmpPath) }
func TestTxnBlockBackendForceCommit(t *testing.T) { b, tmpPath := backend.NewDefaultTmpBackend() s := NewStore(b, &lease.FakeLessor{}, nil) defer os.Remove(tmpPath) id := s.TxnBegin() done := make(chan struct{}) go func() { s.b.ForceCommit() done <- struct{}{} }() select { case <-done: t.Fatalf("failed to block ForceCommit") case <-time.After(100 * time.Millisecond): } s.TxnEnd(id) select { case <-done: case <-time.After(5 * time.Second): // wait 5 seconds for CI with slow IO testutil.FatalStack(t, "failed to execute ForceCommit") } }
func TestWatchableKVWatch(t *testing.T) { b, tmpPath := backend.NewDefaultTmpBackend() s := WatchableKV(newWatchableStore(b, &lease.FakeLessor{}, nil)) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() defer w.Close() wid := w.Watch([]byte("foo"), []byte("fop"), 0) wev := []storagepb.Event{ {Type: storagepb.PUT, Kv: &storagepb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: 2, Version: 1, Lease: 1, }, }, { Type: storagepb.PUT, Kv: &storagepb.KeyValue{ Key: []byte("foo1"), Value: []byte("bar1"), CreateRevision: 3, ModRevision: 3, Version: 1, Lease: 2, }, }, { Type: storagepb.PUT, Kv: &storagepb.KeyValue{ Key: []byte("foo1"), Value: []byte("bar11"), CreateRevision: 3, ModRevision: 4, Version: 2, Lease: 3, }, }, } s.Put([]byte("foo"), []byte("bar"), 1) select { case resp := <-w.Chan(): if resp.WatchID != wid { t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) } ev := resp.Events[0] if !reflect.DeepEqual(ev, wev[0]) { t.Errorf("watched event = %+v, want %+v", ev, wev[0]) } case <-time.After(5 * time.Second): // CPU might be too slow, and the routine is not able to switch around testutil.FatalStack(t, "failed to watch the event") } s.Put([]byte("foo1"), []byte("bar1"), 2) select { case resp := <-w.Chan(): if resp.WatchID != wid { t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) } ev := resp.Events[0] if !reflect.DeepEqual(ev, wev[1]) { t.Errorf("watched event = %+v, want %+v", ev, wev[1]) } case <-time.After(5 * time.Second): testutil.FatalStack(t, "failed to watch the event") } w = s.NewWatchStream() wid = w.Watch([]byte("foo1"), []byte("foo2"), 3) select { case resp := <-w.Chan(): if resp.WatchID != wid { t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) } ev := resp.Events[0] if !reflect.DeepEqual(ev, wev[1]) { t.Errorf("watched event = %+v, want %+v", ev, wev[1]) } case <-time.After(5 * time.Second): testutil.FatalStack(t, "failed to watch the event") } s.Put([]byte("foo1"), []byte("bar11"), 3) select { case resp := <-w.Chan(): if resp.WatchID != wid { t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) } ev := resp.Events[0] if !reflect.DeepEqual(ev, wev[2]) { t.Errorf("watched event = %+v, want %+v", ev, wev[2]) } case <-time.After(5 * time.Second): testutil.FatalStack(t, "failed to watch the event") } }