Repository: etcd-io/etcd
File: tests/common/kv_test.go (Go)

Code before:

				_, err := cc.Put(ctx, key, value, config.PutOptions{})
				require.NoErrorf(t, err, "count not put key %q", key)
				resp, err := cc.Get(ctx, key, config.GetOptions{})
				require.NoErrorf(t, err, "count not get key %q, err: %s", key, err)
				assert.Lenf(t, resp.Kvs, 1, "Unexpected length of response, got %d", len(resp.Kvs))
				assert.Equalf(t, string(resp.Kvs[0].Key), key, "Unexpected key, want %q, got %q", key, resp.Kvs[0].Key)
				assert.Equalf(t, string(resp.Kvs[0].Value), value, "Unexpected value, want %q, got %q", value, resp.Kvs[0].Value)
			})
		})
	}
}

func TestKVGet(t *testing.T) {
	testRunner.BeforeTest(t)
	for _, tc := range clusterTestCases() {
		t.Run(tc.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(t.Context(), 30*time.Second)
			defer cancel()
			clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(tc.config))
			defer clus.Close()
			cc := testutils.MustClient(clus.Client())

			testutils.ExecuteUntil(ctx, t, func() {
				kvs := [][]string{
					{"a", "aa1"},
					{"b", "a"},
					{"c", "ac1"},
					{"c", "ac2"},
					{"c", "aac"},
					{"foo", "bar"},
					{"foo/abc", "0"},
					{"fop", "s"},
				}

				var firstHeader *etcdserverpb.ResponseHeader
				for i := range kvs {
					resp, err := cc.Put(ctx, kvs[i][0], kvs[i][1], config.PutOptions{})
					require.NoErrorf(t, err, "count not put key value %q", kvs[i])
					if i == 0 {
						firstHeader = resp.Header
					}
				}

				firstRev := firstHeader.Revision
				kvA := createKV("a", "aa1", firstRev, firstRev, 1)
				kvB := createKV("b", "a", firstRev+1, firstRev+1, 1)
				kvCV1 := createKV("c", "ac1", firstRev+2, firstRev+2, 1)
				kvCV2 := createKV("c", "ac2", firstRev+2, firstRev+3, 2)
				kvC := createKV("c", "aac", firstRev+2, firstRev+4, 3)
				kvFoo := createKV("foo", "bar", firstRev+5, firstRev+5, 1)

Review comment (suggestion):
Instead of maintaining two separete sources of keys/values I recommend to have one list:

```
				kvA := createKV("a", "aa1", firstRev, firstRev, 1)
				kvB := createKV("b", "a", firstRev+1, firstRev+1, 1)
				kvCV1 := createKV("c", "ac1", firstRev+2, firstRev+2, 1)
				kvCV2 := createKV("c", "ac2", firstRev+2, firstRev+3, 2)
				kvC := createKV("c", "aac", firstRev+2, firstRev+4, 3)
				kvFoo := createKV("foo", "bar", firstRev+5, firstRev+5, 1)
				kvFooAbc := createKV("foo/abc", "0", firstRev+6, firstRev+6, 1)
				kvFop := createKV("fop", "s", firstRev+7, firstRev+7, 1)
				allKvs := []*mvccpb.KeyValue{kvA, kvB, kvC, kvFoo, kvFooAbc, kvFop}
				
				var firstHeader *etcdserverpb.ResponseHeader
				for i := range allKvs {
					resp, err := cc.Put(ctx, allKvs[i].Key, allKvs[i].Value, config.PutOptions{})
					require.NoErrorf(t, err, "count not put key value %q", kvs[i])
					if i == 0 {
						firstHeader = resp.Header
					}
				}
```

Code after:

				_, err := cc.Put(ctx, key, value, config.PutOptions{})
				require.NoErrorf(t, err, "count not put key %q", key)
				resp, err := cc.Get(ctx, key, config.GetOptions{})
				require.NoErrorf(t, err, "count not get key %q, err: %s", key, err)
				assert.Lenf(t, resp.Kvs, 1, "Unexpected length of response, got %d", len(resp.Kvs))
				assert.Equalf(t, string(resp.Kvs[0].Key), key, "Unexpected key, want %q, got %q", key, resp.Kvs[0].Key)
				assert.Equalf(t, string(resp.Kvs[0].Value), value, "Unexpected value, want %q, got %q", value, resp.Kvs[0].Value)
			})
		})
	}
}

func TestKVGet(t *testing.T) {
	testRunner.BeforeTest(t)
	for _, tc := range clusterTestCases() {
		t.Run(tc.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(t.Context(), 30*time.Second)
			defer cancel()
			clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(tc.config))
			defer clus.Close()
			cc := testutils.MustClient(clus.Client())

			testutils.ExecuteUntil(ctx, t, func() {
				resp, err := cc.Get(ctx, "", config.GetOptions{Prefix: true})
				require.NoError(t, err)
				firstRev := resp.Header.Revision

				kvA := createKV("a", "aa1", firstRev+1, firstRev+1, 1)
				kvB := createKV("b", "a", firstRev+2, firstRev+2, 1)
				kvCV1 := createKV("c", "ac1", firstRev+3, firstRev+3, 1)
				kvCV2 := createKV("c", "ac2", firstRev+3, firstRev+4, 2)
				kvC := createKV("c", "aac", firstRev+3, firstRev+5, 3)
				kvFoo := createKV("foo", "bar", firstRev+6, firstRev+6, 1)
				kvFooAbc := createKV("foo/abc", "0", firstRev+7, firstRev+7, 1)
				kvFop := createKV("fop", "s", firstRev+8, firstRev+8, 1)

				inputs := []*mvccpb.KeyValue{kvA, kvB, kvCV1, kvCV2, kvC, kvFoo, kvFooAbc, kvFop}
				for i := range inputs {
					_, putError := cc.Put(ctx, string(inputs[i].Key), string(inputs[i].Value), config.PutOptions{})
					require.NoErrorf(t, putError, "count not put key value %q", inputs[i])
				}

				allKvs := []*mvccpb.KeyValue{kvA, kvB, kvC, kvFoo, kvFooAbc, kvFop}
				kvsByVersion := []*mvccpb.KeyValue{kvA, kvB, kvFoo, kvFooAbc, kvFop, kvC}
				reversedKvs := []*mvccpb.KeyValue{kvFop, kvFooAbc, kvFoo, kvC, kvB, kvA}
				kvsByValue := []*mvccpb.KeyValue{kvFooAbc, kvB, kvA, kvC, kvFoo, kvFop}
				kvsByValueDesc := []*mvccpb.KeyValue{kvFop, kvFoo, kvC, kvA, kvB, kvFooAbc}

				currentResp, err := cc.Get(ctx, "", config.GetOptions{Prefix: true})
				require.NoError(t, err)