etcdserver: reject v3 txns with duplicate put keys

An API check to support PR #4363; bad requests didn't return an error.
This commit is contained in:
Anthony Romano
2016-02-02 00:51:17 -08:00
parent 20673e384a
commit c5c5063efe
3 changed files with 145 additions and 3 deletions

View File

@ -84,12 +84,19 @@ func TestV3TxnTooManyOps(t *testing.T) {
kvc := clus.RandClient().KV
// unique keys
i := new(int)
keyf := func() []byte {
*i++
return []byte(fmt.Sprintf("key-%d", i))
}
addCompareOps := func(txn *pb.TxnRequest) {
txn.Compare = append(txn.Compare,
&pb.Compare{
Result: pb.Compare_GREATER,
Target: pb.Compare_CREATE,
Key: []byte("bar"),
Key: keyf(),
})
}
addSuccessOps := func(txn *pb.TxnRequest) {
@ -97,7 +104,7 @@ func TestV3TxnTooManyOps(t *testing.T) {
&pb.RequestUnion{
Request: &pb.RequestUnion_RequestPut{
RequestPut: &pb.PutRequest{
Key: []byte("bar"),
Key: keyf(),
Value: []byte("bar"),
},
},
@ -108,7 +115,7 @@ func TestV3TxnTooManyOps(t *testing.T) {
&pb.RequestUnion{
Request: &pb.RequestUnion_RequestPut{
RequestPut: &pb.PutRequest{
Key: []byte("bar"),
Key: keyf(),
Value: []byte("bar"),
},
},
@ -134,6 +141,72 @@ func TestV3TxnTooManyOps(t *testing.T) {
}
}
func TestV3TxnDuplicateKeys(t *testing.T) {
defer testutil.AfterTest(t)
clus := NewClusterV3(t, &ClusterConfig{Size: 3})
defer clus.Terminate(t)
putreq := &pb.RequestUnion{Request: &pb.RequestUnion_RequestPut{RequestPut: &pb.PutRequest{Key: []byte("abc"), Value: []byte("def")}}}
delKeyReq := &pb.RequestUnion{Request: &pb.RequestUnion_RequestDeleteRange{
RequestDeleteRange: &pb.DeleteRangeRequest{
Key: []byte("abc"),
},
},
}
delInRangeReq := &pb.RequestUnion{Request: &pb.RequestUnion_RequestDeleteRange{
RequestDeleteRange: &pb.DeleteRangeRequest{
Key: []byte("a"), RangeEnd: []byte("b"),
},
},
}
delOutOfRangeReq := &pb.RequestUnion{Request: &pb.RequestUnion_RequestDeleteRange{
RequestDeleteRange: &pb.DeleteRangeRequest{
Key: []byte("abb"), RangeEnd: []byte("abc"),
},
},
}
kvc := clus.RandClient().KV
tests := []struct {
txnSuccess []*pb.RequestUnion
werr error
}{
{
txnSuccess: []*pb.RequestUnion{putreq, putreq},
werr: v3rpc.ErrDuplicateKey,
},
{
txnSuccess: []*pb.RequestUnion{putreq, delKeyReq},
werr: v3rpc.ErrDuplicateKey,
},
{
txnSuccess: []*pb.RequestUnion{putreq, delInRangeReq},
werr: v3rpc.ErrDuplicateKey,
},
{
txnSuccess: []*pb.RequestUnion{delKeyReq, delInRangeReq, delKeyReq, delInRangeReq},
werr: nil,
},
{
txnSuccess: []*pb.RequestUnion{putreq, delOutOfRangeReq},
werr: nil,
},
}
for i, tt := range tests {
txn := &pb.TxnRequest{Success: tt.txnSuccess}
_, err := kvc.Txn(context.Background(), txn)
if err != tt.werr {
t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
}
}
}
// TestV3PutMissingLease ensures that a Put on a key with a bogus lease fails.
func TestV3PutMissingLease(t *testing.T) {
defer testutil.AfterTest(t)