Skip to content

Commit

Permalink
Merge pull request etcd-io#16515 from serathius/test-txn
Browse files Browse the repository at this point in the history
server: Test txn checking
  • Loading branch information
serathius authored Sep 1, 2023
2 parents 7666f97 + e1617f9 commit 2763392
Show file tree
Hide file tree
Showing 2 changed files with 251 additions and 3 deletions.
238 changes: 238 additions & 0 deletions server/etcdserver/txn/txn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (

"go.uber.org/zap/zaptest"

"go.etcd.io/etcd/pkg/v3/traceutil"

"go.etcd.io/etcd/api/v3/authpb"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
"go.etcd.io/etcd/server/v3/auth"
Expand All @@ -35,6 +37,242 @@ import (
"github.com/stretchr/testify/require"
)

func TestCheckTxn(t *testing.T) {

var futureRev int64 = 1000

tcs := []struct {
name string
compactRevision int64
setupLease int64
setupKey []byte
txn *pb.TxnRequest

expectError string
}{
{
name: "Range with revision 0 should succeed",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestRange{
RequestRange: &pb.RangeRequest{
Revision: 0,
},
},
},
},
},
},
{
name: "Range on future rev should fail",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestRange{
RequestRange: &pb.RangeRequest{
Revision: futureRev,
},
},
},
},
},
expectError: "mvcc: required revision is a future revision",
},
{
name: "Range on compacted rev should fail",
compactRevision: 10,
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestRange{
RequestRange: &pb.RangeRequest{
Revision: 9,
},
},
},
},
},
expectError: "mvcc: required revision has been compacted",
},
{
name: "Invalid range on Failed path should succeed",
txn: &pb.TxnRequest{
Failure: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestRange{
RequestRange: &pb.RangeRequest{
Revision: futureRev,
},
},
},
},
},
},
{
name: "Invalid range subtransaction should fail",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestTxn{
RequestTxn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestRange{
RequestRange: &pb.RangeRequest{
Revision: futureRev,
},
},
},
},
},
},
},
},
},
expectError: "mvcc: required revision is a future revision",
},
{
name: "Put without lease should succeed",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{},
},
},
},
},
},
{
name: "Put with non-existing lease should fail",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
Lease: 123,
},
},
},
},
},
expectError: "lease not found",
},
{
name: "Put with existing lease should succeed",
setupLease: 123,
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
Lease: 123,
},
},
},
},
},
},
{
name: "Put with ignore value without previous key should fail",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
IgnoreValue: true,
},
},
},
},
},
expectError: "etcdserver: key not found",
},
{
name: "Put with ignore lease without previous key should fail",
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
IgnoreLease: true,
},
},
},
},
},
expectError: "etcdserver: key not found",
},
{
name: "Put with ignore value with previous key should succeeded",
setupKey: []byte("ignore-value"),
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
IgnoreValue: true,
Key: []byte("ignore-value"),
},
},
},
},
},
},
{
name: "Put with ignore lease with previous key should succeed ",
setupKey: []byte("ignore-lease"),
txn: &pb.TxnRequest{
Success: []*pb.RequestOp{
{
Request: &pb.RequestOp_RequestPut{
RequestPut: &pb.PutRequest{
IgnoreLease: true,
Key: []byte("ignore-lease"),
},
},
},
},
},
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()

b, _ := betesting.NewDefaultTmpBackend(t)
defer betesting.Close(t, b)
lessor := &lease.FakeLessor{LeaseSet: map[lease.LeaseID]struct{}{}}
s := mvcc.NewStore(zaptest.NewLogger(t), b, lessor, mvcc.StoreConfig{})
defer s.Close()

if tc.compactRevision != 0 {
for i := 0; int64(i) < tc.compactRevision; i++ {
s.Put([]byte("a"), []byte("b"), 0)
}
s.Compact(traceutil.TODO(), tc.compactRevision)
}
if tc.setupLease != 0 {
lessor.Grant(lease.LeaseID(tc.setupLease), 0)
}
if len(tc.setupKey) != 0 {
s.Put(tc.setupKey, []byte("b"), 0)
}

_, _, err := Txn(ctx, zaptest.NewLogger(t), tc.txn, false, s, lessor)
gotErr := ""
if err != nil {
gotErr = err.Error()
}
if gotErr != tc.expectError {
t.Errorf("Error not matching, got %q, expected %q", gotErr, tc.expectError)
}
})
}
}

func TestReadonlyTxnError(t *testing.T) {
b, _ := betesting.NewDefaultTmpBackend(t)
defer betesting.Close(t, b)
Expand Down
16 changes: 13 additions & 3 deletions server/lease/lessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,13 +816,18 @@ func (le *lessor) initAndRecover() {

// FakeLessor is a fake implementation of Lessor interface.
// Used for testing only.
type FakeLessor struct{}
type FakeLessor struct {
LeaseSet map[LeaseID]struct{}
}

func (fl *FakeLessor) SetRangeDeleter(dr RangeDeleter) {}

func (fl *FakeLessor) SetCheckpointer(cp Checkpointer) {}

func (fl *FakeLessor) Grant(id LeaseID, ttl int64) (*Lease, error) { return nil, nil }
func (fl *FakeLessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
fl.LeaseSet[id] = struct{}{}
return nil, nil
}

func (fl *FakeLessor) Revoke(id LeaseID) error { return nil }

Expand All @@ -839,7 +844,12 @@ func (fl *FakeLessor) Demote() {}

func (fl *FakeLessor) Renew(id LeaseID) (int64, error) { return 10, nil }

func (fl *FakeLessor) Lookup(id LeaseID) *Lease { return nil }
func (fl *FakeLessor) Lookup(id LeaseID) *Lease {
if _, ok := fl.LeaseSet[id]; ok {
return &Lease{ID: id}
}
return nil
}

func (fl *FakeLessor) Leases() []*Lease { return nil }

Expand Down

0 comments on commit 2763392

Please sign in to comment.