13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
16 cmn "github.com/tendermint/tmlibs/common"
19 // NOTE: Returned group has ticker stopped
20 func createTestGroup(t *testing.T, headSizeLimit int64) *Group {
21 testID := cmn.RandStr(12)
22 testDir := "_test_" + testID
23 err := cmn.EnsureDir(testDir, 0700)
24 require.NoError(t, err, "Error creating dir")
25 headPath := testDir + "/myfile"
26 g, err := OpenGroup(headPath)
27 require.NoError(t, err, "Error opening Group")
28 g.SetHeadSizeLimit(headSizeLimit)
30 require.NotEqual(t, nil, g, "Failed to create Group")
34 func destroyTestGroup(t *testing.T, g *Group) {
35 err := os.RemoveAll(g.Dir)
36 require.NoError(t, err, "Error removing test Group directory")
39 func assertGroupInfo(t *testing.T, gInfo GroupInfo, minIndex, maxIndex int, totalSize, headSize int64) {
40 assert.Equal(t, minIndex, gInfo.MinIndex)
41 assert.Equal(t, maxIndex, gInfo.MaxIndex)
42 assert.Equal(t, totalSize, gInfo.TotalSize)
43 assert.Equal(t, headSize, gInfo.HeadSize)
46 func TestCheckHeadSizeLimit(t *testing.T) {
47 g := createTestGroup(t, 1000*1000)
49 // At first, there are no files.
50 assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 0, 0)
52 // Write 1000 bytes 999 times.
53 for i := 0; i < 999; i++ {
54 err := g.WriteLine(cmn.RandStr(999))
55 require.NoError(t, err, "Error appending to head")
58 assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
60 // Even calling checkHeadSizeLimit manually won't rotate it.
61 g.checkHeadSizeLimit()
62 assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
64 // Write 1000 more bytes.
65 err := g.WriteLine(cmn.RandStr(999))
66 require.NoError(t, err, "Error appending to head")
69 // Calling checkHeadSizeLimit this time rolls it.
70 g.checkHeadSizeLimit()
71 assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1000000, 0)
73 // Write 1000 more bytes.
74 err = g.WriteLine(cmn.RandStr(999))
75 require.NoError(t, err, "Error appending to head")
78 // Calling checkHeadSizeLimit does nothing.
79 g.checkHeadSizeLimit()
80 assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1001000, 1000)
82 // Write 1000 bytes 999 times.
83 for i := 0; i < 999; i++ {
84 err = g.WriteLine(cmn.RandStr(999))
85 require.NoError(t, err, "Error appending to head")
88 assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 2000000, 1000000)
90 // Calling checkHeadSizeLimit rolls it again.
91 g.checkHeadSizeLimit()
92 assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2000000, 0)
94 // Write 1000 more bytes.
95 _, err = g.Head.Write([]byte(cmn.RandStr(999) + "\n"))
96 require.NoError(t, err, "Error appending to head")
98 assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
100 // Calling checkHeadSizeLimit does nothing.
101 g.checkHeadSizeLimit()
102 assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
105 destroyTestGroup(t, g)
108 func TestSearch(t *testing.T) {
109 g := createTestGroup(t, 10*1000)
111 // Create some files in the group that have several INFO lines in them.
112 // Try to put the INFO lines in various spots.
113 for i := 0; i < 100; i++ {
114 // The random junk at the end ensures that this INFO linen
115 // is equally likely to show up at the end.
116 _, err := g.Head.Write([]byte(fmt.Sprintf("INFO %v %v\n", i, cmn.RandStr(123))))
117 require.NoError(t, err, "Failed to write to head")
118 g.checkHeadSizeLimit()
119 for j := 0; j < 10; j++ {
120 _, err1 := g.Head.Write([]byte(cmn.RandStr(123) + "\n"))
121 require.NoError(t, err1, "Failed to write to head")
122 g.checkHeadSizeLimit()
126 // Create a search func that searches for line
127 makeSearchFunc := func(target int) SearchFunc {
128 return func(line string) (int, error) {
129 parts := strings.Split(line, " ")
131 return -1, errors.New("Line did not have 3 parts")
133 i, err := strconv.Atoi(parts[1])
135 return -1, errors.New("Failed to parse INFO: " + err.Error())
139 } else if target == i {
147 // Now search for each number
148 for i := 0; i < 100; i++ {
149 t.Log("Testing for i", i)
150 gr, match, err := g.Search("INFO", makeSearchFunc(i))
151 require.NoError(t, err, "Failed to search for line")
152 assert.True(t, match, "Expected Search to return exact match")
153 line, err := gr.ReadLine()
154 require.NoError(t, err, "Failed to read line after search")
155 if !strings.HasPrefix(line, fmt.Sprintf("INFO %v ", i)) {
156 t.Fatal("Failed to get correct line")
158 // Make sure we can continue to read from there.
161 line, err := gr.ReadLine()
167 t.Fatal("Got EOF after the wrong INFO #")
169 } else if err != nil {
170 t.Fatal("Error reading line", err)
172 if !strings.HasPrefix(line, "INFO ") {
175 if !strings.HasPrefix(line, fmt.Sprintf("INFO %v ", cur)) {
176 t.Fatalf("Unexpected INFO #. Expected %v got:\n%v", cur, line)
183 // Now search for something that is too small.
184 // We should get the first available line.
186 gr, match, err := g.Search("INFO", makeSearchFunc(-999))
187 require.NoError(t, err, "Failed to search for line")
188 assert.False(t, match, "Expected Search to not return exact match")
189 line, err := gr.ReadLine()
190 require.NoError(t, err, "Failed to read line after search")
191 if !strings.HasPrefix(line, "INFO 0 ") {
192 t.Error("Failed to fetch correct line, which is the earliest INFO")
195 require.NoError(t, err, "Failed to close GroupReader")
198 // Now search for something that is too large.
199 // We should get an EOF error.
201 gr, _, err := g.Search("INFO", makeSearchFunc(999))
202 assert.Equal(t, io.EOF, err)
207 destroyTestGroup(t, g)
210 func TestRotateFile(t *testing.T) {
211 g := createTestGroup(t, 0)
212 g.WriteLine("Line 1")
213 g.WriteLine("Line 2")
214 g.WriteLine("Line 3")
217 g.WriteLine("Line 4")
218 g.WriteLine("Line 5")
219 g.WriteLine("Line 6")
222 // Read g.Head.Path+"000"
223 body1, err := ioutil.ReadFile(g.Head.Path + ".000")
224 assert.NoError(t, err, "Failed to read first rolled file")
225 if string(body1) != "Line 1\nLine 2\nLine 3\n" {
226 t.Errorf("Got unexpected contents: [%v]", string(body1))
230 body2, err := ioutil.ReadFile(g.Head.Path)
231 assert.NoError(t, err, "Failed to read first rolled file")
232 if string(body2) != "Line 4\nLine 5\nLine 6\n" {
233 t.Errorf("Got unexpected contents: [%v]", string(body2))
237 destroyTestGroup(t, g)
240 func TestFindLast1(t *testing.T) {
241 g := createTestGroup(t, 0)
243 g.WriteLine("Line 1")
244 g.WriteLine("Line 2")
246 g.WriteLine("Line 3")
249 g.WriteLine("Line 4")
250 g.WriteLine("Line 5")
251 g.WriteLine("Line 6")
255 match, found, err := g.FindLast("#")
256 assert.NoError(t, err)
257 assert.True(t, found)
258 assert.Equal(t, "# b", match)
261 destroyTestGroup(t, g)
264 func TestFindLast2(t *testing.T) {
265 g := createTestGroup(t, 0)
267 g.WriteLine("Line 1")
268 g.WriteLine("Line 2")
269 g.WriteLine("Line 3")
273 g.WriteLine("Line 4")
274 g.WriteLine("Line 5")
276 g.WriteLine("Line 6")
279 match, found, err := g.FindLast("#")
280 assert.NoError(t, err)
281 assert.True(t, found)
282 assert.Equal(t, "# b", match)
285 destroyTestGroup(t, g)
288 func TestFindLast3(t *testing.T) {
289 g := createTestGroup(t, 0)
291 g.WriteLine("Line 1")
293 g.WriteLine("Line 2")
295 g.WriteLine("Line 3")
298 g.WriteLine("Line 4")
299 g.WriteLine("Line 5")
300 g.WriteLine("Line 6")
303 match, found, err := g.FindLast("#")
304 assert.NoError(t, err)
305 assert.True(t, found)
306 assert.Equal(t, "# b", match)
309 destroyTestGroup(t, g)
312 func TestFindLast4(t *testing.T) {
313 g := createTestGroup(t, 0)
315 g.WriteLine("Line 1")
316 g.WriteLine("Line 2")
317 g.WriteLine("Line 3")
320 g.WriteLine("Line 4")
321 g.WriteLine("Line 5")
322 g.WriteLine("Line 6")
325 match, found, err := g.FindLast("#")
326 assert.NoError(t, err)
327 assert.False(t, found)
328 assert.Empty(t, match)
331 destroyTestGroup(t, g)
334 func TestWrite(t *testing.T) {
335 g := createTestGroup(t, 0)
337 written := []byte("Medusa")
341 read := make([]byte, len(written))
342 gr, err := g.NewReader(0)
343 require.NoError(t, err, "failed to create reader")
345 _, err = gr.Read(read)
346 assert.NoError(t, err, "failed to read data")
347 assert.Equal(t, written, read)
350 destroyTestGroup(t, g)
353 // test that Read reads the required amount of bytes from all the files in the
354 // group and returns no error if n == size of the given slice.
355 func TestGroupReaderRead(t *testing.T) {
356 g := createTestGroup(t, 0)
358 professor := []byte("Professor Monster")
362 frankenstein := []byte("Frankenstein's Monster")
363 g.Write(frankenstein)
366 totalWrittenLength := len(professor) + len(frankenstein)
367 read := make([]byte, totalWrittenLength)
368 gr, err := g.NewReader(0)
369 require.NoError(t, err, "failed to create reader")
371 n, err := gr.Read(read)
372 assert.NoError(t, err, "failed to read data")
373 assert.Equal(t, totalWrittenLength, n, "not enough bytes read")
374 professorPlusFrankenstein := professor
375 professorPlusFrankenstein = append(professorPlusFrankenstein, frankenstein...)
376 assert.Equal(t, professorPlusFrankenstein, read)
379 destroyTestGroup(t, g)
382 // test that Read returns an error if number of bytes read < size of
383 // the given slice. Subsequent call should return 0, io.EOF.
384 func TestGroupReaderRead2(t *testing.T) {
385 g := createTestGroup(t, 0)
387 professor := []byte("Professor Monster")
391 frankenstein := []byte("Frankenstein's Monster")
392 frankensteinPart := []byte("Frankenstein")
393 g.Write(frankensteinPart) // note writing only a part
396 totalLength := len(professor) + len(frankenstein)
397 read := make([]byte, totalLength)
398 gr, err := g.NewReader(0)
399 require.NoError(t, err, "failed to create reader")
401 // 1) n < (size of the given slice), io.EOF
402 n, err := gr.Read(read)
403 assert.Equal(t, io.EOF, err)
404 assert.Equal(t, len(professor)+len(frankensteinPart), n, "Read more/less bytes than it is in the group")
407 n, err = gr.Read([]byte("0"))
408 assert.Equal(t, io.EOF, err)
409 assert.Equal(t, 0, n)
412 destroyTestGroup(t, g)
415 func TestMinIndex(t *testing.T) {
416 g := createTestGroup(t, 0)
418 assert.Zero(t, g.MinIndex(), "MinIndex should be zero at the beginning")
421 destroyTestGroup(t, g)
424 func TestMaxIndex(t *testing.T) {
425 g := createTestGroup(t, 0)
427 assert.Zero(t, g.MaxIndex(), "MaxIndex should be zero at the beginning")
429 g.WriteLine("Line 1")
433 assert.Equal(t, 1, g.MaxIndex(), "MaxIndex should point to the last file")
436 destroyTestGroup(t, g)