Merge pull request #16044 from serathius/robusness-empty

tests/robustness: Assume starting from empty etcd instead of throwing out first failed request
dependabot/go_modules/github.com/prometheus/procfs-0.11.0
Marek Siarkowicz 2023-06-12 10:18:34 +02:00 committed by GitHub
commit a6ab774458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 14 deletions

View File

@ -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.
func initState(request EtcdRequest, response EtcdResponse) etcdState {
state := etcdState{
Revision: response.Revision,
KeyValues: map[string]ValueRevision{},
KeyLeases: map[string]int64{},
Leases: map[int64]EtcdLease{},
}
state := emptyState()
state.Revision = response.Revision
switch request.Type {
case Txn:
if response.Txn.Failure {
@ -118,6 +114,15 @@ func initState(request EtcdRequest, response EtcdResponse) etcdState {
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.
func (s etcdState) step(request EtcdRequest) (etcdState, EtcdResponse) {
newKVs := map[string]ValueRevision{}

View File

@ -71,11 +71,10 @@ type EtcdNonDeterministicResponse struct {
func (states nonDeterministicState) Step(request EtcdRequest, response EtcdNonDeterministicResponse) (bool, nonDeterministicState) {
if len(states) == 0 {
// states were not initialized
if response.Err != nil || response.ResultUnknown || response.Revision == 0 {
return true, nil
if response.Err == nil && !response.ResultUnknown {
return true, nonDeterministicState{initState(request, response.EtcdResponse)}
}
return true, initNonDeterministicState(request, response)
states = nonDeterministicState{emptyState()}
}
var newStates nonDeterministicState
if response.Err != nil {
@ -86,10 +85,6 @@ func (states nonDeterministicState) Step(request EtcdRequest, response EtcdNonDe
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.
func (states nonDeterministicState) stepFailedRequest(request EtcdRequest) nonDeterministicState {
newStates := make(nonDeterministicState, 0, len(states)*2)

View File

@ -21,6 +21,8 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"go.etcd.io/etcd/api/v3/mvccpb"
)
func TestModelNonDeterministic(t *testing.T) {
@ -30,6 +32,22 @@ func TestModelNonDeterministic(t *testing.T) {
}
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",
operations: []nonDeterministicOperation{