From 107e094f51319f99f7353f1aeae36229deda34c0 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 15 Aug 2024 18:53:33 +0000 Subject: [PATCH] internal/sync: refactor HashTrieMap tests into per-op suites This change does a minor refactor of the HashTrieMap tests to be better organized into suites for each operation. It might be worthwhile to deduplicate some code in here, but it's also helpful to see exactly what's happening when something goes wrong. Change-Id: I138515ee6de5aec5f3d38afe8a3bf3972afb2800 Reviewed-on: https://go-review.googlesource.com/c/go/+/606457 Auto-Submit: Michael Knyszek Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/internal/sync/hashtriemap_test.go | 1055 +++++++++++++------------ 1 file changed, 532 insertions(+), 523 deletions(-) diff --git a/src/internal/sync/hashtriemap_test.go b/src/internal/sync/hashtriemap_test.go index cca7512350..12e3ee6091 100644 --- a/src/internal/sync/hashtriemap_test.go +++ b/src/internal/sync/hashtriemap_test.go @@ -59,602 +59,611 @@ func testHashTrieMap(t *testing.T, newMap func() *isync.HashTrieMap[string, int] expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } }) - t.Run("CompareAndDeleteAll", func(t *testing.T) { + t.Run("All", func(t *testing.T) { m := newMap() - for range 3 { + testAll(t, m, testDataMap(testData[:]), func(_ string, _ int) bool { + return true + }) + }) + t.Run("CompareAndDelete", func(t *testing.T) { + t.Run("All", func(t *testing.T) { + m := newMap() + + for range 3 { + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) + } + for i, s := range testData { + expectPresent(t, s, i)(m.Load(s)) + expectNotDeleted(t, s, math.MaxInt)(m.CompareAndDelete(s, math.MaxInt)) + expectDeleted(t, s, i)(m.CompareAndDelete(s, i)) + expectNotDeleted(t, s, i)(m.CompareAndDelete(s, i)) + expectMissing(t, s, 0)(m.Load(s)) + } + for _, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + } + } + }) + t.Run("One", func(t *testing.T) { + m := newMap() + for i, s := range testData { expectMissing(t, s, 0)(m.Load(s)) expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } + expectNotDeleted(t, testData[15], math.MaxInt)(m.CompareAndDelete(testData[15], math.MaxInt)) + expectDeleted(t, testData[15], 15)(m.CompareAndDelete(testData[15], 15)) + expectNotDeleted(t, testData[15], 15)(m.CompareAndDelete(testData[15], 15)) for i, s := range testData { - expectPresent(t, s, i)(m.Load(s)) - expectNotDeleted(t, s, math.MaxInt)(m.CompareAndDelete(s, math.MaxInt)) - expectDeleted(t, s, i)(m.CompareAndDelete(s, i)) - expectNotDeleted(t, s, i)(m.CompareAndDelete(s, i)) - expectMissing(t, s, 0)(m.Load(s)) - } - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) + if i == 15 { + expectMissing(t, s, 0)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } } - } - }) - t.Run("CompareAndDeleteOne", func(t *testing.T) { - m := newMap() + }) + t.Run("Multiple", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - expectNotDeleted(t, testData[15], math.MaxInt)(m.CompareAndDelete(testData[15], math.MaxInt)) - expectDeleted(t, testData[15], 15)(m.CompareAndDelete(testData[15], 15)) - expectNotDeleted(t, testData[15], 15)(m.CompareAndDelete(testData[15], 15)) - for i, s := range testData { - if i == 15 { + for i, s := range testData { expectMissing(t, s, 0)(m.Load(s)) - } else { + expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } - } - }) - t.Run("CompareAndDeleteMultiple", func(t *testing.T) { - m := newMap() + for _, i := range []int{1, 105, 6, 85} { + expectNotDeleted(t, testData[i], math.MaxInt)(m.CompareAndDelete(testData[i], math.MaxInt)) + expectDeleted(t, testData[i], i)(m.CompareAndDelete(testData[i], i)) + expectNotDeleted(t, testData[i], i)(m.CompareAndDelete(testData[i], i)) + } + for i, s := range testData { + if i == 1 || i == 105 || i == 6 || i == 85 { + expectMissing(t, s, 0)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } + } + }) + t.Run("Iterate", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - for _, i := range []int{1, 105, 6, 85} { - expectNotDeleted(t, testData[i], math.MaxInt)(m.CompareAndDelete(testData[i], math.MaxInt)) - expectDeleted(t, testData[i], i)(m.CompareAndDelete(testData[i], i)) - expectNotDeleted(t, testData[i], i)(m.CompareAndDelete(testData[i], i)) - } - for i, s := range testData { - if i == 1 || i == 105 || i == 6 || i == 85 { + testAll(t, m, testDataMap(testData[:]), func(s string, i int) bool { + expectDeleted(t, s, i)(m.CompareAndDelete(s, i)) + return true + }) + for _, s := range testData { expectMissing(t, s, 0)(m.Load(s)) - } else { - expectPresent(t, s, i)(m.Load(s)) } - } - }) - t.Run("All", func(t *testing.T) { - m := newMap() - - testAll(t, m, testDataMap(testData[:]), func(_ string, _ int) bool { - return true }) - }) - t.Run("AllCompareAndDelete", func(t *testing.T) { - m := newMap() - - testAll(t, m, testDataMap(testData[:]), func(s string, i int) bool { - expectDeleted(t, s, i)(m.CompareAndDelete(s, i)) - return true + t.Run("ConcurrentUnsharedKeys", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectStored(t, key, id)(m.LoadOrStore(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectDeleted(t, key, id)(m.CompareAndDelete(key, id)) + expectMissing(t, key, 0)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + } + }(i) + } + wg.Wait() }) - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - } - }) - t.Run("ConcurrentCompareAndDeleteUnsharedKeys", func(t *testing.T) { - m := newMap() - - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("ConcurrentSharedKeys", func(t *testing.T) { + m := newMap() - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectStored(t, key, id)(m.LoadOrStore(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectDeleted(t, key, id)(m.CompareAndDelete(key, id)) - expectMissing(t, key, 0)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - } - }(i) - } - wg.Wait() + // Load up the map. + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + } + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + for i, s := range testData { + expectNotDeleted(t, s, math.MaxInt)(m.CompareAndDelete(s, math.MaxInt)) + m.CompareAndDelete(s, i) + expectMissing(t, s, 0)(m.Load(s)) + } + for _, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + } + }(i) + } + wg.Wait() + }) }) - t.Run("ConcurrentCompareAndDeleteSharedKeys", func(t *testing.T) { - m := newMap() - - // Load up the map. - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - } - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("CompareAndSwap", func(t *testing.T) { + t.Run("All", func(t *testing.T) { + m := newMap() + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) + } + for j := range 3 { for i, s := range testData { - expectNotDeleted(t, s, math.MaxInt)(m.CompareAndDelete(s, math.MaxInt)) - m.CompareAndDelete(s, i) - expectMissing(t, s, 0)(m.Load(s)) - } - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) + expectPresent(t, s, i+j)(m.Load(s)) + expectNotSwapped(t, s, math.MaxInt, i+j+1)(m.CompareAndSwap(s, math.MaxInt, i+j+1)) + expectSwapped(t, s, i, i+j+1)(m.CompareAndSwap(s, i+j, i+j+1)) + expectNotSwapped(t, s, i+j, i+j+1)(m.CompareAndSwap(s, i+j, i+j+1)) + expectPresent(t, s, i+j+1)(m.Load(s)) } - }(i) - } - wg.Wait() - }) - t.Run("CompareAndSwapAll", func(t *testing.T) { - m := newMap() - - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - for j := range 3 { + } for i, s := range testData { - expectPresent(t, s, i+j)(m.Load(s)) - expectNotSwapped(t, s, math.MaxInt, i+j+1)(m.CompareAndSwap(s, math.MaxInt, i+j+1)) - expectSwapped(t, s, i, i+j+1)(m.CompareAndSwap(s, i+j, i+j+1)) - expectNotSwapped(t, s, i+j, i+j+1)(m.CompareAndSwap(s, i+j, i+j+1)) - expectPresent(t, s, i+j+1)(m.Load(s)) + expectPresent(t, s, i+3)(m.Load(s)) } - } - for i, s := range testData { - expectPresent(t, s, i+3)(m.Load(s)) - } - }) - t.Run("CompareAndSwapOne", func(t *testing.T) { - m := newMap() + }) + t.Run("One", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - expectNotSwapped(t, testData[15], math.MaxInt, 16)(m.CompareAndSwap(testData[15], math.MaxInt, 16)) - expectSwapped(t, testData[15], 15, 16)(m.CompareAndSwap(testData[15], 15, 16)) - expectNotSwapped(t, testData[15], 15, 16)(m.CompareAndSwap(testData[15], 15, 16)) - for i, s := range testData { - if i == 15 { - expectPresent(t, s, 16)(m.Load(s)) - } else { + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } - } - }) - t.Run("CompareAndSwapMultiple", func(t *testing.T) { - m := newMap() + expectNotSwapped(t, testData[15], math.MaxInt, 16)(m.CompareAndSwap(testData[15], math.MaxInt, 16)) + expectSwapped(t, testData[15], 15, 16)(m.CompareAndSwap(testData[15], 15, 16)) + expectNotSwapped(t, testData[15], 15, 16)(m.CompareAndSwap(testData[15], 15, 16)) + for i, s := range testData { + if i == 15 { + expectPresent(t, s, 16)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } + } + }) + t.Run("Multiple", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - for _, i := range []int{1, 105, 6, 85} { - expectNotSwapped(t, testData[i], math.MaxInt, i+1)(m.CompareAndSwap(testData[i], math.MaxInt, i+1)) - expectSwapped(t, testData[i], i, i+1)(m.CompareAndSwap(testData[i], i, i+1)) - expectNotSwapped(t, testData[i], i, i+1)(m.CompareAndSwap(testData[i], i, i+1)) - } - for i, s := range testData { - if i == 1 || i == 105 || i == 6 || i == 85 { - expectPresent(t, s, i+1)(m.Load(s)) - } else { + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } - } - }) - t.Run("ConcurrentCompareAndSwapUnsharedKeys", func(t *testing.T) { - m := newMap() - - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() - - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectStored(t, key, id)(m.LoadOrStore(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectSwapped(t, key, id, id+1)(m.CompareAndSwap(key, id, id+1)) - expectPresent(t, key, id+1)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id+1)(m.Load(key)) + for _, i := range []int{1, 105, 6, 85} { + expectNotSwapped(t, testData[i], math.MaxInt, i+1)(m.CompareAndSwap(testData[i], math.MaxInt, i+1)) + expectSwapped(t, testData[i], i, i+1)(m.CompareAndSwap(testData[i], i, i+1)) + expectNotSwapped(t, testData[i], i, i+1)(m.CompareAndSwap(testData[i], i, i+1)) + } + for i, s := range testData { + if i == 1 || i == 105 || i == 6 || i == 85 { + expectPresent(t, s, i+1)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) } - }(i) - } - wg.Wait() - }) - t.Run("ConcurrentCompareAndSwapAndDeleteUnsharedKeys", func(t *testing.T) { - m := newMap() + } + }) - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("ConcurrentUnsharedKeys", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectStored(t, key, id)(m.LoadOrStore(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectSwapped(t, key, id, id+1)(m.CompareAndSwap(key, id, id+1)) + expectPresent(t, key, id+1)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id+1)(m.Load(key)) + } + }(i) + } + wg.Wait() + }) + t.Run("ConcurrentUnsharedKeysWithDelete", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectStored(t, key, id)(m.LoadOrStore(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectSwapped(t, key, id, id+1)(m.CompareAndSwap(key, id, id+1)) + expectPresent(t, key, id+1)(m.Load(key)) + expectDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) + expectNotSwapped(t, key, id+1, id+2)(m.CompareAndSwap(key, id+1, id+2)) + expectNotDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) + expectMissing(t, key, 0)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + } + }(i) + } + wg.Wait() + }) + t.Run("ConcurrentSharedKeys", func(t *testing.T) { + m := newMap() - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectStored(t, key, id)(m.LoadOrStore(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectSwapped(t, key, id, id+1)(m.CompareAndSwap(key, id, id+1)) - expectPresent(t, key, id+1)(m.Load(key)) - expectDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) - expectNotSwapped(t, key, id+1, id+2)(m.CompareAndSwap(key, id+1, id+2)) - expectNotDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) - expectMissing(t, key, 0)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - } - }(i) - } - wg.Wait() + // Load up the map. + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + } + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + for i, s := range testData { + expectNotSwapped(t, s, math.MaxInt, i+1)(m.CompareAndSwap(s, math.MaxInt, i+1)) + m.CompareAndSwap(s, i, i+1) + expectPresent(t, s, i+1)(m.Load(s)) + } + for i, s := range testData { + expectPresent(t, s, i+1)(m.Load(s)) + } + }(i) + } + wg.Wait() + }) }) - t.Run("ConcurrentCompareAndSwapSharedKeys", func(t *testing.T) { - m := newMap() - - // Load up the map. - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - } - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("Swap", func(t *testing.T) { + t.Run("All", func(t *testing.T) { + m := newMap() + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) + expectPresent(t, s, i)(m.Load(s)) + expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) + } + for j := range 3 { for i, s := range testData { - expectNotSwapped(t, s, math.MaxInt, i+1)(m.CompareAndSwap(s, math.MaxInt, i+1)) - m.CompareAndSwap(s, i, i+1) - expectPresent(t, s, i+1)(m.Load(s)) - } - for i, s := range testData { - expectPresent(t, s, i+1)(m.Load(s)) + expectPresent(t, s, i+j)(m.Load(s)) + expectLoadedFromSwap(t, s, i+j, i+j+1)(m.Swap(s, i+j+1)) + expectPresent(t, s, i+j+1)(m.Load(s)) } - }(i) - } - wg.Wait() - }) - t.Run("SwapAll", func(t *testing.T) { - m := newMap() - - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) - } - for j := range 3 { + } for i, s := range testData { - expectPresent(t, s, i+j)(m.Load(s)) - expectLoadedFromSwap(t, s, i+j, i+j+1)(m.Swap(s, i+j+1)) - expectPresent(t, s, i+j+1)(m.Load(s)) + expectLoadedFromSwap(t, s, i+3, i+3)(m.Swap(s, i+3)) } - } - for i, s := range testData { - expectLoadedFromSwap(t, s, i+3, i+3)(m.Swap(s, i+3)) - } - }) - t.Run("SwapOne", func(t *testing.T) { - m := newMap() + }) + t.Run("One", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) - } - expectLoadedFromSwap(t, testData[15], 15, 16)(m.Swap(testData[15], 16)) - for i, s := range testData { - if i == 15 { - expectPresent(t, s, 16)(m.Load(s)) - } else { + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) } - } - }) - t.Run("SwapMultiple", func(t *testing.T) { - m := newMap() + expectLoadedFromSwap(t, testData[15], 15, 16)(m.Swap(testData[15], 16)) + for i, s := range testData { + if i == 15 { + expectPresent(t, s, 16)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } + } + }) + t.Run("Multiple", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) - } - for _, i := range []int{1, 105, 6, 85} { - expectLoadedFromSwap(t, testData[i], i, i+1)(m.Swap(testData[i], i+1)) - } - for i, s := range testData { - if i == 1 || i == 105 || i == 6 || i == 85 { - expectPresent(t, s, i+1)(m.Load(s)) - } else { + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectNotLoadedFromSwap(t, s, i)(m.Swap(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoadedFromSwap(t, s, i, i)(m.Swap(s, i)) } - } - }) - t.Run("ConcurrentSwapUnsharedKeys", func(t *testing.T) { - m := newMap() - - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() - - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectNotLoadedFromSwap(t, key, id)(m.Swap(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoadedFromSwap(t, key, id, id)(m.Swap(key, id)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectLoadedFromSwap(t, key, id, id+1)(m.Swap(key, id+1)) - expectPresent(t, key, id+1)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id+1)(m.Load(key)) + for _, i := range []int{1, 105, 6, 85} { + expectLoadedFromSwap(t, testData[i], i, i+1)(m.Swap(testData[i], i+1)) + } + for i, s := range testData { + if i == 1 || i == 105 || i == 6 || i == 85 { + expectPresent(t, s, i+1)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) } - }(i) - } - wg.Wait() - }) - t.Run("ConcurrentSwapAndDeleteUnsharedKeys", func(t *testing.T) { - m := newMap() - - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + } + }) + t.Run("ConcurrentUnsharedKeys", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectNotLoadedFromSwap(t, key, id)(m.Swap(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoadedFromSwap(t, key, id, id)(m.Swap(key, id)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectLoadedFromSwap(t, key, id, id+1)(m.Swap(key, id+1)) + expectPresent(t, key, id+1)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id+1)(m.Load(key)) + } + }(i) + } + wg.Wait() + }) + t.Run("ConcurrentUnsharedKeysWithDelete", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectNotLoadedFromSwap(t, key, id)(m.Swap(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoadedFromSwap(t, key, id, id)(m.Swap(key, id)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectLoadedFromSwap(t, key, id, id+1)(m.Swap(key, id+1)) + expectPresent(t, key, id+1)(m.Load(key)) + expectDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) + expectNotLoadedFromSwap(t, key, id+2)(m.Swap(key, id+2)) + expectPresent(t, key, id+2)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id+2)(m.Load(key)) + } + }(i) + } + wg.Wait() + }) + t.Run("ConcurrentSharedKeys", func(t *testing.T) { + m := newMap() - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectNotLoadedFromSwap(t, key, id)(m.Swap(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoadedFromSwap(t, key, id, id)(m.Swap(key, id)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectLoadedFromSwap(t, key, id, id+1)(m.Swap(key, id+1)) - expectPresent(t, key, id+1)(m.Load(key)) - expectDeleted(t, key, id+1)(m.CompareAndDelete(key, id+1)) - expectNotLoadedFromSwap(t, key, id+2)(m.Swap(key, id+2)) - expectPresent(t, key, id+2)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id+2)(m.Load(key)) - } - }(i) - } - wg.Wait() + // Load up the map. + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + } + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + for i, s := range testData { + m.Swap(s, i+1) + expectPresent(t, s, i+1)(m.Load(s)) + } + for i, s := range testData { + expectPresent(t, s, i+1)(m.Load(s)) + } + }(i) + } + wg.Wait() + }) }) - t.Run("ConcurrentSwapSharedKeys", func(t *testing.T) { - m := newMap() - - // Load up the map. - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - } - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("LoadAndDelete", func(t *testing.T) { + t.Run("All", func(t *testing.T) { + m := newMap() + for range 3 { for i, s := range testData { - m.Swap(s, i+1) - expectPresent(t, s, i+1)(m.Load(s)) + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } for i, s := range testData { - expectPresent(t, s, i+1)(m.Load(s)) + expectPresent(t, s, i)(m.Load(s)) + expectLoadedFromDelete(t, s, i)(m.LoadAndDelete(s)) + expectMissing(t, s, 0)(m.Load(s)) + expectNotLoadedFromDelete(t, s, 0)(m.LoadAndDelete(s)) } - }(i) - } - wg.Wait() - }) - t.Run("LoadAndDeleteAll", func(t *testing.T) { - m := newMap() + for _, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + } + } + }) + t.Run("One", func(t *testing.T) { + m := newMap() - for range 3 { for i, s := range testData { expectMissing(t, s, 0)(m.Load(s)) expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } + expectPresent(t, testData[15], 15)(m.Load(testData[15])) + expectLoadedFromDelete(t, testData[15], 15)(m.LoadAndDelete(testData[15])) + expectMissing(t, testData[15], 0)(m.Load(testData[15])) + expectNotLoadedFromDelete(t, testData[15], 0)(m.LoadAndDelete(testData[15])) for i, s := range testData { - expectPresent(t, s, i)(m.Load(s)) - expectLoadedFromDelete(t, s, i)(m.LoadAndDelete(s)) - expectMissing(t, s, 0)(m.Load(s)) - expectNotLoadedFromDelete(t, s, 0)(m.LoadAndDelete(s)) - } - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) + if i == 15 { + expectMissing(t, s, 0)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } } - } - }) - t.Run("LoadAndDeleteOne", func(t *testing.T) { - m := newMap() + }) + t.Run("Multiple", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - expectPresent(t, testData[15], 15)(m.Load(testData[15])) - expectLoadedFromDelete(t, testData[15], 15)(m.LoadAndDelete(testData[15])) - expectMissing(t, testData[15], 0)(m.Load(testData[15])) - expectNotLoadedFromDelete(t, testData[15], 0)(m.LoadAndDelete(testData[15])) - for i, s := range testData { - if i == 15 { + for i, s := range testData { expectMissing(t, s, 0)(m.Load(s)) - } else { + expectStored(t, s, i)(m.LoadOrStore(s, i)) expectPresent(t, s, i)(m.Load(s)) + expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) } - } - }) - t.Run("LoadAndDeleteMultiple", func(t *testing.T) { - m := newMap() + for _, i := range []int{1, 105, 6, 85} { + expectPresent(t, testData[i], i)(m.Load(testData[i])) + expectLoadedFromDelete(t, testData[i], i)(m.LoadAndDelete(testData[i])) + expectMissing(t, testData[i], 0)(m.Load(testData[i])) + expectNotLoadedFromDelete(t, testData[i], 0)(m.LoadAndDelete(testData[i])) + } + for i, s := range testData { + if i == 1 || i == 105 || i == 6 || i == 85 { + expectMissing(t, s, 0)(m.Load(s)) + } else { + expectPresent(t, s, i)(m.Load(s)) + } + } + }) + t.Run("Iterate", func(t *testing.T) { + m := newMap() - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - expectPresent(t, s, i)(m.Load(s)) - expectLoaded(t, s, i)(m.LoadOrStore(s, 0)) - } - for _, i := range []int{1, 105, 6, 85} { - expectPresent(t, testData[i], i)(m.Load(testData[i])) - expectLoadedFromDelete(t, testData[i], i)(m.LoadAndDelete(testData[i])) - expectMissing(t, testData[i], 0)(m.Load(testData[i])) - expectNotLoadedFromDelete(t, testData[i], 0)(m.LoadAndDelete(testData[i])) - } - for i, s := range testData { - if i == 1 || i == 105 || i == 6 || i == 85 { + testAll(t, m, testDataMap(testData[:]), func(s string, i int) bool { + expectLoadedFromDelete(t, s, i)(m.LoadAndDelete(s)) + return true + }) + for _, s := range testData { expectMissing(t, s, 0)(m.Load(s)) - } else { - expectPresent(t, s, i)(m.Load(s)) } - } - }) - t.Run("AllLoadAndDelete", func(t *testing.T) { - m := newMap() - - testAll(t, m, testDataMap(testData[:]), func(s string, i int) bool { - expectLoadedFromDelete(t, s, i)(m.LoadAndDelete(s)) - return true }) - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - } - }) - t.Run("ConcurrentLoadAndDeleteUnsharedKeys", func(t *testing.T) { - m := newMap() - - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() - - makeKey := func(s string) string { - return s + "-" + strconv.Itoa(id) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - expectStored(t, key, id)(m.LoadOrStore(key, id)) - expectPresent(t, key, id)(m.Load(key)) - expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) - } - for _, s := range testData { - key := makeKey(s) - expectPresent(t, key, id)(m.Load(key)) - expectLoadedFromDelete(t, key, id)(m.LoadAndDelete(key)) - expectMissing(t, key, 0)(m.Load(key)) - } - for _, s := range testData { - key := makeKey(s) - expectMissing(t, key, 0)(m.Load(key)) - } - }(i) - } - wg.Wait() - }) - t.Run("ConcurrentLoadAndDeleteSharedKeys", func(t *testing.T) { - m := newMap() - - // Load up the map. - for i, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - expectStored(t, s, i)(m.LoadOrStore(s, i)) - } - gmp := runtime.GOMAXPROCS(-1) - var wg sync.WaitGroup - for i := range gmp { - wg.Add(1) - go func(id int) { - defer wg.Done() + t.Run("ConcurrentUnsharedKeys", func(t *testing.T) { + m := newMap() + + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + makeKey := func(s string) string { + return s + "-" + strconv.Itoa(id) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + expectStored(t, key, id)(m.LoadOrStore(key, id)) + expectPresent(t, key, id)(m.Load(key)) + expectLoaded(t, key, id)(m.LoadOrStore(key, 0)) + } + for _, s := range testData { + key := makeKey(s) + expectPresent(t, key, id)(m.Load(key)) + expectLoadedFromDelete(t, key, id)(m.LoadAndDelete(key)) + expectMissing(t, key, 0)(m.Load(key)) + } + for _, s := range testData { + key := makeKey(s) + expectMissing(t, key, 0)(m.Load(key)) + } + }(i) + } + wg.Wait() + }) + t.Run("ConcurrentSharedKeys", func(t *testing.T) { + m := newMap() - for _, s := range testData { - m.LoadAndDelete(s) - expectMissing(t, s, 0)(m.Load(s)) - } - for _, s := range testData { - expectMissing(t, s, 0)(m.Load(s)) - } - }(i) - } - wg.Wait() + // Load up the map. + for i, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + expectStored(t, s, i)(m.LoadOrStore(s, i)) + } + gmp := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + for i := range gmp { + wg.Add(1) + go func(id int) { + defer wg.Done() + + for _, s := range testData { + m.LoadAndDelete(s) + expectMissing(t, s, 0)(m.Load(s)) + } + for _, s := range testData { + expectMissing(t, s, 0)(m.Load(s)) + } + }(i) + } + wg.Wait() + }) }) } -- 2.48.1