You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
7.1 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package autofile
  2. import (
  3. "io"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. tmos "github.com/tendermint/tendermint/libs/os"
  11. tmrand "github.com/tendermint/tendermint/libs/rand"
  12. )
  13. func createTestGroupWithHeadSizeLimit(t *testing.T, headSizeLimit int64) *Group {
  14. testID := tmrand.Str(12)
  15. testDir := "_test_" + testID
  16. err := tmos.EnsureDir(testDir, 0700)
  17. require.NoError(t, err, "Error creating dir")
  18. headPath := testDir + "/myfile"
  19. g, err := OpenGroup(headPath, GroupHeadSizeLimit(headSizeLimit))
  20. require.NoError(t, err, "Error opening Group")
  21. require.NotEqual(t, nil, g, "Failed to create Group")
  22. return g
  23. }
  24. func destroyTestGroup(t *testing.T, g *Group) {
  25. g.Close()
  26. err := os.RemoveAll(g.Dir)
  27. require.NoError(t, err, "Error removing test Group directory")
  28. }
  29. func assertGroupInfo(t *testing.T, gInfo GroupInfo, minIndex, maxIndex int, totalSize, headSize int64) {
  30. assert.Equal(t, minIndex, gInfo.MinIndex)
  31. assert.Equal(t, maxIndex, gInfo.MaxIndex)
  32. assert.Equal(t, totalSize, gInfo.TotalSize)
  33. assert.Equal(t, headSize, gInfo.HeadSize)
  34. }
  35. func TestCheckHeadSizeLimit(t *testing.T) {
  36. g := createTestGroupWithHeadSizeLimit(t, 1000*1000)
  37. // At first, there are no files.
  38. assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 0, 0)
  39. // Write 1000 bytes 999 times.
  40. for i := 0; i < 999; i++ {
  41. err := g.WriteLine(tmrand.Str(999))
  42. require.NoError(t, err, "Error appending to head")
  43. }
  44. g.FlushAndSync()
  45. assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
  46. // Even calling checkHeadSizeLimit manually won't rotate it.
  47. g.checkHeadSizeLimit()
  48. assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
  49. // Write 1000 more bytes.
  50. err := g.WriteLine(tmrand.Str(999))
  51. require.NoError(t, err, "Error appending to head")
  52. g.FlushAndSync()
  53. // Calling checkHeadSizeLimit this time rolls it.
  54. g.checkHeadSizeLimit()
  55. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1000000, 0)
  56. // Write 1000 more bytes.
  57. err = g.WriteLine(tmrand.Str(999))
  58. require.NoError(t, err, "Error appending to head")
  59. g.FlushAndSync()
  60. // Calling checkHeadSizeLimit does nothing.
  61. g.checkHeadSizeLimit()
  62. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1001000, 1000)
  63. // Write 1000 bytes 999 times.
  64. for i := 0; i < 999; i++ {
  65. err = g.WriteLine(tmrand.Str(999))
  66. require.NoError(t, err, "Error appending to head")
  67. }
  68. g.FlushAndSync()
  69. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 2000000, 1000000)
  70. // Calling checkHeadSizeLimit rolls it again.
  71. g.checkHeadSizeLimit()
  72. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2000000, 0)
  73. // Write 1000 more bytes.
  74. _, err = g.Head.Write([]byte(tmrand.Str(999) + "\n"))
  75. require.NoError(t, err, "Error appending to head")
  76. g.FlushAndSync()
  77. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
  78. // Calling checkHeadSizeLimit does nothing.
  79. g.checkHeadSizeLimit()
  80. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
  81. // Cleanup
  82. destroyTestGroup(t, g)
  83. }
  84. func TestRotateFile(t *testing.T) {
  85. g := createTestGroupWithHeadSizeLimit(t, 0)
  86. // Create a different temporary directory and move into it, to make sure
  87. // relative paths are resolved at Group creation
  88. origDir, err := os.Getwd()
  89. require.NoError(t, err)
  90. defer os.Chdir(origDir)
  91. dir, err := ioutil.TempDir("", "rotate_test")
  92. require.NoError(t, err)
  93. defer os.RemoveAll(dir)
  94. err = os.Chdir(dir)
  95. require.NoError(t, err)
  96. require.True(t, filepath.IsAbs(g.Head.Path))
  97. require.True(t, filepath.IsAbs(g.Dir))
  98. // Create and rotate files
  99. g.WriteLine("Line 1")
  100. g.WriteLine("Line 2")
  101. g.WriteLine("Line 3")
  102. g.FlushAndSync()
  103. g.RotateFile()
  104. g.WriteLine("Line 4")
  105. g.WriteLine("Line 5")
  106. g.WriteLine("Line 6")
  107. g.FlushAndSync()
  108. // Read g.Head.Path+"000"
  109. body1, err := ioutil.ReadFile(g.Head.Path + ".000")
  110. assert.NoError(t, err, "Failed to read first rolled file")
  111. if string(body1) != "Line 1\nLine 2\nLine 3\n" {
  112. t.Errorf("got unexpected contents: [%v]", string(body1))
  113. }
  114. // Read g.Head.Path
  115. body2, err := ioutil.ReadFile(g.Head.Path)
  116. assert.NoError(t, err, "Failed to read first rolled file")
  117. if string(body2) != "Line 4\nLine 5\nLine 6\n" {
  118. t.Errorf("got unexpected contents: [%v]", string(body2))
  119. }
  120. // Make sure there are no files in the current, temporary directory
  121. files, err := ioutil.ReadDir(".")
  122. require.NoError(t, err)
  123. assert.Empty(t, files)
  124. // Cleanup
  125. destroyTestGroup(t, g)
  126. }
  127. func TestWrite(t *testing.T) {
  128. g := createTestGroupWithHeadSizeLimit(t, 0)
  129. written := []byte("Medusa")
  130. g.Write(written)
  131. g.FlushAndSync()
  132. read := make([]byte, len(written))
  133. gr, err := g.NewReader(0)
  134. require.NoError(t, err, "failed to create reader")
  135. _, err = gr.Read(read)
  136. assert.NoError(t, err, "failed to read data")
  137. assert.Equal(t, written, read)
  138. // Cleanup
  139. destroyTestGroup(t, g)
  140. }
  141. // test that Read reads the required amount of bytes from all the files in the
  142. // group and returns no error if n == size of the given slice.
  143. func TestGroupReaderRead(t *testing.T) {
  144. g := createTestGroupWithHeadSizeLimit(t, 0)
  145. professor := []byte("Professor Monster")
  146. g.Write(professor)
  147. g.FlushAndSync()
  148. g.RotateFile()
  149. frankenstein := []byte("Frankenstein's Monster")
  150. g.Write(frankenstein)
  151. g.FlushAndSync()
  152. totalWrittenLength := len(professor) + len(frankenstein)
  153. read := make([]byte, totalWrittenLength)
  154. gr, err := g.NewReader(0)
  155. require.NoError(t, err, "failed to create reader")
  156. n, err := gr.Read(read)
  157. assert.NoError(t, err, "failed to read data")
  158. assert.Equal(t, totalWrittenLength, n, "not enough bytes read")
  159. professorPlusFrankenstein := professor
  160. professorPlusFrankenstein = append(professorPlusFrankenstein, frankenstein...)
  161. assert.Equal(t, professorPlusFrankenstein, read)
  162. // Cleanup
  163. destroyTestGroup(t, g)
  164. }
  165. // test that Read returns an error if number of bytes read < size of
  166. // the given slice. Subsequent call should return 0, io.EOF.
  167. func TestGroupReaderRead2(t *testing.T) {
  168. g := createTestGroupWithHeadSizeLimit(t, 0)
  169. professor := []byte("Professor Monster")
  170. g.Write(professor)
  171. g.FlushAndSync()
  172. g.RotateFile()
  173. frankenstein := []byte("Frankenstein's Monster")
  174. frankensteinPart := []byte("Frankenstein")
  175. g.Write(frankensteinPart) // note writing only a part
  176. g.FlushAndSync()
  177. totalLength := len(professor) + len(frankenstein)
  178. read := make([]byte, totalLength)
  179. gr, err := g.NewReader(0)
  180. require.NoError(t, err, "failed to create reader")
  181. // 1) n < (size of the given slice), io.EOF
  182. n, err := gr.Read(read)
  183. assert.Equal(t, io.EOF, err)
  184. assert.Equal(t, len(professor)+len(frankensteinPart), n, "Read more/less bytes than it is in the group")
  185. // 2) 0, io.EOF
  186. n, err = gr.Read([]byte("0"))
  187. assert.Equal(t, io.EOF, err)
  188. assert.Equal(t, 0, n)
  189. // Cleanup
  190. destroyTestGroup(t, g)
  191. }
  192. func TestMinIndex(t *testing.T) {
  193. g := createTestGroupWithHeadSizeLimit(t, 0)
  194. assert.Zero(t, g.MinIndex(), "MinIndex should be zero at the beginning")
  195. // Cleanup
  196. destroyTestGroup(t, g)
  197. }
  198. func TestMaxIndex(t *testing.T) {
  199. g := createTestGroupWithHeadSizeLimit(t, 0)
  200. assert.Zero(t, g.MaxIndex(), "MaxIndex should be zero at the beginning")
  201. g.WriteLine("Line 1")
  202. g.FlushAndSync()
  203. g.RotateFile()
  204. assert.Equal(t, 1, g.MaxIndex(), "MaxIndex should point to the last file")
  205. // Cleanup
  206. destroyTestGroup(t, g)
  207. }