github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/common/txn_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  	"fmt"
    20  	"testing"
    21  	"time"
    22  
    23  	pb "github.com/lfch/etcd-io/api/v3/etcdserverpb"
    24  	clientv3 "github.com/lfch/etcd-io/client/v3"
    25  	"github.com/lfch/etcd-io/tests/v3/framework"
    26  	"github.com/lfch/etcd-io/tests/v3/framework/config"
    27  	"github.com/lfch/etcd-io/tests/v3/framework/testutils"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  type txnReq struct {
    32  	compare  []string
    33  	ifSucess []string
    34  	ifFail   []string
    35  	results  []string
    36  }
    37  
    38  func TestTxnSucc(t *testing.T) {
    39  	testRunner.BeforeTest(t)
    40  	reqs := []txnReq{
    41  		{
    42  			compare:  []string{`value("key1") != "value2"`, `value("key2") != "value1"`},
    43  			ifSucess: []string{"get key1", "get key2"},
    44  			results:  []string{"SUCCESS", "key1", "value1", "key2", "value2"},
    45  		},
    46  		{
    47  			compare:  []string{`version("key1") = "1"`, `version("key2") = "1"`},
    48  			ifSucess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`},
    49  			ifFail:   []string{`put key1 "fail"`, `put key2 "fail"`},
    50  			results:  []string{"SUCCESS", "key1", "value1", "key2", "value2", "OK"},
    51  		},
    52  		{
    53  			compare:  []string{`version("key \"with\" space") = "1"`},
    54  			ifSucess: []string{`get "key \"with\" space"`},
    55  			results:  []string{"SUCCESS", `key "with" space`, "value \x23"},
    56  		},
    57  	}
    58  	for _, cfg := range clusterTestCases {
    59  		t.Run(cfg.name, func(t *testing.T) {
    60  			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    61  			defer cancel()
    62  			clus := testRunner.NewCluster(ctx, t, cfg.config)
    63  			defer clus.Close()
    64  			cc := framework.MustClient(clus.Client(clientv3.AuthConfig{}))
    65  			testutils.ExecuteUntil(ctx, t, func() {
    66  				if err := cc.Put(ctx, "key1", "value1", config.PutOptions{}); err != nil {
    67  					t.Fatalf("could not create key:%s, value:%s", "key1", "value1")
    68  				}
    69  				if err := cc.Put(ctx, "key2", "value2", config.PutOptions{}); err != nil {
    70  					t.Fatalf("could not create key:%s, value:%s", "key2", "value2")
    71  				}
    72  				for _, req := range reqs {
    73  					resp, err := cc.Txn(ctx, req.compare, req.ifSucess, req.ifFail, config.TxnOptions{
    74  						Interactive: true,
    75  					})
    76  					if err != nil {
    77  						t.Errorf("Txn returned error: %s", err)
    78  					}
    79  					assert.Equal(t, req.results, getRespValues(resp))
    80  				}
    81  			})
    82  		})
    83  	}
    84  }
    85  
    86  func TestTxnFail(t *testing.T) {
    87  	testRunner.BeforeTest(t)
    88  	reqs := []txnReq{
    89  		{
    90  			compare:  []string{`version("key") < "0"`},
    91  			ifSucess: []string{`put key "success"`},
    92  			ifFail:   []string{`put key "fail"`},
    93  			results:  []string{"FAILURE", "OK"},
    94  		},
    95  		{
    96  			compare:  []string{`value("key1") != "value1"`},
    97  			ifSucess: []string{`put key1 "success"`},
    98  			ifFail:   []string{`put key1 "fail"`},
    99  			results:  []string{"FAILURE", "OK"},
   100  		},
   101  	}
   102  	for _, cfg := range clusterTestCases {
   103  		t.Run(cfg.name, func(t *testing.T) {
   104  			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   105  			defer cancel()
   106  			clus := testRunner.NewCluster(ctx, t, cfg.config)
   107  			defer clus.Close()
   108  			cc := framework.MustClient(clus.Client(clientv3.AuthConfig{}))
   109  			testutils.ExecuteUntil(ctx, t, func() {
   110  				if err := cc.Put(ctx, "key1", "value1", config.PutOptions{}); err != nil {
   111  					t.Fatalf("could not create key:%s, value:%s", "key1", "value1")
   112  				}
   113  				for _, req := range reqs {
   114  					resp, err := cc.Txn(ctx, req.compare, req.ifSucess, req.ifFail, config.TxnOptions{
   115  						Interactive: true,
   116  					})
   117  					if err != nil {
   118  						t.Errorf("Txn returned error: %s", err)
   119  					}
   120  					assert.Equal(t, req.results, getRespValues(resp))
   121  				}
   122  			})
   123  		})
   124  	}
   125  }
   126  
   127  func getRespValues(r *clientv3.TxnResponse) []string {
   128  	var ss []string
   129  	if r.Succeeded {
   130  		ss = append(ss, "SUCCESS")
   131  	} else {
   132  		ss = append(ss, "FAILURE")
   133  	}
   134  	for _, resp := range r.Responses {
   135  		switch v := resp.Response.(type) {
   136  		case *pb.ResponseOp_ResponseDeleteRange:
   137  			r := (clientv3.DeleteResponse)(*v.ResponseDeleteRange)
   138  			ss = append(ss, fmt.Sprintf("%d", r.Deleted))
   139  		case *pb.ResponseOp_ResponsePut:
   140  			r := (clientv3.PutResponse)(*v.ResponsePut)
   141  			ss = append(ss, "OK")
   142  			if r.PrevKv != nil {
   143  				ss = append(ss, string(r.PrevKv.Key), string(r.PrevKv.Value))
   144  			}
   145  		case *pb.ResponseOp_ResponseRange:
   146  			r := (clientv3.GetResponse)(*v.ResponseRange)
   147  			for _, kv := range r.Kvs {
   148  				ss = append(ss, string(kv.Key), string(kv.Value))
   149  			}
   150  		default:
   151  			ss = append(ss, fmt.Sprintf("\"Unknown\" : %q\n", fmt.Sprintf("%+v", v)))
   152  		}
   153  	}
   154  	return ss
   155  }