etcd/tests/common/txn_test.go
Piotr Tabor 9abc895122 Goimports: Apply automated fixing to test files as well.
Signed-off-by: Piotr Tabor <ptab@google.com>
2022-12-29 13:04:45 +01:00

156 lines
4.8 KiB
Go

// Copyright 2022 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/tests/v3/framework/config"
"go.etcd.io/etcd/tests/v3/framework/testutils"
)
type txnReq struct {
compare []string
ifSuccess []string
ifFail []string
results []string
}
func TestTxnSucc(t *testing.T) {
testRunner.BeforeTest(t)
reqs := []txnReq{
{
compare: []string{`value("key1") != "value2"`, `value("key2") != "value1"`},
ifSuccess: []string{"get key1", "get key2"},
results: []string{"SUCCESS", "key1", "value1", "key2", "value2"},
},
{
compare: []string{`version("key1") = "1"`, `version("key2") = "1"`},
ifSuccess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`},
ifFail: []string{`put key1 "fail"`, `put key2 "fail"`},
results: []string{"SUCCESS", "key1", "value1", "key2", "value2", "OK"},
},
{
compare: []string{`version("key \"with\" space") = "1"`},
ifSuccess: []string{`get "key \"with\" space"`},
results: []string{"SUCCESS", `key "with" space`, "value \x23"},
},
}
for _, cfg := range clusterTestCases() {
t.Run(cfg.name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(cfg.config))
defer clus.Close()
cc := testutils.MustClient(clus.Client())
testutils.ExecuteUntil(ctx, t, func() {
if err := cc.Put(ctx, "key1", "value1", config.PutOptions{}); err != nil {
t.Fatalf("could not create key:%s, value:%s", "key1", "value1")
}
if err := cc.Put(ctx, "key2", "value2", config.PutOptions{}); err != nil {
t.Fatalf("could not create key:%s, value:%s", "key2", "value2")
}
for _, req := range reqs {
resp, err := cc.Txn(ctx, req.compare, req.ifSuccess, req.ifFail, config.TxnOptions{
Interactive: true,
})
if err != nil {
t.Errorf("Txn returned error: %s", err)
}
assert.Equal(t, req.results, getRespValues(resp))
}
})
})
}
}
func TestTxnFail(t *testing.T) {
testRunner.BeforeTest(t)
reqs := []txnReq{
{
compare: []string{`version("key") < "0"`},
ifSuccess: []string{`put key "success"`},
ifFail: []string{`put key "fail"`},
results: []string{"FAILURE", "OK"},
},
{
compare: []string{`value("key1") != "value1"`},
ifSuccess: []string{`put key1 "success"`},
ifFail: []string{`put key1 "fail"`},
results: []string{"FAILURE", "OK"},
},
}
for _, cfg := range clusterTestCases() {
t.Run(cfg.name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(cfg.config))
defer clus.Close()
cc := testutils.MustClient(clus.Client())
testutils.ExecuteUntil(ctx, t, func() {
if err := cc.Put(ctx, "key1", "value1", config.PutOptions{}); err != nil {
t.Fatalf("could not create key:%s, value:%s", "key1", "value1")
}
for _, req := range reqs {
resp, err := cc.Txn(ctx, req.compare, req.ifSuccess, req.ifFail, config.TxnOptions{
Interactive: true,
})
if err != nil {
t.Errorf("Txn returned error: %s", err)
}
assert.Equal(t, req.results, getRespValues(resp))
}
})
})
}
}
func getRespValues(r *clientv3.TxnResponse) []string {
var ss []string
if r.Succeeded {
ss = append(ss, "SUCCESS")
} else {
ss = append(ss, "FAILURE")
}
for _, resp := range r.Responses {
switch v := resp.Response.(type) {
case *pb.ResponseOp_ResponseDeleteRange:
r := (clientv3.DeleteResponse)(*v.ResponseDeleteRange)
ss = append(ss, fmt.Sprintf("%d", r.Deleted))
case *pb.ResponseOp_ResponsePut:
r := (clientv3.PutResponse)(*v.ResponsePut)
ss = append(ss, "OK")
if r.PrevKv != nil {
ss = append(ss, string(r.PrevKv.Key), string(r.PrevKv.Value))
}
case *pb.ResponseOp_ResponseRange:
r := (clientv3.GetResponse)(*v.ResponseRange)
for _, kv := range r.Kvs {
ss = append(ss, string(kv.Key), string(kv.Value))
}
default:
ss = append(ss, fmt.Sprintf("\"Unknown\" : %q\n", fmt.Sprintf("%+v", v)))
}
}
return ss
}