github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/integration/clientv3/ordering_kv_test.go (about) 1 // Copyright 2017 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package clientv3test 16 17 import ( 18 "context" 19 "errors" 20 "testing" 21 "time" 22 23 "github.com/lfch/etcd-io/client/v3" 24 "github.com/lfch/etcd-io/client/v3/ordering" 25 integration2 "github.com/lfch/etcd-io/tests/v3/framework/integration" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestDetectKvOrderViolation(t *testing.T) { 30 var errOrderViolation = errors.New("DetectedOrderViolation") 31 32 integration2.BeforeTest(t) 33 clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) 34 defer clus.Terminate(t) 35 36 cfg := clientv3.Config{ 37 Endpoints: []string{ 38 clus.Members[0].GRPCURL(), 39 clus.Members[1].GRPCURL(), 40 clus.Members[2].GRPCURL(), 41 }, 42 } 43 cli, err := integration2.NewClient(t, cfg) 44 if err != nil { 45 t.Fatal(err) 46 } 47 defer func() { assert.NoError(t, cli.Close()) }() 48 ctx := context.TODO() 49 50 if _, err = clus.Client(0).Put(ctx, "foo", "bar"); err != nil { 51 t.Fatal(err) 52 } 53 // ensure that the second member has the current revision for the key foo 54 if _, err = clus.Client(1).Get(ctx, "foo"); err != nil { 55 t.Fatal(err) 56 } 57 58 // stop third member in order to force the member to have an outdated revision 59 clus.Members[2].Stop(t) 60 time.Sleep(1 * time.Second) // give enough time for operation 61 _, err = cli.Put(ctx, "foo", "buzz") 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 // perform get request against the first member, in order to 67 // set up kvOrdering to expect "foo" revisions greater than that of 68 // the third member. 69 orderingKv := ordering.NewKV(cli.KV, 70 func(op clientv3.Op, resp clientv3.OpResponse, prevRev int64) error { 71 return errOrderViolation 72 }) 73 v, err := orderingKv.Get(ctx, "foo") 74 if err != nil { 75 t.Fatal(err) 76 } 77 t.Logf("Read from the first member: v:%v err:%v", v, err) 78 assert.Equal(t, []byte("buzz"), v.Kvs[0].Value) 79 80 // ensure that only the third member is queried during requests 81 clus.Members[0].Stop(t) 82 clus.Members[1].Stop(t) 83 assert.NoError(t, clus.Members[2].Restart(t)) 84 // force OrderingKv to query the third member 85 cli.SetEndpoints(clus.Members[2].GRPCURL()) 86 time.Sleep(2 * time.Second) // FIXME: Figure out how pause SetEndpoints sufficiently that this is not needed 87 88 t.Logf("Quering m2 after restart") 89 v, err = orderingKv.Get(ctx, "foo", clientv3.WithSerializable()) 90 t.Logf("Quering m2 returned: v:%v erro:%v ", v, err) 91 if err != errOrderViolation { 92 t.Fatalf("expected %v, got err:%v v:%v", errOrderViolation, err, v) 93 } 94 } 95 96 func TestDetectTxnOrderViolation(t *testing.T) { 97 var errOrderViolation = errors.New("DetectedOrderViolation") 98 99 integration2.BeforeTest(t) 100 clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) 101 defer clus.Terminate(t) 102 103 cfg := clientv3.Config{ 104 Endpoints: []string{ 105 clus.Members[0].GRPCURL(), 106 clus.Members[1].GRPCURL(), 107 clus.Members[2].GRPCURL(), 108 }, 109 } 110 cli, err := integration2.NewClient(t, cfg) 111 if err != nil { 112 t.Fatal(err) 113 } 114 defer func() { assert.NoError(t, cli.Close()) }() 115 ctx := context.TODO() 116 117 if _, err = clus.Client(0).Put(ctx, "foo", "bar"); err != nil { 118 t.Fatal(err) 119 } 120 // ensure that the second member has the current revision for the key foo 121 if _, err = clus.Client(1).Get(ctx, "foo"); err != nil { 122 t.Fatal(err) 123 } 124 125 // stop third member in order to force the member to have an outdated revision 126 clus.Members[2].Stop(t) 127 time.Sleep(1 * time.Second) // give enough time for operation 128 if _, err = clus.Client(1).Put(ctx, "foo", "buzz"); err != nil { 129 t.Fatal(err) 130 } 131 132 // perform get request against the first member, in order to 133 // set up kvOrdering to expect "foo" revisions greater than that of 134 // the third member. 135 orderingKv := ordering.NewKV(cli.KV, 136 func(op clientv3.Op, resp clientv3.OpResponse, prevRev int64) error { 137 return errOrderViolation 138 }) 139 orderingTxn := orderingKv.Txn(ctx) 140 _, err = orderingTxn.If( 141 clientv3.Compare(clientv3.Value("b"), ">", "a"), 142 ).Then( 143 clientv3.OpGet("foo"), 144 ).Commit() 145 if err != nil { 146 t.Fatal(err) 147 } 148 149 // ensure that only the third member is queried during requests 150 clus.Members[0].Stop(t) 151 clus.Members[1].Stop(t) 152 assert.NoError(t, clus.Members[2].Restart(t)) 153 // force OrderingKv to query the third member 154 cli.SetEndpoints(clus.Members[2].GRPCURL()) 155 time.Sleep(2 * time.Second) // FIXME: Figure out how pause SetEndpoints sufficiently that this is not needed 156 _, err = orderingKv.Get(ctx, "foo", clientv3.WithSerializable()) 157 if err != errOrderViolation { 158 t.Fatalf("expected %v, got %v", errOrderViolation, err) 159 } 160 orderingTxn = orderingKv.Txn(ctx) 161 _, err = orderingTxn.If( 162 clientv3.Compare(clientv3.Value("b"), ">", "a"), 163 ).Then( 164 clientv3.OpGet("foo", clientv3.WithSerializable()), 165 ).Commit() 166 if err != errOrderViolation { 167 t.Fatalf("expected %v, got %v", errOrderViolation, err) 168 } 169 }