file_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. package hercules
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "gopkg.in/src-d/hercules.v3/rbtree"
  6. )
  7. func updateStatusFile(
  8. status interface{}, _ int, previousTime int, delta int) {
  9. status.(map[int]int64)[previousTime] += int64(delta)
  10. }
  11. func fixtureFile() (*File, map[int]int64) {
  12. status := map[int]int64{}
  13. file := NewFile(0, 100, NewStatus(status, updateStatusFile))
  14. return file, status
  15. }
  16. func TestInitializeFile(t *testing.T) {
  17. file, status := fixtureFile()
  18. dump := file.Dump()
  19. // Output:
  20. // 0 0
  21. // 100 -1
  22. assert.Equal(t, "0 0\n100 -1\n", dump)
  23. assert.Equal(t, int64(100), status[0])
  24. }
  25. func testPanicFile(t *testing.T, method func(*File), msg string) {
  26. defer func() {
  27. r := recover()
  28. assert.NotNil(t, r, "not panic()-ed")
  29. assert.IsType(t, "", r)
  30. assert.Contains(t, r.(string), msg)
  31. }()
  32. file, _ := fixtureFile()
  33. method(file)
  34. }
  35. func TestBullshitFile(t *testing.T) {
  36. testPanicFile(t, func(file *File) { file.Update(1, -10, 10, 0) }, "insert")
  37. testPanicFile(t, func(file *File) { file.Update(1, 110, 10, 0) }, "insert")
  38. testPanicFile(t, func(file *File) { file.Update(1, -10, 0, 10) }, "delete")
  39. testPanicFile(t, func(file *File) { file.Update(1, 100, 0, 10) }, "delete")
  40. testPanicFile(t, func(file *File) { file.Update(1, 0, -10, 0) }, "Length")
  41. testPanicFile(t, func(file *File) { file.Update(1, 0, 0, -10) }, "Length")
  42. testPanicFile(t, func(file *File) { file.Update(1, 0, -10, -10) }, "Length")
  43. testPanicFile(t, func(file *File) { file.Update(-1, 0, 10, 10) }, "time")
  44. file, status := fixtureFile()
  45. file.Update(1, 10, 0, 0)
  46. assert.Equal(t, int64(100), status[0])
  47. assert.Equal(t, int64(0), status[1])
  48. }
  49. func TestLenFile(t *testing.T) {
  50. file, _ := fixtureFile()
  51. assert.Equal(t, 100, file.Len())
  52. }
  53. func TestInsertFile(t *testing.T) {
  54. file, status := fixtureFile()
  55. file.Update(1, 10, 10, 0)
  56. dump := file.Dump()
  57. // Output:
  58. // 0 0
  59. // 10 1
  60. // 20 0
  61. // 110 -1
  62. assert.Equal(t, "0 0\n10 1\n20 0\n110 -1\n", dump)
  63. assert.Equal(t, int64(100), status[0])
  64. assert.Equal(t, int64(10), status[1])
  65. }
  66. func TestZeroInitializeFile(t *testing.T) {
  67. status := map[int]int64{}
  68. file := NewFile(0, 0, NewStatus(status, updateStatusFile))
  69. assert.NotContains(t, status, 0)
  70. dump := file.Dump()
  71. // Output:
  72. // 0 -1
  73. assert.Equal(t, "0 -1\n", dump)
  74. file.Update(1, 0, 10, 0)
  75. dump = file.Dump()
  76. // Output:
  77. // 0 1
  78. // 10 -1
  79. assert.Equal(t, "0 1\n10 -1\n", dump)
  80. assert.Equal(t, int64(10), status[1])
  81. }
  82. func TestDeleteFile(t *testing.T) {
  83. file, status := fixtureFile()
  84. file.Update(1, 10, 0, 10)
  85. dump := file.Dump()
  86. // Output:
  87. // 0 0
  88. // 90 -1
  89. assert.Equal(t, "0 0\n90 -1\n", dump)
  90. assert.Equal(t, int64(90), status[0])
  91. assert.Equal(t, int64(0), status[1])
  92. }
  93. func TestFusedFile(t *testing.T) {
  94. file, status := fixtureFile()
  95. file.Update(1, 10, 6, 7)
  96. dump := file.Dump()
  97. // Output:
  98. // 0 0
  99. // 10 1
  100. // 16 0
  101. // 99 -1
  102. assert.Equal(t, "0 0\n10 1\n16 0\n99 -1\n", dump)
  103. assert.Equal(t, int64(93), status[0])
  104. assert.Equal(t, int64(6), status[1])
  105. }
  106. func TestInsertSameTimeFile(t *testing.T) {
  107. file, status := fixtureFile()
  108. file.Update(0, 5, 10, 0)
  109. dump := file.Dump()
  110. // Output:
  111. // 0 0
  112. // 110 -1
  113. assert.Equal(t, "0 0\n110 -1\n", dump)
  114. assert.Equal(t, int64(110), status[0])
  115. }
  116. func TestInsertSameStartFile(t *testing.T) {
  117. file, status := fixtureFile()
  118. file.Update(1, 10, 10, 0)
  119. file.Update(2, 10, 10, 0)
  120. dump := file.Dump()
  121. // Output:
  122. // 0 0
  123. // 10 2
  124. // 20 1
  125. // 30 0
  126. // 120 -1
  127. assert.Equal(t, "0 0\n10 2\n20 1\n30 0\n120 -1\n", dump)
  128. assert.Equal(t, int64(100), status[0])
  129. assert.Equal(t, int64(10), status[1])
  130. assert.Equal(t, int64(10), status[2])
  131. }
  132. func TestInsertEndFile(t *testing.T) {
  133. file, status := fixtureFile()
  134. file.Update(1, 100, 10, 0)
  135. dump := file.Dump()
  136. // Output:
  137. // 0 0
  138. // 100 1
  139. // 110 -1
  140. assert.Equal(t, "0 0\n100 1\n110 -1\n", dump)
  141. assert.Equal(t, int64(100), status[0])
  142. assert.Equal(t, int64(10), status[1])
  143. }
  144. func TestDeleteSameStart0File(t *testing.T) {
  145. file, status := fixtureFile()
  146. file.Update(1, 0, 0, 10)
  147. dump := file.Dump()
  148. // Output:
  149. // 0 0
  150. // 90 -1
  151. assert.Equal(t, "0 0\n90 -1\n", dump)
  152. assert.Equal(t, int64(90), status[0])
  153. assert.Equal(t, int64(0), status[1])
  154. }
  155. func TestDeleteSameStartMiddleFile(t *testing.T) {
  156. file, status := fixtureFile()
  157. file.Update(1, 10, 10, 0)
  158. file.Update(2, 10, 0, 5)
  159. dump := file.Dump()
  160. // Output:
  161. // 0 0
  162. // 10 1
  163. // 15 0
  164. // 105 -1
  165. assert.Equal(t, "0 0\n10 1\n15 0\n105 -1\n", dump)
  166. assert.Equal(t, int64(100), status[0])
  167. assert.Equal(t, int64(5), status[1])
  168. }
  169. func TestDeleteIntersectionFile(t *testing.T) {
  170. file, status := fixtureFile()
  171. file.Update(1, 10, 10, 0)
  172. file.Update(2, 15, 0, 10)
  173. dump := file.Dump()
  174. // Output:
  175. // 0 0
  176. // 10 1
  177. // 15 0
  178. // 100 -1
  179. assert.Equal(t, "0 0\n10 1\n15 0\n100 -1\n", dump)
  180. assert.Equal(t, int64(95), status[0])
  181. assert.Equal(t, int64(5), status[1])
  182. }
  183. func TestDeleteAllFile(t *testing.T) {
  184. file, status := fixtureFile()
  185. file.Update(1, 0, 0, 100)
  186. // Output:
  187. // 0 -1
  188. dump := file.Dump()
  189. assert.Equal(t, "0 -1\n", dump)
  190. assert.Equal(t, int64(0), status[0])
  191. assert.Equal(t, int64(0), status[1])
  192. }
  193. func TestFusedIntersectionFile(t *testing.T) {
  194. file, status := fixtureFile()
  195. file.Update(1, 10, 10, 0)
  196. file.Update(2, 15, 3, 10)
  197. dump := file.Dump()
  198. // Output:
  199. // 0 0
  200. // 10 1
  201. // 15 2
  202. // 18 0
  203. // 103 -1
  204. assert.Equal(t, "0 0\n10 1\n15 2\n18 0\n103 -1\n", dump)
  205. assert.Equal(t, int64(95), status[0])
  206. assert.Equal(t, int64(5), status[1])
  207. assert.Equal(t, int64(3), status[2])
  208. }
  209. func TestTortureFile(t *testing.T) {
  210. file, status := fixtureFile()
  211. // 0 0 | 100 -1 [0]: 100
  212. file.Update(1, 20, 30, 0)
  213. // 0 0 | 20 1 | 50 0 | 130 -1 [0]: 100, [1]: 30
  214. file.Update(2, 20, 0, 5)
  215. // 0 0 | 20 1 | 45 0 | 125 -1 [0]: 100, [1]: 25
  216. file.Update(3, 20, 0, 5)
  217. // 0 0 | 20 1 | 40 0 | 120 -1 [0]: 100, [1]: 20
  218. file.Update(4, 20, 10, 0)
  219. // 0 0 | 20 4 | 30 1 | 50 0 | 130 -1 [0]: 100, [1]: 20, [4]: 10
  220. file.Update(5, 45, 0, 10)
  221. // 0 0 | 20 4 | 30 1 | 45 0 | 120 -1 [0]: 95, [1]: 15, [4]: 10
  222. file.Update(6, 45, 5, 0)
  223. // 0 0 | 20 4 | 30 1 | 45 6 | 50 0 | 125 -1 [0]: 95, [1]: 15, [4]: 10, [6]: 5
  224. file.Update(7, 10, 0, 50)
  225. // 0 0 | 75 -1 [0]: 75
  226. file.Update(8, 0, 10, 10)
  227. // 0 8 | 10 0 | 75 -1 [0]: 65, [8]: 10
  228. dump := file.Dump()
  229. assert.Equal(t, "0 8\n10 0\n75 -1\n", dump)
  230. assert.Equal(t, int64(65), status[0])
  231. assert.Equal(t, int64(0), status[1])
  232. assert.Equal(t, int64(0), status[2])
  233. assert.Equal(t, int64(0), status[3])
  234. assert.Equal(t, int64(0), status[4])
  235. assert.Equal(t, int64(0), status[5])
  236. assert.Equal(t, int64(0), status[6])
  237. assert.Equal(t, int64(0), status[7])
  238. assert.Equal(t, int64(10), status[8])
  239. }
  240. func TestInsertDeleteSameTimeFile(t *testing.T) {
  241. file, status := fixtureFile()
  242. file.Update(0, 10, 10, 20)
  243. dump := file.Dump()
  244. assert.Equal(t, "0 0\n90 -1\n", dump)
  245. assert.Equal(t, int64(90), status[0])
  246. file.Update(0, 10, 20, 10)
  247. dump = file.Dump()
  248. assert.Equal(t, "0 0\n100 -1\n", dump)
  249. assert.Equal(t, int64(100), status[0])
  250. }
  251. func TestBug1File(t *testing.T) {
  252. file, status := fixtureFile()
  253. file.Update(316, 1, 86, 0)
  254. file.Update(316, 87, 0, 99)
  255. file.Update(251, 0, 1, 0)
  256. file.Update(251, 1, 0, 1)
  257. dump := file.Dump()
  258. assert.Equal(t, "0 251\n1 316\n87 -1\n", dump)
  259. assert.Equal(t, int64(1), status[251])
  260. assert.Equal(t, int64(86), status[316])
  261. file.Update(316, 0, 0, 1)
  262. file.Update(316, 0, 1, 0)
  263. dump = file.Dump()
  264. assert.Equal(t, "0 316\n87 -1\n", dump)
  265. assert.Equal(t, int64(0), status[251])
  266. assert.Equal(t, int64(87), status[316])
  267. }
  268. func TestBug2File(t *testing.T) {
  269. file, status := fixtureFile()
  270. file.Update(316, 1, 86, 0)
  271. file.Update(316, 87, 0, 99)
  272. file.Update(251, 0, 1, 0)
  273. file.Update(251, 1, 0, 1)
  274. dump := file.Dump()
  275. assert.Equal(t, "0 251\n1 316\n87 -1\n", dump)
  276. file.Update(316, 0, 1, 1)
  277. dump = file.Dump()
  278. assert.Equal(t, "0 316\n87 -1\n", dump)
  279. assert.Equal(t, int64(0), status[251])
  280. assert.Equal(t, int64(87), status[316])
  281. }
  282. func TestJoinFile(t *testing.T) {
  283. file, status := fixtureFile()
  284. file.Update(1, 10, 10, 0)
  285. file.Update(1, 30, 10, 0)
  286. file.Update(1, 20, 10, 10)
  287. dump := file.Dump()
  288. assert.Equal(t, "0 0\n10 1\n40 0\n120 -1\n", dump)
  289. assert.Equal(t, int64(90), status[0])
  290. assert.Equal(t, int64(30), status[1])
  291. }
  292. func TestBug3File(t *testing.T) {
  293. file, status := fixtureFile()
  294. file.Update(0, 1, 0, 99)
  295. file.Update(0, 0, 1, 1)
  296. dump := file.Dump()
  297. assert.Equal(t, "0 0\n1 -1\n", dump)
  298. assert.Equal(t, int64(1), status[0])
  299. }
  300. func TestBug4File(t *testing.T) {
  301. status := map[int]int64{}
  302. file := NewFile(0, 10, NewStatus(status, updateStatusFile))
  303. file.Update(125, 0, 20, 9)
  304. file.Update(125, 0, 20, 20)
  305. file.Update(166, 12, 1, 1)
  306. file.Update(214, 2, 1, 1)
  307. file.Update(214, 4, 9, 0)
  308. file.Update(214, 27, 1, 1)
  309. file.Update(215, 3, 1, 1)
  310. file.Update(215, 13, 1, 1)
  311. file.Update(215, 17, 1, 1)
  312. file.Update(215, 19, 5, 0)
  313. file.Update(215, 25, 0, 1)
  314. file.Update(215, 31, 6, 1)
  315. file.Update(215, 27, 15, 0)
  316. file.Update(215, 2, 25, 4)
  317. file.Update(215, 28, 1, 1)
  318. file.Update(215, 30, 7, 2)
  319. file.Update(215, 38, 1, 0)
  320. file.Update(215, 40, 4, 2)
  321. file.Update(215, 46, 1, 0)
  322. file.Update(215, 49, 1, 0)
  323. file.Update(215, 52, 2, 6)
  324. dump := file.Dump()
  325. assert.Equal(t, "0 125\n2 215\n48 125\n50 215\n69 125\n73 215\n79 125\n80 0\n81 -1\n", dump)
  326. }
  327. func TestBug5File(t *testing.T) {
  328. status := map[int]int64{}
  329. keys := []int{0, 2, 4, 7, 10}
  330. vals := []int{24, 28, 24, 28, -1}
  331. file := NewFileFromTree(keys, vals, NewStatus(status, updateStatusFile))
  332. file.Update(28, 0, 1, 3)
  333. dump := file.Dump()
  334. assert.Equal(t, "0 28\n2 24\n5 28\n8 -1\n", dump)
  335. keys = []int{0, 1, 16, 18}
  336. vals = []int{305, 0, 157, -1}
  337. file = NewFileFromTree(keys, vals, NewStatus(status, updateStatusFile))
  338. file.Update(310, 0, 0, 2)
  339. dump = file.Dump()
  340. assert.Equal(t, "0 0\n14 157\n16 -1\n", dump)
  341. }
  342. func TestMinMaxAbs64Funcs(t *testing.T) {
  343. var a int64 = 1
  344. var b int64 = -1
  345. assert.Equal(t, min64(a, b), b)
  346. assert.Equal(t, max64(a, b), a)
  347. assert.Equal(t, min64(b, a), b)
  348. assert.Equal(t, max64(b, a), a)
  349. assert.Equal(t, abs64(a), a)
  350. assert.Equal(t, abs64(b), a)
  351. }
  352. func TestNewFileFromTreeInvalidSize(t *testing.T) {
  353. keys := [...]int{1, 2, 3}
  354. vals := [...]int{4, 5}
  355. assert.Panics(t, func() { NewFileFromTree(keys[:], vals[:]) })
  356. }
  357. func TestUpdatePanic(t *testing.T) {
  358. keys := [...]int{0}
  359. vals := [...]int{-1}
  360. file := NewFileFromTree(keys[:], vals[:])
  361. file.tree.DeleteWithKey(0)
  362. file.tree.Insert(rbtree.Item{Key: -1, Value: -1})
  363. var paniced interface{}
  364. func() {
  365. defer func() {
  366. paniced = recover()
  367. }()
  368. file.Update(1, 0, 1, 0)
  369. }()
  370. assert.Contains(t, paniced, "invalid tree state")
  371. }
  372. func TestFileStatus(t *testing.T) {
  373. f, _ := fixtureFile()
  374. assert.Panics(t, func() { f.Status(1) })
  375. assert.NotNil(t, f.Status(0))
  376. }
  377. func TestFileValidate(t *testing.T) {
  378. keys := [...]int{0}
  379. vals := [...]int{-1}
  380. file := NewFileFromTree(keys[:], vals[:])
  381. file.tree.DeleteWithKey(0)
  382. file.tree.Insert(rbtree.Item{Key: -1, Value: -1})
  383. assert.Panics(t, func() { file.Validate() })
  384. file.tree.DeleteWithKey(-1)
  385. file.tree.Insert(rbtree.Item{Key: 0, Value: -1})
  386. file.Validate()
  387. file.tree.DeleteWithKey(0)
  388. file.tree.Insert(rbtree.Item{Key: 0, Value: 0})
  389. assert.Panics(t, func() { file.Validate() })
  390. file.tree.DeleteWithKey(0)
  391. file.tree.Insert(rbtree.Item{Key: 0, Value: 1})
  392. file.tree.Insert(rbtree.Item{Key: 1, Value: 1})
  393. file.tree.Insert(rbtree.Item{Key: 2, Value: -1})
  394. file.Validate()
  395. file.tree.FindGE(2).Item().Key = 1
  396. assert.Panics(t, func() { file.Validate() })
  397. }