diff --git a/internal/skiplist/skiplist_chaos_test.go b/internal/skiplist/skiplist_chaos_test.go index bba8d82ce4..3f6ee064e3 100644 --- a/internal/skiplist/skiplist_chaos_test.go +++ b/internal/skiplist/skiplist_chaos_test.go @@ -5,6 +5,7 @@ import ( "math/rand" "sort" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -37,73 +38,83 @@ func (ti testInterface) Less(other interface{}) bool { } func TestSkiplistChaos(t *testing.T) { - rnd := rand.New(rand.NewSource(0)) + t.Parallel() iterations := 20 + seed := time.Now().UnixNano() + + rndMain := rand.New(rand.NewSource(seed)) + for i := 0; i < iterations; i++ { - numUsers := rnd.Intn(2000) + 100 - users := make([]string, numUsers) + i := i + numUsers := rndMain.Intn(2000) + 100 + numOps := rndMain.Intn(100_000) + 100 + numLists := rndMain.Intn(47) + 3 + name := fmt.Sprintf("iteration=%d,users=%d,ops=%d,lists=%d", i, numUsers, numOps, numLists) - for j := 0; j < numUsers; j++ { - users[j] = randString(t, rnd) - } + t.Run(name, func(t *testing.T) { + t.Parallel() - numOps := rnd.Intn(100_000) + 100 - ops := make([]testInterface, numOps) + // Setup a new PRNG for this subtest + rnd := rand.New(rand.NewSource(seed + int64(i))) - for j := 0; j < numOps; j++ { - id := users[rnd.Intn(numUsers)] - ops[j] = testInterface{ - id: id, - val: rnd.Intn(999) + 1, + users := make([]string, numUsers) + for j := 0; j < numUsers; j++ { + users[j] = randString(t, rnd) } - } - numLists := rnd.Intn(47) + 3 - lists := make([]*SkipList, numLists) - userOps := make([]map[string]testInterface, numLists) + ops := make([]testInterface, numOps) + for j := 0; j < numOps; j++ { + id := users[rnd.Intn(numUsers)] + ops[j] = testInterface{ + id: id, + val: rnd.Intn(999) + 1, + } + } - fmt.Printf("** iteration=%v, users=%v, ops=%v, lists=%v\n", i, numUsers, numOps, numLists) + lists := make([]*SkipList, numLists) + userOps := make([]map[string]testInterface, numLists) - // Populate lists - for j := 0; j < numLists; j++ { - rnd.Shuffle(len(ops), func(i, j int) { - ops[i], ops[j] = ops[j], ops[i] - }) + // Populate lists + for j := 0; j < numLists; j++ { + rnd.Shuffle(len(ops), func(i, j int) { + ops[i], ops[j] = ops[j], ops[i] + }) - userOps[j] = make(map[string]testInterface, numUsers) + userOps[j] = make(map[string]testInterface, numUsers) - lists[j] = New() - for _, op := range ops { - oldOp, ok := userOps[j][op.id] - if ok { - lists[j].Delete(oldOp) - op.val += oldOp.val - } + lists[j] = New() + for _, op := range ops { + oldOp, ok := userOps[j][op.id] + if ok { + lists[j].Delete(oldOp) + op.val += oldOp.val + } - lists[j].Insert(op) - userOps[j][op.id] = op + lists[j].Insert(op) + userOps[j][op.id] = op + } } - } - // Now verify - for j, sl := range lists { - listOps := make([]testInterface, 0, len(ops)) + // Now verify + for j, sl := range lists { + listOps := make([]testInterface, 0, len(ops)) - for _, op := range userOps[j] { - listOps = append(listOps, op) - } + for _, op := range userOps[j] { + listOps = append(listOps, op) + } - sort.Slice(listOps, func(i, j int) bool { - return listOps[i].Less(listOps[j]) - }) + sort.Slice(listOps, func(i, j int) bool { + return listOps[i].Less(listOps[j]) + }) - for idx, op := range listOps { - rank := idx + 1 + for idx, op := range listOps { + rank := idx + 1 - listRank := sl.GetRank(op) - require.Equal(t, rank, listRank, "list %d, unexpected rank for op %+v", j, op) + listRank := sl.GetRank(op) + require.Equal(t, rank, listRank, "list %d, unexpected rank for op %+v", j, op) + } } - } + }) } }