diff --git a/integration/v3_grpc_test.go b/integration/v3_grpc_test.go index 7e1fa6c2e..b9c7dbc07 100644 --- a/integration/v3_grpc_test.go +++ b/integration/v3_grpc_test.go @@ -380,6 +380,95 @@ func TestV3TxnCmpHeaderRev(t *testing.T) { } } +// TestV3TxnRangeCompare tests range comparisons in txns +func TestV3TxnRangeCompare(t *testing.T) { + defer testutil.AfterTest(t) + clus := NewClusterV3(t, &ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + // put keys, named by expected revision + for _, k := range []string{"/a/2", "/a/3", "/a/4", "/f/5"} { + if _, err := clus.Client(0).Put(context.TODO(), k, "x"); err != nil { + t.Fatal(err) + } + } + + tests := []struct { + cmp pb.Compare + + wSuccess bool + }{ + { + // >= /a/; all create revs fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte{0}, + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{6}, + }, + true, + }, + { + // >= /a/; one create rev doesn't fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte{0}, + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{5}, + }, + false, + }, + { + // prefix /a/*; all create revs fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte("/a0"), + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{5}, + }, + true, + }, + { + // prefix /a/*; one create rev doesn't fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte("/a0"), + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{4}, + }, + false, + }, + { + // does not exist, does not succeed + pb.Compare{ + Key: []byte("/b/"), + RangeEnd: []byte("/b0"), + Target: pb.Compare_VALUE, + Result: pb.Compare_EQUAL, + TargetUnion: &pb.Compare_Value{[]byte("x")}, + }, + false, + }, + } + + kvc := toGRPC(clus.Client(0)).KV + for i, tt := range tests { + txn := &pb.TxnRequest{} + txn.Compare = append(txn.Compare, &tt.cmp) + tresp, err := kvc.Txn(context.TODO(), txn) + if err != nil { + t.Fatal(err) + } + if tt.wSuccess != tresp.Succeeded { + t.Errorf("#%d: expected %v, got %v", i, tt.wSuccess, tresp.Succeeded) + } + } +} + // TestV3PutIgnoreValue ensures that writes with ignore_value overwrites with previous key-value pair. func TestV3PutIgnoreValue(t *testing.T) { defer testutil.AfterTest(t)