github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/mempool/herocache/execution_data_test.go (about) 1 package herocache_test 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/onflow/flow-go/module/executiondatasync/execution_data" 12 "github.com/onflow/flow-go/module/mempool/herocache" 13 "github.com/onflow/flow-go/module/metrics" 14 "github.com/onflow/flow-go/utils/unittest" 15 ) 16 17 func TestBlockExecutionDataPool(t *testing.T) { 18 ed1 := unittest.BlockExecutionDatEntityFixture() 19 ed2 := unittest.BlockExecutionDatEntityFixture() 20 21 cache := herocache.NewBlockExecutionData(1000, unittest.Logger(), metrics.NewNoopCollector()) 22 23 t.Run("should be able to add first", func(t *testing.T) { 24 added := cache.Add(ed1) 25 assert.True(t, added) 26 }) 27 28 t.Run("should be able to add second", func(t *testing.T) { 29 added := cache.Add(ed2) 30 assert.True(t, added) 31 }) 32 33 t.Run("should be able to get size", func(t *testing.T) { 34 size := cache.Size() 35 assert.EqualValues(t, 2, size) 36 }) 37 38 t.Run("should be able to get first by blockID", func(t *testing.T) { 39 actual, exists := cache.ByID(ed1.BlockID) 40 assert.True(t, exists) 41 assert.Equal(t, ed1, actual) 42 }) 43 44 t.Run("should be able to remove second by blockID", func(t *testing.T) { 45 ok := cache.Remove(ed2.BlockID) 46 assert.True(t, ok) 47 }) 48 49 t.Run("should be able to retrieve all", func(t *testing.T) { 50 items := cache.All() 51 assert.Len(t, items, 1) 52 assert.Equal(t, ed1, items[0]) 53 }) 54 55 t.Run("should be able to clear", func(t *testing.T) { 56 assert.True(t, cache.Size() > 0) 57 cache.Clear() 58 assert.Equal(t, uint(0), cache.Size()) 59 }) 60 } 61 62 // TestConcurrentWriteAndRead checks correctness of cache mempool under concurrent read and write. 63 func TestBlockExecutionDataConcurrentWriteAndRead(t *testing.T) { 64 total := 100 65 execDatas := unittest.BlockExecutionDatEntityListFixture(total) 66 cache := herocache.NewBlockExecutionData(uint32(total), unittest.Logger(), metrics.NewNoopCollector()) 67 68 wg := sync.WaitGroup{} 69 wg.Add(total) 70 71 // storing all cache 72 for i := 0; i < total; i++ { 73 go func(ed *execution_data.BlockExecutionDataEntity) { 74 require.True(t, cache.Add(ed)) 75 76 wg.Done() 77 }(execDatas[i]) 78 } 79 80 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "could not write all cache on time") 81 require.Equal(t, cache.Size(), uint(total)) 82 83 wg.Add(total) 84 // reading all cache 85 for i := 0; i < total; i++ { 86 go func(ed *execution_data.BlockExecutionDataEntity) { 87 actual, ok := cache.ByID(ed.BlockID) 88 require.True(t, ok) 89 require.Equal(t, ed, actual) 90 91 wg.Done() 92 }(execDatas[i]) 93 } 94 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "could not read all cache on time") 95 } 96 97 // TestAllReturnsInOrder checks All method of the HeroCache-based cache mempool returns all 98 // cache in the same order as they are returned. 99 func TestBlockExecutionDataAllReturnsInOrder(t *testing.T) { 100 total := 100 101 execDatas := unittest.BlockExecutionDatEntityListFixture(total) 102 cache := herocache.NewBlockExecutionData(uint32(total), unittest.Logger(), metrics.NewNoopCollector()) 103 104 // storing all cache 105 for i := 0; i < total; i++ { 106 require.True(t, cache.Add(execDatas[i])) 107 ed, ok := cache.ByID(execDatas[i].BlockID) 108 require.True(t, ok) 109 require.Equal(t, execDatas[i], ed) 110 } 111 112 // all cache must be retrieved in the same order as they are added 113 all := cache.All() 114 for i := 0; i < total; i++ { 115 require.Equal(t, execDatas[i], all[i]) 116 } 117 }