github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/common/kv_test.go (about)

     1  // Copyright 2022 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 common
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	clientv3 "github.com/lfch/etcd-io/client/v3"
    23  	"github.com/lfch/etcd-io/tests/v3/framework"
    24  	"github.com/lfch/etcd-io/tests/v3/framework/config"
    25  	"github.com/lfch/etcd-io/tests/v3/framework/testutils"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  func TestKVPut(t *testing.T) {
    30  	testRunner.BeforeTest(t)
    31  	for _, tc := range clusterTestCases {
    32  		t.Run(tc.name, func(t *testing.T) {
    33  			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    34  			defer cancel()
    35  			clus := testRunner.NewCluster(ctx, t, tc.config)
    36  			defer clus.Close()
    37  			cc := framework.MustClient(clus.Client(clientv3.AuthConfig{}))
    38  
    39  			testutils.ExecuteUntil(ctx, t, func() {
    40  				key, value := "foo", "bar"
    41  
    42  				if err := cc.Put(ctx, key, value, config.PutOptions{}); err != nil {
    43  					t.Fatalf("count not put key %q, err: %s", key, err)
    44  				}
    45  				resp, err := cc.Get(ctx, key, config.GetOptions{})
    46  				if err != nil {
    47  					t.Fatalf("count not get key %q, err: %s", key, err)
    48  				}
    49  				if len(resp.Kvs) != 1 {
    50  					t.Errorf("Unexpected lenth of response, got %d", len(resp.Kvs))
    51  				}
    52  				if string(resp.Kvs[0].Key) != key {
    53  					t.Errorf("Unexpected key, want %q, got %q", key, resp.Kvs[0].Key)
    54  				}
    55  				if string(resp.Kvs[0].Value) != value {
    56  					t.Errorf("Unexpected value, want %q, got %q", value, resp.Kvs[0].Value)
    57  				}
    58  			})
    59  		})
    60  	}
    61  }
    62  
    63  func TestKVGet(t *testing.T) {
    64  	testRunner.BeforeTest(t)
    65  	for _, tc := range clusterTestCases {
    66  		t.Run(tc.name, func(t *testing.T) {
    67  			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    68  			defer cancel()
    69  			clus := testRunner.NewCluster(ctx, t, tc.config)
    70  			defer clus.Close()
    71  			cc := framework.MustClient(clus.Client(clientv3.AuthConfig{}))
    72  
    73  			testutils.ExecuteUntil(ctx, t, func() {
    74  				var (
    75  					kvs          = []string{"a", "b", "c", "c", "c", "foo", "foo/abc", "fop"}
    76  					wantKvs      = []string{"a", "b", "c", "foo", "foo/abc", "fop"}
    77  					kvsByVersion = []string{"a", "b", "foo", "foo/abc", "fop", "c"}
    78  					reversedKvs  = []string{"fop", "foo/abc", "foo", "c", "b", "a"}
    79  				)
    80  
    81  				for i := range kvs {
    82  					if err := cc.Put(ctx, kvs[i], "bar", config.PutOptions{}); err != nil {
    83  						t.Fatalf("count not put key %q, err: %s", kvs[i], err)
    84  					}
    85  				}
    86  				tests := []struct {
    87  					begin   string
    88  					end     string
    89  					options config.GetOptions
    90  
    91  					wkv []string
    92  				}{
    93  					{begin: "a", wkv: wantKvs[:1]},
    94  					{begin: "a", options: config.GetOptions{Serializable: true}, wkv: wantKvs[:1]},
    95  					{begin: "a", options: config.GetOptions{End: "c"}, wkv: wantKvs[:2]},
    96  					{begin: "", options: config.GetOptions{Prefix: true}, wkv: wantKvs},
    97  					{begin: "", options: config.GetOptions{FromKey: true}, wkv: wantKvs},
    98  					{begin: "a", options: config.GetOptions{End: "x"}, wkv: wantKvs},
    99  					{begin: "", options: config.GetOptions{Prefix: true, Revision: 4}, wkv: kvs[:3]},
   100  					{begin: "a", options: config.GetOptions{CountOnly: true}, wkv: nil},
   101  					{begin: "foo", options: config.GetOptions{Prefix: true}, wkv: []string{"foo", "foo/abc"}},
   102  					{begin: "foo", options: config.GetOptions{FromKey: true}, wkv: []string{"foo", "foo/abc", "fop"}},
   103  					{begin: "", options: config.GetOptions{Prefix: true, Limit: 2}, wkv: wantKvs[:2]},
   104  					{begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByModRevision}, wkv: wantKvs},
   105  					{begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByVersion}, wkv: kvsByVersion},
   106  					{begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortNone, SortBy: clientv3.SortByCreateRevision}, wkv: wantKvs},
   107  					{begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByCreateRevision}, wkv: reversedKvs},
   108  					{begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByKey}, wkv: reversedKvs},
   109  				}
   110  				for _, tt := range tests {
   111  					resp, err := cc.Get(ctx, tt.begin, tt.options)
   112  					if err != nil {
   113  						t.Fatalf("count not get key %q, err: %s", tt.begin, err)
   114  					}
   115  					kvs := testutils.KeysFromGetResponse(resp)
   116  					assert.Equal(t, tt.wkv, kvs)
   117  				}
   118  			})
   119  		})
   120  	}
   121  }
   122  
   123  func TestKVDelete(t *testing.T) {
   124  	testRunner.BeforeTest(t)
   125  	for _, tc := range clusterTestCases {
   126  		t.Run(tc.name, func(t *testing.T) {
   127  			ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
   128  			defer cancel()
   129  			clus := testRunner.NewCluster(ctx, t, tc.config)
   130  			defer clus.Close()
   131  			cc := framework.MustClient(clus.Client(clientv3.AuthConfig{}))
   132  			testutils.ExecuteUntil(ctx, t, func() {
   133  				kvs := []string{"a", "b", "c", "c/abc", "d"}
   134  				tests := []struct {
   135  					deleteKey string
   136  					options   config.DeleteOptions
   137  
   138  					wantDeleted int
   139  					wantKeys    []string
   140  				}{
   141  					{ // delete all keys
   142  						deleteKey:   "",
   143  						options:     config.DeleteOptions{Prefix: true},
   144  						wantDeleted: 5,
   145  					},
   146  					{ // delete all keys
   147  						deleteKey:   "",
   148  						options:     config.DeleteOptions{FromKey: true},
   149  						wantDeleted: 5,
   150  					},
   151  					{
   152  						deleteKey:   "a",
   153  						options:     config.DeleteOptions{End: "c"},
   154  						wantDeleted: 2,
   155  						wantKeys:    []string{"c", "c/abc", "d"},
   156  					},
   157  					{
   158  						deleteKey:   "c",
   159  						wantDeleted: 1,
   160  						wantKeys:    []string{"a", "b", "c/abc", "d"},
   161  					},
   162  					{
   163  						deleteKey:   "c",
   164  						options:     config.DeleteOptions{Prefix: true},
   165  						wantDeleted: 2,
   166  						wantKeys:    []string{"a", "b", "d"},
   167  					},
   168  					{
   169  						deleteKey:   "c",
   170  						options:     config.DeleteOptions{FromKey: true},
   171  						wantDeleted: 3,
   172  						wantKeys:    []string{"a", "b"},
   173  					},
   174  					{
   175  						deleteKey:   "e",
   176  						wantDeleted: 0,
   177  						wantKeys:    kvs,
   178  					},
   179  				}
   180  				for _, tt := range tests {
   181  					for i := range kvs {
   182  						if err := cc.Put(ctx, kvs[i], "bar", config.PutOptions{}); err != nil {
   183  							t.Fatalf("count not put key %q, err: %s", kvs[i], err)
   184  						}
   185  					}
   186  					del, err := cc.Delete(ctx, tt.deleteKey, tt.options)
   187  					if err != nil {
   188  						t.Fatalf("count not get key %q, err: %s", tt.deleteKey, err)
   189  					}
   190  					assert.Equal(t, tt.wantDeleted, int(del.Deleted))
   191  					get, err := cc.Get(ctx, "", config.GetOptions{Prefix: true})
   192  					if err != nil {
   193  						t.Fatalf("count not get key, err: %s", err)
   194  					}
   195  					kvs := testutils.KeysFromGetResponse(get)
   196  					assert.Equal(t, tt.wantKeys, kvs)
   197  				}
   198  			})
   199  		})
   200  	}
   201  }
   202  
   203  func TestKVGetNoQuorum(t *testing.T) {
   204  	testRunner.BeforeTest(t)
   205  	tcs := []struct {
   206  		name    string
   207  		options config.GetOptions
   208  
   209  		wantError bool
   210  	}{
   211  		{
   212  			name:    "Serializable",
   213  			options: config.GetOptions{Serializable: true},
   214  		},
   215  		{
   216  			name:      "Linearizable",
   217  			options:   config.GetOptions{Serializable: false, Timeout: time.Second},
   218  			wantError: true,
   219  		},
   220  	}
   221  	for _, tc := range tcs {
   222  		t.Run(tc.name, func(t *testing.T) {
   223  			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   224  			defer cancel()
   225  			clus := testRunner.NewCluster(ctx, t, config.ClusterConfig{ClusterSize: 3})
   226  			defer clus.Close()
   227  
   228  			clus.Members()[0].Stop()
   229  			clus.Members()[1].Stop()
   230  
   231  			cc := clus.Members()[2].Client()
   232  			testutils.ExecuteUntil(ctx, t, func() {
   233  				key := "foo"
   234  				_, err := cc.Get(ctx, key, tc.options)
   235  				gotError := err != nil
   236  				if gotError != tc.wantError {
   237  					t.Fatalf("Unexpeted result, wantError: %v, gotErr: %v, err: %s", tc.wantError, gotError, err)
   238  				}
   239  			})
   240  		})
   241  	}
   242  }