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.

history_test.go 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright (c) 2018 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package history
  4. import (
  5. "reflect"
  6. "strconv"
  7. "testing"
  8. "time"
  9. )
  10. const (
  11. timeFormat = "2006-01-02 15:04:05Z"
  12. )
  13. func TestEmptyBuffer(t *testing.T) {
  14. pastTime := easyParse(timeFormat)
  15. buf := NewHistoryBuffer(0, 0)
  16. if buf.Enabled() {
  17. t.Error("the buffer of size 0 must be considered disabled")
  18. }
  19. buf.Add(Item{
  20. Nick: "testnick",
  21. })
  22. since, complete := buf.Between(pastTime, time.Now(), false, 0)
  23. if len(since) != 0 {
  24. t.Error("shouldn't be able to add to disabled buf")
  25. }
  26. if complete {
  27. t.Error("the empty/disabled buffer should report results as incomplete")
  28. }
  29. buf.Resize(1, 0)
  30. if !buf.Enabled() {
  31. t.Error("the buffer of size 1 must be considered enabled")
  32. }
  33. since, complete = buf.Between(pastTime, time.Now(), false, 0)
  34. assertEqual(complete, true, t)
  35. assertEqual(len(since), 0, t)
  36. buf.Add(Item{
  37. Nick: "testnick",
  38. })
  39. since, complete = buf.Between(pastTime, time.Now(), false, 0)
  40. if len(since) != 1 {
  41. t.Error("should be able to store items in a nonempty buffer")
  42. }
  43. if !complete {
  44. t.Error("results should be complete")
  45. }
  46. if since[0].Nick != "testnick" {
  47. t.Error("retrived junk data")
  48. }
  49. buf.Add(Item{
  50. Nick: "testnick2",
  51. })
  52. since, complete = buf.Between(pastTime, time.Now(), false, 0)
  53. if len(since) != 1 {
  54. t.Error("expect exactly 1 item")
  55. }
  56. if complete {
  57. t.Error("results must be marked incomplete")
  58. }
  59. if since[0].Nick != "testnick2" {
  60. t.Error("retrieved junk data")
  61. }
  62. matchAll := func(item Item) bool { return true }
  63. assertEqual(toNicks(buf.Match(matchAll, false, 0)), []string{"testnick2"}, t)
  64. }
  65. func toNicks(items []Item) (result []string) {
  66. result = make([]string, len(items))
  67. for i, item := range items {
  68. result[i] = item.Nick
  69. }
  70. return
  71. }
  72. func easyParse(timestamp string) time.Time {
  73. result, err := time.Parse(timeFormat, timestamp)
  74. if err != nil {
  75. panic(err)
  76. }
  77. return result
  78. }
  79. func easyItem(nick string, timestamp string) (result Item) {
  80. result.Message.Time = easyParse(timestamp)
  81. result.Nick = nick
  82. return
  83. }
  84. func assertEqual(supplied, expected interface{}, t *testing.T) {
  85. if !reflect.DeepEqual(supplied, expected) {
  86. t.Errorf("expected %v but got %v", expected, supplied)
  87. }
  88. }
  89. func TestBuffer(t *testing.T) {
  90. start := easyParse("2006-01-01 00:00:00Z")
  91. buf := NewHistoryBuffer(3, 0)
  92. buf.Add(easyItem("testnick0", "2006-01-01 15:04:05Z"))
  93. buf.Add(easyItem("testnick1", "2006-01-02 15:04:05Z"))
  94. buf.Add(easyItem("testnick2", "2006-01-03 15:04:05Z"))
  95. since, complete := buf.Between(start, time.Now(), false, 0)
  96. assertEqual(complete, true, t)
  97. assertEqual(toNicks(since), []string{"testnick0", "testnick1", "testnick2"}, t)
  98. // add another item, evicting the first
  99. buf.Add(easyItem("testnick3", "2006-01-04 15:04:05Z"))
  100. since, complete = buf.Between(start, time.Now(), false, 0)
  101. assertEqual(complete, false, t)
  102. assertEqual(toNicks(since), []string{"testnick1", "testnick2", "testnick3"}, t)
  103. // now exclude the time of the discarded entry; results should be complete again
  104. since, complete = buf.Between(easyParse("2006-01-02 00:00:00Z"), time.Now(), false, 0)
  105. assertEqual(complete, true, t)
  106. assertEqual(toNicks(since), []string{"testnick1", "testnick2", "testnick3"}, t)
  107. since, complete = buf.Between(easyParse("2006-01-02 00:00:00Z"), easyParse("2006-01-03 00:00:00Z"), false, 0)
  108. assertEqual(complete, true, t)
  109. assertEqual(toNicks(since), []string{"testnick1"}, t)
  110. // shrink the buffer, cutting off testnick1
  111. buf.Resize(2, 0)
  112. since, complete = buf.Between(easyParse("2006-01-02 00:00:00Z"), time.Now(), false, 0)
  113. assertEqual(complete, false, t)
  114. assertEqual(toNicks(since), []string{"testnick2", "testnick3"}, t)
  115. buf.Resize(5, 0)
  116. buf.Add(easyItem("testnick4", "2006-01-05 15:04:05Z"))
  117. buf.Add(easyItem("testnick5", "2006-01-06 15:04:05Z"))
  118. buf.Add(easyItem("testnick6", "2006-01-07 15:04:05Z"))
  119. since, complete = buf.Between(easyParse("2006-01-03 00:00:00Z"), time.Now(), false, 0)
  120. assertEqual(complete, true, t)
  121. assertEqual(toNicks(since), []string{"testnick2", "testnick3", "testnick4", "testnick5", "testnick6"}, t)
  122. // test ascending order
  123. since, _ = buf.Between(easyParse("2006-01-03 00:00:00Z"), time.Now(), true, 2)
  124. assertEqual(toNicks(since), []string{"testnick2", "testnick3"}, t)
  125. }
  126. func autoItem(id int, t time.Time) (result Item) {
  127. result.Message.Time = t
  128. result.Nick = strconv.Itoa(id)
  129. return
  130. }
  131. func atoi(s string) int {
  132. result, err := strconv.Atoi(s)
  133. if err != nil {
  134. panic(err)
  135. }
  136. return result
  137. }
  138. func TestAutoresize(t *testing.T) {
  139. now := easyParse("2006-01-01 00:00:00Z")
  140. nowFunc := func() time.Time {
  141. return now
  142. }
  143. buf := NewHistoryBuffer(128, time.Hour)
  144. buf.nowFunc = nowFunc
  145. // add items slowly (one every 10 minutes): the buffer should not expand
  146. // beyond initialAutoSize
  147. id := 0
  148. for i := 0; i < 72; i += 1 {
  149. buf.Add(autoItem(id, now))
  150. if initialAutoSize < buf.length() {
  151. t.Errorf("buffer incorrectly resized above %d to %d", initialAutoSize, buf.length())
  152. }
  153. now = now.Add(time.Minute * 10)
  154. id += 1
  155. }
  156. items := buf.Latest(0)
  157. assertEqual(len(items), initialAutoSize, t)
  158. assertEqual(atoi(items[0].Nick), 40, t)
  159. assertEqual(atoi(items[len(items)-1].Nick), 71, t)
  160. // dump 100 items in very fast:
  161. for i := 0; i < 100; i += 1 {
  162. buf.Add(autoItem(id, now))
  163. now = now.Add(time.Second)
  164. id += 1
  165. }
  166. // ok, 5 items from the first batch are still in the 1-hour window;
  167. // we should overwrite until only those 5 are left, then start expanding
  168. // the buffer so that it retains those 5 and the 100 new items
  169. items = buf.Latest(0)
  170. assertEqual(len(items), 105, t)
  171. assertEqual(atoi(items[0].Nick), 67, t)
  172. assertEqual(atoi(items[len(items)-1].Nick), 171, t)
  173. // another 100 items very fast:
  174. for i := 0; i < 100; i += 1 {
  175. buf.Add(autoItem(id, now))
  176. now = now.Add(time.Second)
  177. id += 1
  178. }
  179. // should fill up to the maximum size of 128 and start overwriting
  180. items = buf.Latest(0)
  181. assertEqual(len(items), 128, t)
  182. assertEqual(atoi(items[0].Nick), 144, t)
  183. assertEqual(atoi(items[len(items)-1].Nick), 271, t)
  184. }
  185. func TestRoundUp(t *testing.T) {
  186. assertEqual(roundUpToPowerOfTwo(2), 2, t)
  187. assertEqual(roundUpToPowerOfTwo(3), 4, t)
  188. assertEqual(roundUpToPowerOfTwo(64), 64, t)
  189. assertEqual(roundUpToPowerOfTwo(65), 128, t)
  190. assertEqual(roundUpToPowerOfTwo(100), 128, t)
  191. assertEqual(roundUpToPowerOfTwo(1000), 1024, t)
  192. assertEqual(roundUpToPowerOfTwo(1025), 2048, t)
  193. assertEqual(roundUpToPowerOfTwo(269435457), 536870912, t)
  194. }