Merge pull request #16044 from serathius/robusness-empty
tests/robustness: Assume starting from empty etcd instead of throwing out first failed requestdependabot/go_modules/github.com/prometheus/procfs-0.11.0
commit
a6ab774458
|
@ -70,12 +70,8 @@ func (s etcdState) Step(request EtcdRequest, response EtcdResponse) (bool, etcdS
|
||||||
|
|
||||||
// initState tries to create etcd state based on the first request.
|
// initState tries to create etcd state based on the first request.
|
||||||
func initState(request EtcdRequest, response EtcdResponse) etcdState {
|
func initState(request EtcdRequest, response EtcdResponse) etcdState {
|
||||||
state := etcdState{
|
state := emptyState()
|
||||||
Revision: response.Revision,
|
state.Revision = response.Revision
|
||||||
KeyValues: map[string]ValueRevision{},
|
|
||||||
KeyLeases: map[string]int64{},
|
|
||||||
Leases: map[int64]EtcdLease{},
|
|
||||||
}
|
|
||||||
switch request.Type {
|
switch request.Type {
|
||||||
case Txn:
|
case Txn:
|
||||||
if response.Txn.Failure {
|
if response.Txn.Failure {
|
||||||
|
@ -118,6 +114,15 @@ func initState(request EtcdRequest, response EtcdResponse) etcdState {
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func emptyState() etcdState {
|
||||||
|
return etcdState{
|
||||||
|
Revision: 1,
|
||||||
|
KeyValues: map[string]ValueRevision{},
|
||||||
|
KeyLeases: map[string]int64{},
|
||||||
|
Leases: map[int64]EtcdLease{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// step handles a successful request, returning updated state and response it would generate.
|
// step handles a successful request, returning updated state and response it would generate.
|
||||||
func (s etcdState) step(request EtcdRequest) (etcdState, EtcdResponse) {
|
func (s etcdState) step(request EtcdRequest) (etcdState, EtcdResponse) {
|
||||||
newKVs := map[string]ValueRevision{}
|
newKVs := map[string]ValueRevision{}
|
||||||
|
|
|
@ -71,11 +71,10 @@ type EtcdNonDeterministicResponse struct {
|
||||||
|
|
||||||
func (states nonDeterministicState) Step(request EtcdRequest, response EtcdNonDeterministicResponse) (bool, nonDeterministicState) {
|
func (states nonDeterministicState) Step(request EtcdRequest, response EtcdNonDeterministicResponse) (bool, nonDeterministicState) {
|
||||||
if len(states) == 0 {
|
if len(states) == 0 {
|
||||||
// states were not initialized
|
if response.Err == nil && !response.ResultUnknown {
|
||||||
if response.Err != nil || response.ResultUnknown || response.Revision == 0 {
|
return true, nonDeterministicState{initState(request, response.EtcdResponse)}
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
return true, initNonDeterministicState(request, response)
|
states = nonDeterministicState{emptyState()}
|
||||||
}
|
}
|
||||||
var newStates nonDeterministicState
|
var newStates nonDeterministicState
|
||||||
if response.Err != nil {
|
if response.Err != nil {
|
||||||
|
@ -86,10 +85,6 @@ func (states nonDeterministicState) Step(request EtcdRequest, response EtcdNonDe
|
||||||
return len(newStates) > 0, newStates
|
return len(newStates) > 0, newStates
|
||||||
}
|
}
|
||||||
|
|
||||||
func initNonDeterministicState(request EtcdRequest, response EtcdNonDeterministicResponse) nonDeterministicState {
|
|
||||||
return nonDeterministicState{initState(request, response.EtcdResponse)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stepFailedRequest duplicates number of states by considering request persisted and lost.
|
// stepFailedRequest duplicates number of states by considering request persisted and lost.
|
||||||
func (states nonDeterministicState) stepFailedRequest(request EtcdRequest) nonDeterministicState {
|
func (states nonDeterministicState) stepFailedRequest(request EtcdRequest) nonDeterministicState {
|
||||||
newStates := make(nonDeterministicState, 0, len(states)*2)
|
newStates := make(nonDeterministicState, 0, len(states)*2)
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestModelNonDeterministic(t *testing.T) {
|
func TestModelNonDeterministic(t *testing.T) {
|
||||||
|
@ -30,6 +32,22 @@ func TestModelNonDeterministic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nonDeterministicTestScenarios = append(nonDeterministicTestScenarios, []nonDeterministicModelTest{
|
nonDeterministicTestScenarios = append(nonDeterministicTestScenarios, []nonDeterministicModelTest{
|
||||||
|
{
|
||||||
|
name: "First Put request fails, but is persisted",
|
||||||
|
operations: []nonDeterministicOperation{
|
||||||
|
{req: putRequest("key1", "1"), resp: failedResponse(errors.New("failed"))},
|
||||||
|
{req: putRequest("key2", "2"), resp: putResponse(3)},
|
||||||
|
{req: rangeRequest("key", true, 0), resp: rangeResponse([]*mvccpb.KeyValue{{Key: []byte("key1"), Value: []byte("1"), ModRevision: 2}, {Key: []byte("key2"), Value: []byte("2"), ModRevision: 3}}, 2, 3)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "First Put request fails, and is lost",
|
||||||
|
operations: []nonDeterministicOperation{
|
||||||
|
{req: putRequest("key1", "1"), resp: failedResponse(errors.New("failed"))},
|
||||||
|
{req: putRequest("key2", "2"), resp: putResponse(2)},
|
||||||
|
{req: rangeRequest("key", true, 0), resp: rangeResponse([]*mvccpb.KeyValue{{Key: []byte("key2"), Value: []byte("2"), ModRevision: 2}}, 1, 2)},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Put can fail and be lost before get",
|
name: "Put can fail and be lost before get",
|
||||||
operations: []nonDeterministicOperation{
|
operations: []nonDeterministicOperation{
|
||||||
|
|
Loading…
Reference in New Issue