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.

291 lines
7.9 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
  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. err := g.FlushAndSync()
  45. require.NoError(t, err)
  46. assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
  47. // Even calling checkHeadSizeLimit manually won't rotate it.
  48. g.checkHeadSizeLimit()
  49. assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000)
  50. // Write 1000 more bytes.
  51. err = g.WriteLine(tmrand.Str(999))
  52. require.NoError(t, err, "Error appending to head")
  53. err = g.FlushAndSync()
  54. require.NoError(t, err)
  55. // Calling checkHeadSizeLimit this time rolls it.
  56. g.checkHeadSizeLimit()
  57. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1000000, 0)
  58. // Write 1000 more bytes.
  59. err = g.WriteLine(tmrand.Str(999))
  60. require.NoError(t, err, "Error appending to head")
  61. err = g.FlushAndSync()
  62. require.NoError(t, err)
  63. // Calling checkHeadSizeLimit does nothing.
  64. g.checkHeadSizeLimit()
  65. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1001000, 1000)
  66. // Write 1000 bytes 999 times.
  67. for i := 0; i < 999; i++ {
  68. err = g.WriteLine(tmrand.Str(999))
  69. require.NoError(t, err, "Error appending to head")
  70. }
  71. err = g.FlushAndSync()
  72. require.NoError(t, err)
  73. assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 2000000, 1000000)
  74. // Calling checkHeadSizeLimit rolls it again.
  75. g.checkHeadSizeLimit()
  76. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2000000, 0)
  77. // Write 1000 more bytes.
  78. _, err = g.Head.Write([]byte(tmrand.Str(999) + "\n"))
  79. require.NoError(t, err, "Error appending to head")
  80. err = g.FlushAndSync()
  81. require.NoError(t, err)
  82. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
  83. // Calling checkHeadSizeLimit does nothing.
  84. g.checkHeadSizeLimit()
  85. assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000)
  86. // Cleanup
  87. destroyTestGroup(t, g)
  88. }
  89. func TestRotateFile(t *testing.T) {
  90. g := createTestGroupWithHeadSizeLimit(t, 0)
  91. // Create a different temporary directory and move into it, to make sure
  92. // relative paths are resolved at Group creation
  93. origDir, err := os.Getwd()
  94. require.NoError(t, err)
  95. defer func() {
  96. if err := os.Chdir(origDir); err != nil {
  97. t.Error(err)
  98. }
  99. }()
  100. dir, err := ioutil.TempDir("", "rotate_test")
  101. require.NoError(t, err)
  102. defer os.RemoveAll(dir)
  103. err = os.Chdir(dir)
  104. require.NoError(t, err)
  105. require.True(t, filepath.IsAbs(g.Head.Path))
  106. require.True(t, filepath.IsAbs(g.Dir))
  107. // Create and rotate files
  108. err = g.WriteLine("Line 1")
  109. require.NoError(t, err)
  110. err = g.WriteLine("Line 2")
  111. require.NoError(t, err)
  112. err = g.WriteLine("Line 3")
  113. require.NoError(t, err)
  114. err = g.FlushAndSync()
  115. require.NoError(t, err)
  116. g.RotateFile()
  117. err = g.WriteLine("Line 4")
  118. require.NoError(t, err)
  119. err = g.WriteLine("Line 5")
  120. require.NoError(t, err)
  121. err = g.WriteLine("Line 6")
  122. require.NoError(t, err)
  123. err = g.FlushAndSync()
  124. require.NoError(t, err)
  125. // Read g.Head.Path+"000"
  126. body1, err := ioutil.ReadFile(g.Head.Path + ".000")
  127. assert.NoError(t, err, "Failed to read first rolled file")
  128. if string(body1) != "Line 1\nLine 2\nLine 3\n" {
  129. t.Errorf("got unexpected contents: [%v]", string(body1))
  130. }
  131. // Read g.Head.Path
  132. body2, err := ioutil.ReadFile(g.Head.Path)
  133. assert.NoError(t, err, "Failed to read first rolled file")
  134. if string(body2) != "Line 4\nLine 5\nLine 6\n" {
  135. t.Errorf("got unexpected contents: [%v]", string(body2))
  136. }
  137. // Make sure there are no files in the current, temporary directory
  138. files, err := ioutil.ReadDir(".")
  139. require.NoError(t, err)
  140. assert.Empty(t, files)
  141. // Cleanup
  142. destroyTestGroup(t, g)
  143. }
  144. func TestWrite(t *testing.T) {
  145. g := createTestGroupWithHeadSizeLimit(t, 0)
  146. written := []byte("Medusa")
  147. _, err := g.Write(written)
  148. require.NoError(t, err)
  149. err = g.FlushAndSync()
  150. require.NoError(t, err)
  151. read := make([]byte, len(written))
  152. gr, err := g.NewReader(0)
  153. require.NoError(t, err, "failed to create reader")
  154. _, err = gr.Read(read)
  155. assert.NoError(t, err, "failed to read data")
  156. assert.Equal(t, written, read)
  157. // Cleanup
  158. destroyTestGroup(t, g)
  159. }
  160. // test that Read reads the required amount of bytes from all the files in the
  161. // group and returns no error if n == size of the given slice.
  162. func TestGroupReaderRead(t *testing.T) {
  163. g := createTestGroupWithHeadSizeLimit(t, 0)
  164. professor := []byte("Professor Monster")
  165. _, err := g.Write(professor)
  166. require.NoError(t, err)
  167. err = g.FlushAndSync()
  168. require.NoError(t, err)
  169. g.RotateFile()
  170. frankenstein := []byte("Frankenstein's Monster")
  171. _, err = g.Write(frankenstein)
  172. require.NoError(t, err)
  173. err = g.FlushAndSync()
  174. require.NoError(t, err)
  175. totalWrittenLength := len(professor) + len(frankenstein)
  176. read := make([]byte, totalWrittenLength)
  177. gr, err := g.NewReader(0)
  178. require.NoError(t, err, "failed to create reader")
  179. n, err := gr.Read(read)
  180. assert.NoError(t, err, "failed to read data")
  181. assert.Equal(t, totalWrittenLength, n, "not enough bytes read")
  182. professorPlusFrankenstein := professor
  183. professorPlusFrankenstein = append(professorPlusFrankenstein, frankenstein...)
  184. assert.Equal(t, professorPlusFrankenstein, read)
  185. // Cleanup
  186. destroyTestGroup(t, g)
  187. }
  188. // test that Read returns an error if number of bytes read < size of
  189. // the given slice. Subsequent call should return 0, io.EOF.
  190. func TestGroupReaderRead2(t *testing.T) {
  191. g := createTestGroupWithHeadSizeLimit(t, 0)
  192. professor := []byte("Professor Monster")
  193. _, err := g.Write(professor)
  194. require.NoError(t, err)
  195. err = g.FlushAndSync()
  196. require.NoError(t, err)
  197. g.RotateFile()
  198. frankenstein := []byte("Frankenstein's Monster")
  199. frankensteinPart := []byte("Frankenstein")
  200. _, err = g.Write(frankensteinPart) // note writing only a part
  201. require.NoError(t, err)
  202. err = g.FlushAndSync()
  203. require.NoError(t, err)
  204. totalLength := len(professor) + len(frankenstein)
  205. read := make([]byte, totalLength)
  206. gr, err := g.NewReader(0)
  207. require.NoError(t, err, "failed to create reader")
  208. // 1) n < (size of the given slice), io.EOF
  209. n, err := gr.Read(read)
  210. assert.Equal(t, io.EOF, err)
  211. assert.Equal(t, len(professor)+len(frankensteinPart), n, "Read more/less bytes than it is in the group")
  212. // 2) 0, io.EOF
  213. n, err = gr.Read([]byte("0"))
  214. assert.Equal(t, io.EOF, err)
  215. assert.Equal(t, 0, n)
  216. // Cleanup
  217. destroyTestGroup(t, g)
  218. }
  219. func TestMinIndex(t *testing.T) {
  220. g := createTestGroupWithHeadSizeLimit(t, 0)
  221. assert.Zero(t, g.MinIndex(), "MinIndex should be zero at the beginning")
  222. // Cleanup
  223. destroyTestGroup(t, g)
  224. }
  225. func TestMaxIndex(t *testing.T) {
  226. g := createTestGroupWithHeadSizeLimit(t, 0)
  227. assert.Zero(t, g.MaxIndex(), "MaxIndex should be zero at the beginning")
  228. err := g.WriteLine("Line 1")
  229. require.NoError(t, err)
  230. err = g.FlushAndSync()
  231. require.NoError(t, err)
  232. g.RotateFile()
  233. assert.Equal(t, 1, g.MaxIndex(), "MaxIndex should point to the last file")
  234. // Cleanup
  235. destroyTestGroup(t, g)
  236. }