github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/complete/wal/wal_test.go (about) 1 package wal 2 3 import ( 4 "testing" 5 6 "github.com/rs/zerolog" 7 "github.com/stretchr/testify/require" 8 9 "github.com/onflow/flow-go/module/metrics" 10 "github.com/onflow/flow-go/storage/util" 11 "github.com/onflow/flow-go/utils/unittest" 12 ) 13 14 var ( 15 pathByteSize = 32 16 segmentSize = 32 * 1024 17 ) 18 19 func RunWithWALCheckpointerWithFiles(t *testing.T, names ...interface{}) { 20 f := names[len(names)-1].(func(*testing.T, *DiskWAL, *Checkpointer)) 21 22 fileNames := make([]string, len(names)-1) 23 24 for i := 0; i <= len(names)-2; i++ { 25 fileNames[i] = names[i].(string) 26 } 27 28 unittest.RunWithTempDir(t, func(dir string) { 29 util.CreateFiles(t, dir, fileNames...) 30 31 wal, err := NewDiskWAL(zerolog.Nop(), nil, metrics.NewNoopCollector(), dir, 10, pathByteSize, segmentSize) 32 require.NoError(t, err) 33 34 checkpointer, err := wal.NewCheckpointer() 35 require.NoError(t, err) 36 37 f(t, wal, checkpointer) 38 39 <-wal.Done() 40 }) 41 } 42 43 func Test_emptyDir(t *testing.T) { 44 RunWithWALCheckpointerWithFiles(t, func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 45 latestCheckpoint, err := checkpointer.LatestCheckpoint() 46 require.NoError(t, err) 47 require.Equal(t, -1, latestCheckpoint) 48 49 // here when starting LedgerWAL, it creates empty file for writing, hence directory isn't really empty 50 from, to, err := checkpointer.NotCheckpointedSegments() 51 require.NoError(t, err) 52 require.Equal(t, 0, from) 53 require.Equal(t, 0, to) 54 }) 55 } 56 57 // Prometheus WAL require files to be 8 characters, otherwise it gets confused 58 func Test_noCheckpoints(t *testing.T) { 59 RunWithWALCheckpointerWithFiles(t, "00000000", "00000001", "00000002", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 60 latestCheckpoint, err := checkpointer.LatestCheckpoint() 61 require.NoError(t, err) 62 require.Equal(t, -1, latestCheckpoint) 63 64 from, to, err := checkpointer.NotCheckpointedSegments() 65 require.NoError(t, err) 66 require.Equal(t, 0, from) 67 require.Equal(t, 3, to) //extra one because WAL now creates empty file on start 68 }) 69 } 70 71 func Test_someCheckpoints(t *testing.T) { 72 RunWithWALCheckpointerWithFiles(t, "00000000", "00000001", "00000002", "00000003", "00000004", "00000005", "checkpoint.00000002", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 73 latestCheckpoint, err := checkpointer.LatestCheckpoint() 74 require.NoError(t, err) 75 require.Equal(t, 2, latestCheckpoint) 76 77 from, to, err := checkpointer.NotCheckpointedSegments() 78 require.NoError(t, err) 79 require.Equal(t, 3, from) 80 require.Equal(t, 6, to) //extra one because WAL now creates empty file on start 81 }) 82 } 83 84 func Test_loneCheckpoint(t *testing.T) { 85 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000005", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 86 latestCheckpoint, err := checkpointer.LatestCheckpoint() 87 require.NoError(t, err) 88 require.Equal(t, 5, latestCheckpoint) 89 90 from, to, err := checkpointer.NotCheckpointedSegments() 91 require.NoError(t, err) 92 require.Equal(t, -1, from) 93 require.Equal(t, -1, to) 94 }) 95 } 96 97 func Test_lastCheckpointIsFoundByNumericValue(t *testing.T) { 98 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000005", "checkpoint.00000004", "checkpoint.00000006", "checkpoint.00000002", "checkpoint.00000001", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 99 latestCheckpoint, err := checkpointer.LatestCheckpoint() 100 require.NoError(t, err) 101 require.Equal(t, 6, latestCheckpoint) 102 }) 103 } 104 105 func Test_checkpointWithoutPrecedingSegments(t *testing.T) { 106 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000005", "00000006", "00000007", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 107 latestCheckpoint, err := checkpointer.LatestCheckpoint() 108 require.NoError(t, err) 109 require.Equal(t, 5, latestCheckpoint) 110 111 from, to, err := checkpointer.NotCheckpointedSegments() 112 require.NoError(t, err) 113 require.Equal(t, 6, from) 114 require.Equal(t, 8, to) //extra one because WAL now creates empty file on start 115 }) 116 } 117 118 func Test_checkpointWithSameSegment(t *testing.T) { 119 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000005", "00000005", "00000006", "00000007", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 120 latestCheckpoint, err := checkpointer.LatestCheckpoint() 121 require.NoError(t, err) 122 require.Equal(t, 5, latestCheckpoint) 123 124 from, to, err := checkpointer.NotCheckpointedSegments() 125 require.NoError(t, err) 126 require.Equal(t, 6, from) 127 require.Equal(t, 8, to) //extra one because WAL now creates empty file on start 128 }) 129 } 130 131 func Test_listingCheckpoints(t *testing.T) { 132 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000005", "checkpoint.00000002", "00000003", "checkpoint.00000000", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 133 listCheckpoints, err := checkpointer.Checkpoints() 134 require.NoError(t, err) 135 require.Len(t, listCheckpoints, 3) 136 require.Equal(t, []int{0, 2, 5}, listCheckpoints) 137 }) 138 } 139 140 func Test_NoGapBetweenSegmentsAndLastCheckpoint(t *testing.T) { 141 RunWithWALCheckpointerWithFiles(t, "checkpoint.00000004", "00000006", "00000007", func(t *testing.T, wal *DiskWAL, checkpointer *Checkpointer) { 142 latestCheckpoint, err := checkpointer.LatestCheckpoint() 143 require.NoError(t, err) 144 require.Equal(t, 4, latestCheckpoint) 145 146 _, _, err = checkpointer.NotCheckpointedSegments() 147 require.Error(t, err) 148 }) 149 } 150 151 func Test_LatestPossibleCheckpoints(t *testing.T) { 152 153 require.Equal(t, []int(nil), getPossibleCheckpoints([]int{1, 2, 5}, 0, 0)) 154 155 require.Equal(t, []int{1}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 1)) 156 require.Equal(t, []int{1, 2}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 2)) 157 require.Equal(t, []int{1, 2}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 3)) 158 require.Equal(t, []int{1, 2}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 4)) 159 160 require.Equal(t, []int{1, 2, 5}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 5)) 161 require.Equal(t, []int{1, 2, 5}, getPossibleCheckpoints([]int{1, 2, 5}, 0, 6)) 162 require.Equal(t, []int{1, 2, 5}, getPossibleCheckpoints([]int{1, 2, 5}, 1, 6)) 163 164 require.Equal(t, []int{2, 5}, getPossibleCheckpoints([]int{1, 2, 5}, 2, 6)) 165 require.Equal(t, []int{2}, getPossibleCheckpoints([]int{1, 2, 5}, 2, 3)) 166 require.Equal(t, []int{2}, getPossibleCheckpoints([]int{1, 2, 5}, 2, 4)) 167 require.Equal(t, []int{2, 5}, getPossibleCheckpoints([]int{1, 2, 5}, 2, 5)) 168 169 require.Equal(t, []int{5}, getPossibleCheckpoints([]int{1, 2, 5}, 3, 5)) 170 require.Equal(t, []int{5}, getPossibleCheckpoints([]int{1, 2, 5}, 3, 6)) 171 172 require.Equal(t, []int{5}, getPossibleCheckpoints([]int{1, 2, 5}, 5, 5)) 173 require.Equal(t, []int{}, getPossibleCheckpoints([]int{1, 2, 5}, 6, 6)) 174 175 }