robustness: change mixedVersionOption to use ChoiceWeight.

Signed-off-by: Siyuan Zhang <sizhang@google.com>
This commit is contained in:
Siyuan Zhang 2024-06-17 15:50:32 -07:00
parent debc8fb00b
commit fff58bb809
4 changed files with 57 additions and 58 deletions

View File

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package traffic
package random
import (
"math/rand"
"strings"
)
func randString(size int) string {
func RandString(size int) string {
data := strings.Builder{}
data.Grow(size)
for i := 0; i < size; i++ {
@ -28,22 +28,22 @@ func randString(size int) string {
return data.String()
}
type choiceWeight[T any] struct {
choice T
weight int
type ChoiceWeight[T any] struct {
Choice T
Weight int
}
func pickRandom[T any](choices []choiceWeight[T]) T {
func PickRandom[T any](choices []ChoiceWeight[T]) T {
sum := 0
for _, op := range choices {
sum += op.weight
sum += op.Weight
}
roll := rand.Int() % sum
for _, op := range choices {
if roll < op.weight {
return op.choice
if roll < op.Weight {
return op.Choice
}
roll -= op.weight
roll -= op.Weight
}
panic("unexpected")
}

View File

@ -24,6 +24,7 @@ import (
"go.etcd.io/etcd/tests/v3/framework/e2e"
"go.etcd.io/etcd/tests/v3/robustness/failpoint"
"go.etcd.io/etcd/tests/v3/robustness/options"
"go.etcd.io/etcd/tests/v3/robustness/random"
"go.etcd.io/etcd/tests/v3/robustness/traffic"
)
@ -69,23 +70,19 @@ func exploratoryScenarios(_ *testing.T) []testScenario {
options.ClusterOptions{options.WithTickMs(100), options.WithElectionMs(2000)}),
}
mixedVersionOption := options.WithClusterOptionGroups(
mixedVersionOptionChoices := []random.ChoiceWeight[options.ClusterOptions]{
// 60% with all members of current version
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)},
{Choice: options.ClusterOptions{options.WithVersion(e2e.CurrentVersion)}, Weight: 60},
// 10% with 2 members of current version, 1 member last version, leader is current version
options.ClusterOptions{options.WithVersion(e2e.MinorityLastVersion), options.WithInitialLeaderIndex(0)},
{Choice: options.ClusterOptions{options.WithVersion(e2e.MinorityLastVersion), options.WithInitialLeaderIndex(0)}, Weight: 10},
// 10% with 2 members of current version, 1 member last version, leader is last version
options.ClusterOptions{options.WithVersion(e2e.MinorityLastVersion), options.WithInitialLeaderIndex(2)},
{Choice: options.ClusterOptions{options.WithVersion(e2e.MinorityLastVersion), options.WithInitialLeaderIndex(2)}, Weight: 10},
// 10% with 2 members of last version, 1 member current version, leader is last version
options.ClusterOptions{options.WithVersion(e2e.QuorumLastVersion), options.WithInitialLeaderIndex(0)},
{Choice: options.ClusterOptions{options.WithVersion(e2e.QuorumLastVersion), options.WithInitialLeaderIndex(0)}, Weight: 10},
// 10% with 2 members of last version, 1 member current version, leader is current version
options.ClusterOptions{options.WithVersion(e2e.QuorumLastVersion), options.WithInitialLeaderIndex(2)},
)
{Choice: options.ClusterOptions{options.WithVersion(e2e.QuorumLastVersion), options.WithInitialLeaderIndex(2)}, Weight: 10},
}
mixedVersionOption := options.WithClusterOptionGroups(random.PickRandom[options.ClusterOptions](mixedVersionOptionChoices))
baseOptions := []e2e.EPClusterOption{
options.WithSnapshotCount(50, 100, 1000),

View File

@ -26,6 +26,7 @@ import (
"go.etcd.io/etcd/tests/v3/robustness/client"
"go.etcd.io/etcd/tests/v3/robustness/identity"
"go.etcd.io/etcd/tests/v3/robustness/model"
"go.etcd.io/etcd/tests/v3/robustness/random"
)
var (
@ -33,41 +34,41 @@ var (
keyCount: 10,
leaseTTL: DefaultLeaseTTL,
largePutSize: 32769,
requests: []choiceWeight[etcdRequestType]{
{choice: Get, weight: 15},
{choice: List, weight: 15},
{choice: StaleGet, weight: 10},
{choice: StaleList, weight: 10},
{choice: Delete, weight: 5},
{choice: MultiOpTxn, weight: 5},
{choice: PutWithLease, weight: 5},
{choice: LeaseRevoke, weight: 5},
{choice: CompareAndSet, weight: 5},
{choice: Put, weight: 15},
{choice: LargePut, weight: 5},
{choice: Compact, weight: 5},
requests: []random.ChoiceWeight[etcdRequestType]{
{Choice: Get, Weight: 15},
{Choice: List, Weight: 15},
{Choice: StaleGet, Weight: 10},
{Choice: StaleList, Weight: 10},
{Choice: Delete, Weight: 5},
{Choice: MultiOpTxn, Weight: 5},
{Choice: PutWithLease, Weight: 5},
{Choice: LeaseRevoke, Weight: 5},
{Choice: CompareAndSet, Weight: 5},
{Choice: Put, Weight: 15},
{Choice: LargePut, Weight: 5},
{Choice: Compact, Weight: 5},
},
}
EtcdPut = etcdTraffic{
keyCount: 10,
largePutSize: 32769,
leaseTTL: DefaultLeaseTTL,
requests: []choiceWeight[etcdRequestType]{
{choice: Get, weight: 15},
{choice: List, weight: 15},
{choice: StaleGet, weight: 10},
{choice: StaleList, weight: 10},
{choice: MultiOpTxn, weight: 5},
{choice: LargePut, weight: 5},
{choice: Put, weight: 35},
{choice: Compact, weight: 5},
requests: []random.ChoiceWeight[etcdRequestType]{
{Choice: Get, Weight: 15},
{Choice: List, Weight: 15},
{Choice: StaleGet, Weight: 10},
{Choice: StaleList, Weight: 10},
{Choice: MultiOpTxn, Weight: 5},
{Choice: LargePut, Weight: 5},
{Choice: Put, Weight: 35},
{Choice: Compact, Weight: 5},
},
}
)
type etcdTraffic struct {
keyCount int
requests []choiceWeight[etcdRequestType]
requests []random.ChoiceWeight[etcdRequestType]
leaseTTL int64
largePutSize int
}
@ -126,7 +127,7 @@ func (t etcdTraffic) Run(ctx context.Context, c *client.RecordingClient, limiter
if shouldReturn = nonUniqueWriteLimiter.Take(); !shouldReturn {
choices = filterOutNonUniqueEtcdWrites(choices)
}
requestType = pickRandom(choices)
requestType = random.PickRandom(choices)
} else {
requestType = Get
}
@ -145,9 +146,9 @@ func (t etcdTraffic) Run(ctx context.Context, c *client.RecordingClient, limiter
}
}
func filterOutNonUniqueEtcdWrites(choices []choiceWeight[etcdRequestType]) (resp []choiceWeight[etcdRequestType]) {
func filterOutNonUniqueEtcdWrites(choices []random.ChoiceWeight[etcdRequestType]) (resp []random.ChoiceWeight[etcdRequestType]) {
for _, choice := range choices {
if choice.choice != Delete && choice.choice != LeaseRevoke {
if choice.Choice != Delete && choice.Choice != LeaseRevoke {
resp = append(resp, choice)
}
}
@ -193,7 +194,7 @@ func (c etcdTrafficClient) Request(ctx context.Context, request etcdRequestType,
}
case LargePut:
var resp *clientv3.PutResponse
resp, err = c.client.Put(opCtx, c.randomKey(), randString(c.largePutSize))
resp, err = c.client.Put(opCtx, c.randomKey(), random.RandString(c.largePutSize))
if resp != nil {
rev = resp.Header.Revision
}

View File

@ -29,6 +29,7 @@ import (
"go.etcd.io/etcd/pkg/v3/stringutil"
"go.etcd.io/etcd/tests/v3/robustness/client"
"go.etcd.io/etcd/tests/v3/robustness/identity"
"go.etcd.io/etcd/tests/v3/robustness/random"
)
var (
@ -36,11 +37,11 @@ var (
averageKeyCount: 10,
resource: "pods",
namespace: "default",
writeChoices: []choiceWeight[KubernetesRequestType]{
{choice: KubernetesUpdate, weight: 85},
{choice: KubernetesDelete, weight: 5},
{choice: KubernetesCreate, weight: 5},
{choice: KubernetesCompact, weight: 5},
writeChoices: []random.ChoiceWeight[KubernetesRequestType]{
{Choice: KubernetesUpdate, Weight: 85},
{Choice: KubernetesDelete, Weight: 5},
{Choice: KubernetesCreate, Weight: 5},
{Choice: KubernetesCompact, Weight: 5},
},
}
)
@ -49,7 +50,7 @@ type kubernetesTraffic struct {
averageKeyCount int
resource string
namespace string
writeChoices []choiceWeight[KubernetesRequestType]
writeChoices []random.ChoiceWeight[KubernetesRequestType]
}
func (t kubernetesTraffic) ExpectUniqueRevision() bool {
@ -161,7 +162,7 @@ func (t kubernetesTraffic) Write(ctx context.Context, kc *kubernetesClient, ids
if shouldReturn = nonUniqueWriteLimiter.Take(); !shouldReturn {
choices = filterOutNonUniqueKubernetesWrites(t.writeChoices)
}
op := pickRandom(choices)
op := random.PickRandom(choices)
switch op {
case KubernetesDelete:
_, err = kc.OptimisticDelete(writeCtx, key, rev)
@ -186,9 +187,9 @@ func (t kubernetesTraffic) Write(ctx context.Context, kc *kubernetesClient, ids
return nil
}
func filterOutNonUniqueKubernetesWrites(choices []choiceWeight[KubernetesRequestType]) (resp []choiceWeight[KubernetesRequestType]) {
func filterOutNonUniqueKubernetesWrites(choices []random.ChoiceWeight[KubernetesRequestType]) (resp []random.ChoiceWeight[KubernetesRequestType]) {
for _, choice := range choices {
if choice.choice != KubernetesDelete {
if choice.Choice != KubernetesDelete {
resp = append(resp, choice)
}
}