|
|
@@ -45,10 +45,6 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
Key: []byte("foo")}}},
|
|
|
|
|
|
[]*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
{
|
|
|
Header: &pb.ResponseHeader{Revision: 2},
|
|
|
Created: false,
|
|
|
@@ -68,12 +64,7 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
CreateRequest: &pb.WatchCreateRequest{
|
|
|
Key: []byte("helloworld")}}},
|
|
|
|
|
|
- []*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
- },
|
|
|
+ []*pb.WatchResponse{},
|
|
|
},
|
|
|
// watch the prefix, matching
|
|
|
{
|
|
|
@@ -83,10 +74,6 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
Prefix: []byte("foo")}}},
|
|
|
|
|
|
[]*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
{
|
|
|
Header: &pb.ResponseHeader{Revision: 2},
|
|
|
Created: false,
|
|
|
@@ -106,12 +93,7 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
CreateRequest: &pb.WatchCreateRequest{
|
|
|
Prefix: []byte("helloworld")}}},
|
|
|
|
|
|
- []*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
- },
|
|
|
+ []*pb.WatchResponse{},
|
|
|
},
|
|
|
// multiple puts, one watcher with matching key
|
|
|
{
|
|
|
@@ -121,10 +103,6 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
Key: []byte("foo")}}},
|
|
|
|
|
|
[]*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
{
|
|
|
Header: &pb.ResponseHeader{Revision: 2},
|
|
|
Created: false,
|
|
|
@@ -165,10 +143,6 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
Prefix: []byte("foo")}}},
|
|
|
|
|
|
[]*pb.WatchResponse{
|
|
|
- {
|
|
|
- Header: &pb.ResponseHeader{Revision: 1},
|
|
|
- Created: true,
|
|
|
- },
|
|
|
{
|
|
|
Header: &pb.ResponseHeader{Revision: 2},
|
|
|
Created: false,
|
|
|
@@ -218,6 +192,23 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
t.Fatalf("#%d: wStream.Send error: %v", i, err)
|
|
|
}
|
|
|
|
|
|
+ // ensure watcher request created a new watcher
|
|
|
+ cresp, err := wStream.Recv()
|
|
|
+ if err != nil {
|
|
|
+ t.Errorf("#%d: wStream.Recv error: %v", i, err)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if cresp.Created != true {
|
|
|
+ t.Errorf("#%d: did not create watchid, got +%v", i, cresp)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ createdWatchId := cresp.WatchId
|
|
|
+ if cresp.Header == nil || cresp.Header.Revision != 1 {
|
|
|
+ t.Errorf("#%d: header revision got +%v, wanted revison 1", i, cresp)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // asynchronously create keys
|
|
|
go func() {
|
|
|
for _, k := range tt.putKeys {
|
|
|
kvc := clus.RandClient().KV
|
|
|
@@ -228,7 +219,7 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
- var createdWatchId int64
|
|
|
+ // check stream results
|
|
|
for j, wresp := range tt.wresps {
|
|
|
resp, err := wStream.Recv()
|
|
|
if err != nil {
|
|
|
@@ -245,9 +236,6 @@ func TestV3WatchFromCurrentRevision(t *testing.T) {
|
|
|
if wresp.Created != resp.Created {
|
|
|
t.Errorf("#%d.%d: resp.Created got = %v, want = %v", i, j, resp.Created, wresp.Created)
|
|
|
}
|
|
|
- if resp.Created {
|
|
|
- createdWatchId = resp.WatchId
|
|
|
- }
|
|
|
if resp.WatchId != createdWatchId {
|
|
|
t.Errorf("#%d.%d: resp.WatchId got = %d, want = %d", i, j, resp.WatchId, createdWatchId)
|
|
|
}
|
|
|
@@ -333,6 +321,86 @@ func testV3WatchCancel(t *testing.T, startRev int64) {
|
|
|
clus.Terminate(t)
|
|
|
}
|
|
|
|
|
|
+// TestV3WatchCurrentPutOverlap ensures current watchers receive all events with
|
|
|
+// overlapping puts.
|
|
|
+func TestV3WatchCurrentPutOverlap(t *testing.T) {
|
|
|
+ defer testutil.AfterTest(t)
|
|
|
+ clus := NewClusterV3(t, &ClusterConfig{Size: 3})
|
|
|
+ defer clus.Terminate(t)
|
|
|
+
|
|
|
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
|
+ defer cancel()
|
|
|
+ wStream, wErr := clus.RandClient().Watch.Watch(ctx)
|
|
|
+ if wErr != nil {
|
|
|
+ t.Fatalf("wAPI.Watch error: %v", wErr)
|
|
|
+ }
|
|
|
+
|
|
|
+ // last mod_revision that will be observed
|
|
|
+ nrRevisions := 32
|
|
|
+ // first revision already allocated as empty revision
|
|
|
+ for i := 1; i < nrRevisions; i++ {
|
|
|
+ go func() {
|
|
|
+ kvc := clus.RandClient().KV
|
|
|
+ req := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")}
|
|
|
+ if _, err := kvc.Put(context.TODO(), req); err != nil {
|
|
|
+ t.Fatalf("couldn't put key (%v)", err)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ }
|
|
|
+
|
|
|
+ // maps watcher to current expected revision
|
|
|
+ progress := make(map[int64]int64)
|
|
|
+
|
|
|
+ wreq := &pb.WatchRequest{RequestUnion: &pb.WatchRequest_CreateRequest{
|
|
|
+ CreateRequest: &pb.WatchCreateRequest{Prefix: []byte("foo")}}}
|
|
|
+ if err := wStream.Send(wreq); err != nil {
|
|
|
+ t.Fatalf("first watch request failed (%v)", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ more := true
|
|
|
+ progress[-1] = 0 // watcher creation pending
|
|
|
+ for more {
|
|
|
+ resp, err := wStream.Recv()
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("wStream.Recv error: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if resp.Created {
|
|
|
+ // accept events > header revision
|
|
|
+ progress[resp.WatchId] = resp.Header.Revision + 1
|
|
|
+ if resp.Header.Revision == int64(nrRevisions) {
|
|
|
+ // covered all revisions; create no more watchers
|
|
|
+ progress[-1] = int64(nrRevisions) + 1
|
|
|
+ } else if err := wStream.Send(wreq); err != nil {
|
|
|
+ t.Fatalf("watch request failed (%v)", err)
|
|
|
+ }
|
|
|
+ } else if len(resp.Events) == 0 {
|
|
|
+ t.Fatalf("got events %v, want non-empty", resp.Events)
|
|
|
+ } else {
|
|
|
+ wRev, ok := progress[resp.WatchId]
|
|
|
+ if !ok {
|
|
|
+ t.Fatalf("got %+v, but watch id shouldn't exist ", resp)
|
|
|
+ }
|
|
|
+ if resp.Events[0].Kv.ModRevision != wRev {
|
|
|
+ t.Fatalf("got %+v, wanted first revision %d", resp, wRev)
|
|
|
+ }
|
|
|
+ lastRev := resp.Events[len(resp.Events)-1].Kv.ModRevision
|
|
|
+ progress[resp.WatchId] = lastRev + 1
|
|
|
+ }
|
|
|
+ more = false
|
|
|
+ for _, v := range progress {
|
|
|
+ if v <= int64(nrRevisions) {
|
|
|
+ more = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if rok, nr := waitResponse(wStream, time.Second); !rok {
|
|
|
+ t.Errorf("unexpected pb.WatchResponse is received %+v", nr)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func TestV3WatchMultipleWatchersSynced(t *testing.T) {
|
|
|
defer testutil.AfterTest(t)
|
|
|
testV3WatchMultipleWatchers(t, 0)
|