1// Copyright 2016 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 15package e2e 16 17import "testing" 18 19func TestCtlV3TxnInteractiveSuccess(t *testing.T) { 20 testCtl(t, txnTestSuccess, withInteractive()) 21} 22func TestCtlV3TxnInteractiveSuccessNoTLS(t *testing.T) { 23 testCtl(t, txnTestSuccess, withInteractive(), withCfg(configNoTLS)) 24} 25func TestCtlV3TxnInteractiveSuccessClientTLS(t *testing.T) { 26 testCtl(t, txnTestSuccess, withInteractive(), withCfg(configClientTLS)) 27} 28func TestCtlV3TxnInteractiveSuccessPeerTLS(t *testing.T) { 29 testCtl(t, txnTestSuccess, withInteractive(), withCfg(configPeerTLS)) 30} 31func TestCtlV3TxnInteractiveFail(t *testing.T) { 32 testCtl(t, txnTestFail, withInteractive()) 33} 34 35func txnTestSuccess(cx ctlCtx) { 36 if err := ctlV3Put(cx, "key1", "value1", ""); err != nil { 37 cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err) 38 } 39 if err := ctlV3Put(cx, "key2", "value2", ""); err != nil { 40 cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err) 41 } 42 rqs := []txnRequests{ 43 { 44 compare: []string{`value("key1") != "value2"`, `value("key2") != "value1"`}, 45 ifSucess: []string{"get key1", "get key2"}, 46 results: []string{"SUCCESS", "key1", "value1", "key2", "value2"}, 47 }, 48 { 49 compare: []string{`version("key1") = "1"`, `version("key2") = "1"`}, 50 ifSucess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`}, 51 ifFail: []string{`put key1 "fail"`, `put key2 "fail"`}, 52 results: []string{"SUCCESS", "key1", "value1", "key2", "value2"}, 53 }, 54 { 55 compare: []string{`version("key \"with\" space") = "1"`}, 56 ifSucess: []string{`get "key \"with\" space"`}, 57 results: []string{"SUCCESS", `key "with" space`, "value \x23"}, 58 }, 59 } 60 for _, rq := range rqs { 61 if err := ctlV3Txn(cx, rq); err != nil { 62 cx.t.Fatal(err) 63 } 64 } 65} 66 67func txnTestFail(cx ctlCtx) { 68 if err := ctlV3Put(cx, "key1", "value1", ""); err != nil { 69 cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err) 70 } 71 rqs := []txnRequests{ 72 { 73 compare: []string{`version("key") < "0"`}, 74 ifSucess: []string{`put key "success"`}, 75 ifFail: []string{`put key "fail"`}, 76 results: []string{"FAILURE", "OK"}, 77 }, 78 { 79 compare: []string{`value("key1") != "value1"`}, 80 ifSucess: []string{`put key1 "success"`}, 81 ifFail: []string{`put key1 "fail"`}, 82 results: []string{"FAILURE", "OK"}, 83 }, 84 } 85 for _, rq := range rqs { 86 if err := ctlV3Txn(cx, rq); err != nil { 87 cx.t.Fatal(err) 88 } 89 } 90} 91 92type txnRequests struct { 93 compare []string 94 ifSucess []string 95 ifFail []string 96 results []string 97} 98 99func ctlV3Txn(cx ctlCtx, rqs txnRequests) error { 100 // TODO: support non-interactive mode 101 cmdArgs := append(cx.PrefixArgs(), "txn") 102 if cx.interactive { 103 cmdArgs = append(cmdArgs, "--interactive") 104 } 105 proc, err := spawnCmd(cmdArgs) 106 if err != nil { 107 return err 108 } 109 _, err = proc.Expect("compares:") 110 if err != nil { 111 return err 112 } 113 for _, req := range rqs.compare { 114 if err = proc.Send(req + "\r"); err != nil { 115 return err 116 } 117 } 118 if err = proc.Send("\r"); err != nil { 119 return err 120 } 121 122 _, err = proc.Expect("success requests (get, put, delete):") 123 if err != nil { 124 return err 125 } 126 for _, req := range rqs.ifSucess { 127 if err = proc.Send(req + "\r"); err != nil { 128 return err 129 } 130 } 131 if err = proc.Send("\r"); err != nil { 132 return err 133 } 134 135 _, err = proc.Expect("failure requests (get, put, delete):") 136 if err != nil { 137 return err 138 } 139 for _, req := range rqs.ifFail { 140 if err = proc.Send(req + "\r"); err != nil { 141 return err 142 } 143 } 144 if err = proc.Send("\r"); err != nil { 145 return err 146 } 147 148 for _, line := range rqs.results { 149 _, err = proc.Expect(line) 150 if err != nil { 151 return err 152 } 153 } 154 return proc.Close() 155} 156