diff --git a/tests/robustness/validate/patch_history_test.go b/tests/robustness/validate/patch_history_test.go index bbdea8c198bb..bcc10e316da4 100644 --- a/tests/robustness/validate/patch_history_test.go +++ b/tests/robustness/validate/patch_history_test.go @@ -16,388 +16,356 @@ package validate import ( "errors" - "testing" - "time" - + "github.com/anishathalye/porcupine" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/robustness/identity" "go.etcd.io/etcd/tests/v3/robustness/model" "go.etcd.io/etcd/tests/v3/robustness/report" + "testing" + "time" ) func TestPatchHistory(t *testing.T) { for _, tc := range []struct { name string - historyFunc func(baseTime time.Time, h *model.AppendableHistory) - persistedRequest *model.EtcdRequest - expectedRemainingOperations int + historyFunc func(h *model.AppendableHistory) + persistedRequest []model.EtcdRequest + watchOperations []model.WatchOperation + expectedRemainingOperations []porcupine.Operation }{ { name: "successful range remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendRange("key", "", 0, 0, start, stop, &clientv3.GetResponse{}, nil) + historyFunc: func(h *model.AppendableHistory) { + h.AppendRange("key", "", 0, 0, 1, 2, &clientv3.GetResponse{}, nil) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: rangeResponse(0)}, }, - expectedRemainingOperations: 1, }, { name: "successful put remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPut("key", "value", start, stop, &clientv3.PutResponse{}, nil) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value"), - }, - }, - }, - }, + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key", "value", 1, 2, &clientv3.PutResponse{}, nil) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: putResponse(model.EtcdOperationResult{})}, }, - expectedRemainingOperations: 1, }, { - name: "failed put remains if there is a matching event", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPut("key", "value", start, stop, nil, errors.New("failed")) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value"), - }, - }, - }, - }, + name: "failed put remains if there is a matching event, return time untouched", + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key", "value", 1, 2, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000000, Output: model.MaybeEtcdResponse{Error: "failed"}}, + }, + }, + { + name: "failed put remains if there is a matching event, return time based on next persisted request", + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key1", "value", 1, 2, nil, errors.New("failed")) + h.AppendPut("key2", "value", 3, 4, &clientv3.PutResponse{}, nil) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key1", "value"), + putRequest("key2", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 3, Output: model.MaybeEtcdResponse{Error: "failed"}}, + {Return: 4, Output: putResponse(model.EtcdOperationResult{})}, + }, + }, + { + name: "failed put remains if there is a matching event, revision and return time based on watch", + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key", "value", 1, 2, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + watchOperations: watchPutEvent("key", "value", 2, 3), + expectedRemainingOperations: []porcupine.Operation{ + {Return: 3, Output: model.MaybeEtcdResponse{PartialResponse: true, EtcdResponse: model.EtcdResponse{Revision: 2}}}, }, - expectedRemainingOperations: 1, }, { name: "failed put is dropped if event has different key", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPut("key1", "value", start, stop, nil, errors.New("failed")) - start2 := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop2 := time.Since(baseTime) - h.AppendPut("key2", "value", start2, stop2, &clientv3.PutResponse{}, nil) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key2", - Value: model.ToValueOrHash("value"), - }, - }, - }, - }, + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key2", "value", 1, 2, &clientv3.PutResponse{}, nil) + h.AppendPut("key1", "value", 3, 4, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key2", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: putResponse(model.EtcdOperationResult{})}, }, - expectedRemainingOperations: 1, }, { name: "failed put is dropped if event has different value", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPut("key", "value1", start, stop, nil, errors.New("failed")) - start2 := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop2 := time.Since(baseTime) - h.AppendPut("key", "value2", start2, stop2, &clientv3.PutResponse{}, nil) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value2"), - }, - }, - }, - }, + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key", "value2", 1, 2, &clientv3.PutResponse{}, nil) + h.AppendPut("key", "value1", 3, 4, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value2"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: putResponse(model.EtcdOperationResult{})}, }, - expectedRemainingOperations: 1, }, { - name: "failed put with lease remains if there is a matching event", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPutWithLease("key", "value", 123, start, stop, nil, errors.New("failed")) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value"), - LeaseID: 123, - }, - }, - }, - }, + name: "failed put with lease remains if there is a matching event, return time untouched", + historyFunc: func(h *model.AppendableHistory) { + h.AppendPutWithLease("key", "value", 123, 1, 2, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequestWithLease("key", "value", 123), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000000, Output: model.MaybeEtcdResponse{Error: "failed"}}, + }, + }, + { + name: "failed put with lease remains if there is a matching event, return time based on next persisted request", + historyFunc: func(h *model.AppendableHistory) { + h.AppendPutWithLease("key1", "value", 123, 1, 2, nil, errors.New("failed")) + h.AppendPutWithLease("key2", "value", 234, 3, 4, &clientv3.PutResponse{}, nil) + }, + persistedRequest: []model.EtcdRequest{ + putRequestWithLease("key1", "value", 123), + putRequestWithLease("key2", "value", 234), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 3, Output: model.MaybeEtcdResponse{Error: "failed"}}, + {Return: 4, Output: putResponse(model.EtcdOperationResult{})}, }, - expectedRemainingOperations: 1, }, { name: "failed put is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPut("key", "value", start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendPut("key", "value", 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed put with lease is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendPutWithLease("key", "value", 123, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendPutWithLease("key", "value", 123, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "successful delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendDelete("key", start, stop, &clientv3.DeleteResponse{}, nil) + historyFunc: func(h *model.AppendableHistory) { + h.AppendDelete("key", 1, 2, &clientv3.DeleteResponse{}, nil) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: putResponse(model.EtcdOperationResult{})}, }, - expectedRemainingOperations: 1, - }, - { - name: "failed delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendDelete("key", start, stop, nil, errors.New("failed")) - }, - expectedRemainingOperations: 1, }, { - name: "successful empty txn remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{}, start, stop, &clientv3.TxnResponse{}, nil) - }, - expectedRemainingOperations: 1, + name: "failed delete remains, time untouched regardless of persisted event and watch", + historyFunc: func(h *model.AppendableHistory) { + h.AppendDelete("key", 1, 2, nil, errors.New("failed")) + h.AppendPut("key", "value", 3, 4, &clientv3.PutResponse{}, nil) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + watchOperations: watchDeleteEvent("key", 2, 3), + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000004, Output: model.MaybeEtcdResponse{Error: "failed"}}, + {Return: 4, Output: putResponse(model.EtcdOperationResult{})}, + }, }, { name: "failed empty txn is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed txn put is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed txn put remains if there is a matching event", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value"), - }, - }, - }, - }, + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000000, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "failed txn delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpDelete("key")}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpDelete("key")}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000001, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "successful txn put/delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{clientv3.OpDelete("key")}, start, stop, &clientv3.TxnResponse{}, nil) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{clientv3.OpDelete("key")}, 1, 2, &clientv3.TxnResponse{Succeeded: true}, nil) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 2, Output: putResponse()}, }, - expectedRemainingOperations: 1, }, { name: "failed txn put/delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{clientv3.OpDelete("key")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{clientv3.OpDelete("key")}, 1, 2, nil, errors.New("failed")) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000001, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "failed txn delete/put remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpDelete("key")}, []clientv3.Op{clientv3.OpPut("key", "value")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpDelete("key")}, []clientv3.Op{clientv3.OpPut("key", "value")}, 1, 2, nil, errors.New("failed")) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000001, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "failed txn empty/put is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpPut("key", "value")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpPut("key", "value")}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed txn empty/put remains if there is a matching event", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) - }, - persistedRequest: &model.EtcdRequest{ - Type: model.Txn, - Txn: &model.TxnRequest{ - OperationsOnSuccess: []model.EtcdOperation{ - { - Type: model.PutOperation, - Put: model.PutOptions{ - Key: "key", - Value: model.ToValueOrHash("value"), - }, - }, - }, - }, + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value")}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) + }, + persistedRequest: []model.EtcdRequest{ + putRequest("key", "value"), + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000000, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "failed txn empty/delete remains", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpDelete("key")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpDelete("key")}, 1, 2, nil, errors.New("failed")) + }, + expectedRemainingOperations: []porcupine.Operation{ + {Return: 1000000001, Output: model.MaybeEtcdResponse{Error: "failed"}}, }, - expectedRemainingOperations: 1, }, { name: "failed txn put&delete is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, []clientv3.Op{}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, []clientv3.Op{}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed txn empty/put&delete is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{}, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, { name: "failed txn put&delete/put&delete is dropped", - historyFunc: func(baseTime time.Time, h *model.AppendableHistory) { - start := time.Since(baseTime) - time.Sleep(time.Nanosecond) - stop := time.Since(baseTime) - h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, []clientv3.Op{clientv3.OpPut("key", "value2"), clientv3.OpDelete("key")}, start, stop, nil, errors.New("failed")) + historyFunc: func(h *model.AppendableHistory) { + h.AppendTxn(nil, []clientv3.Op{clientv3.OpPut("key", "value1"), clientv3.OpDelete("key")}, []clientv3.Op{clientv3.OpPut("key", "value2"), clientv3.OpDelete("key")}, 1, 2, nil, errors.New("failed")) }, - expectedRemainingOperations: 0, + expectedRemainingOperations: []porcupine.Operation{}, }, } { t.Run(tc.name, func(t *testing.T) { - baseTime := time.Now() history := model.NewAppendableHistory(identity.NewIDProvider()) - tc.historyFunc(baseTime, history) - requests := []model.EtcdRequest{} - if tc.persistedRequest != nil { - requests = append(requests, *tc.persistedRequest) - } + tc.historyFunc(history) operations := patchLinearizableOperations([]report.ClientReport{ { ClientID: 0, KeyValue: history.History.Operations(), - Watch: []model.WatchOperation{}, + Watch: tc.watchOperations, }, - }, requests) - if len(operations) != tc.expectedRemainingOperations { - t.Errorf("Unexpected remains, got: %d, want: %d", len(operations), tc.expectedRemainingOperations) + }, tc.persistedRequest) + if diff := cmp.Diff(tc.expectedRemainingOperations, operations, + cmpopts.EquateEmpty(), + cmpopts.IgnoreFields(porcupine.Operation{}, "Input", "Call", "ClientId"), + ); diff != "" { + t.Errorf("Response didn't match expected, diff:\n%s", diff) } }) } } + +func putResponse(result ...model.EtcdOperationResult) model.MaybeEtcdResponse { + return model.MaybeEtcdResponse{EtcdResponse: model.EtcdResponse{Txn: &model.TxnResponse{Results: result}}} +} + +func watchPutEvent(key, value string, revision, responseTime int64) []model.WatchOperation { + return []model.WatchOperation{ + { + Responses: []model.WatchResponse{ + { + Time: time.Duration(responseTime), + Events: []model.WatchEvent{ + { + PersistedEvent: model.PersistedEvent{ + Event: model.Event{ + Type: model.PutOperation, + Key: key, + Value: model.ToValueOrHash(value), + }, + Revision: revision, + }, + }, + }, + }, + }, + }, + } +} + +func watchDeleteEvent(key string, revision, responseTime int64) []model.WatchOperation { + return []model.WatchOperation{ + { + Responses: []model.WatchResponse{ + { + Time: time.Duration(responseTime), + Events: []model.WatchEvent{ + { + PersistedEvent: model.PersistedEvent{ + Event: model.Event{ + Type: model.DeleteOperation, + Key: key, + }, + Revision: revision, + }, + }, + }, + }, + }, + }, + } +} diff --git a/tests/robustness/validate/validate_test.go b/tests/robustness/validate/validate_test.go index bfb03267d7e9..b74d1e4a0b85 100644 --- a/tests/robustness/validate/validate_test.go +++ b/tests/robustness/validate/validate_test.go @@ -1960,6 +1960,12 @@ func putRequest(key, value string) model.EtcdRequest { } } +func putRequestWithLease(key, value string, leaseID int64) model.EtcdRequest { + req := putRequest(key, value) + req.Txn.OperationsOnSuccess[0].Put.LeaseID = leaseID + return req +} + func deleteRequest(key string) model.EtcdRequest { return model.EtcdRequest{ Type: model.Txn,