filequeue_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package main
  2. import (
  3. "reflect"
  4. "sync"
  5. "sync/atomic"
  6. "testing"
  7. )
  8. func TestFileQueueAdd(t *testing.T) {
  9. q := NewFileQueue()
  10. q.Add("foo", nil, nil)
  11. }
  12. func TestFileQueueAddSorting(t *testing.T) {
  13. q := NewFileQueue()
  14. q.SetAvailable("zzz", []string{"nodeID"})
  15. q.SetAvailable("aaa", []string{"nodeID"})
  16. q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
  17. q.Add("aaa", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
  18. b, _ := q.Get("nodeID")
  19. if b.name != "aaa" {
  20. t.Errorf("Incorrectly sorted get: %+v", b)
  21. }
  22. q = NewFileQueue()
  23. q.SetAvailable("zzz", []string{"nodeID"})
  24. q.SetAvailable("aaa", []string{"nodeID"})
  25. q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
  26. b, _ = q.Get("nodeID") // Start on zzzz
  27. if b.name != "zzz" {
  28. t.Errorf("Incorrectly sorted get: %+v", b)
  29. }
  30. q.Add("aaa", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
  31. b, _ = q.Get("nodeID")
  32. if b.name != "zzz" {
  33. // Continue rather than starting a new file
  34. t.Errorf("Incorrectly sorted get: %+v", b)
  35. }
  36. }
  37. func TestFileQueueLen(t *testing.T) {
  38. q := NewFileQueue()
  39. q.Add("foo", nil, nil)
  40. q.Add("bar", nil, nil)
  41. if l := q.Len(); l != 2 {
  42. t.Errorf("Incorrect len %d != 2 after adds", l)
  43. }
  44. }
  45. func TestFileQueueGet(t *testing.T) {
  46. q := NewFileQueue()
  47. q.SetAvailable("foo", []string{"nodeID"})
  48. q.SetAvailable("bar", []string{"nodeID"})
  49. q.Add("foo", []Block{
  50. {Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
  51. {Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
  52. {Offset: 256, Size: 128, Hash: []byte("more foo hash bytes")},
  53. }, nil)
  54. q.Add("bar", []Block{
  55. {Offset: 0, Size: 128, Hash: []byte("some bar hash bytes")},
  56. {Offset: 128, Size: 128, Hash: []byte("some other bar hash bytes")},
  57. }, nil)
  58. // First get should return the first block of the first file
  59. expected := queuedBlock{
  60. name: "bar",
  61. block: Block{
  62. Offset: 0,
  63. Size: 128,
  64. Hash: []byte("some bar hash bytes"),
  65. },
  66. }
  67. actual, ok := q.Get("nodeID")
  68. if !ok {
  69. t.Error("Unexpected non-OK Get()")
  70. }
  71. if !reflect.DeepEqual(expected, actual) {
  72. t.Errorf("Incorrect block returned (first)\n E: %+v\n A: %+v", expected, actual)
  73. }
  74. // Second get should return the next block of the first file
  75. expected = queuedBlock{
  76. name: "bar",
  77. block: Block{
  78. Offset: 128,
  79. Size: 128,
  80. Hash: []byte("some other bar hash bytes"),
  81. },
  82. index: 1,
  83. }
  84. actual, ok = q.Get("nodeID")
  85. if !ok {
  86. t.Error("Unexpected non-OK Get()")
  87. }
  88. if !reflect.DeepEqual(expected, actual) {
  89. t.Errorf("Incorrect block returned (second)\n E: %+v\n A: %+v", expected, actual)
  90. }
  91. // Third get should return the first block of the second file
  92. expected = queuedBlock{
  93. name: "foo",
  94. block: Block{
  95. Offset: 0,
  96. Size: 128,
  97. Hash: []byte("some foo hash bytes"),
  98. },
  99. }
  100. actual, ok = q.Get("nodeID")
  101. if !ok {
  102. t.Error("Unexpected non-OK Get()")
  103. }
  104. if !reflect.DeepEqual(expected, actual) {
  105. t.Errorf("Incorrect block returned (third)\n E: %+v\n A: %+v", expected, actual)
  106. }
  107. }
  108. /*
  109. func TestFileQueueDone(t *testing.T) {
  110. ch := make(chan content)
  111. var recv sync.WaitGroup
  112. recv.Add(1)
  113. go func() {
  114. content := <-ch
  115. if bytes.Compare(content.data, []byte("first block bytes")) != 0 {
  116. t.Error("Incorrect data in first content block")
  117. }
  118. content = <-ch
  119. if bytes.Compare(content.data, []byte("second block bytes")) != 0 {
  120. t.Error("Incorrect data in second content block")
  121. }
  122. _, ok := <-ch
  123. if ok {
  124. t.Error("Content channel not closed")
  125. }
  126. recv.Done()
  127. }()
  128. q := FileQueue{resolver: fakeResolver{}}
  129. q.Add("foo", []Block{
  130. {Offset: 0, Length: 128, Hash: []byte("some foo hash bytes")},
  131. {Offset: 128, Length: 128, Hash: []byte("some other foo hash bytes")},
  132. }, ch)
  133. b0, _ := q.Get("nodeID")
  134. b1, _ := q.Get("nodeID")
  135. q.Done(b0.name, b0.block.Offset, []byte("first block bytes"))
  136. q.Done(b1.name, b1.block.Offset, []byte("second block bytes"))
  137. recv.Wait()
  138. // Queue should now have one file less
  139. if l := q.Len(); l != 0 {
  140. t.Error("Queue not empty")
  141. }
  142. _, ok := q.Get("nodeID")
  143. if ok {
  144. t.Error("Unexpected OK Get()")
  145. }
  146. }
  147. */
  148. func TestFileQueueGetNodeIDs(t *testing.T) {
  149. q := NewFileQueue()
  150. q.SetAvailable("a-foo", []string{"nodeID", "a"})
  151. q.SetAvailable("b-bar", []string{"nodeID", "b"})
  152. q.Add("a-foo", []Block{
  153. {Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
  154. {Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
  155. {Offset: 256, Size: 128, Hash: []byte("more foo hash bytes")},
  156. }, nil)
  157. q.Add("b-bar", []Block{
  158. {Offset: 0, Size: 128, Hash: []byte("some bar hash bytes")},
  159. {Offset: 128, Size: 128, Hash: []byte("some other bar hash bytes")},
  160. }, nil)
  161. expected := queuedBlock{
  162. name: "b-bar",
  163. block: Block{
  164. Offset: 0,
  165. Size: 128,
  166. Hash: []byte("some bar hash bytes"),
  167. },
  168. }
  169. actual, ok := q.Get("b")
  170. if !ok {
  171. t.Error("Unexpected non-OK Get()")
  172. }
  173. if !reflect.DeepEqual(expected, actual) {
  174. t.Errorf("Incorrect block returned\n E: %+v\n A: %+v", expected, actual)
  175. }
  176. expected = queuedBlock{
  177. name: "a-foo",
  178. block: Block{
  179. Offset: 0,
  180. Size: 128,
  181. Hash: []byte("some foo hash bytes"),
  182. },
  183. }
  184. actual, ok = q.Get("a")
  185. if !ok {
  186. t.Error("Unexpected non-OK Get()")
  187. }
  188. if !reflect.DeepEqual(expected, actual) {
  189. t.Errorf("Incorrect block returned\n E: %+v\n A: %+v", expected, actual)
  190. }
  191. expected = queuedBlock{
  192. name: "a-foo",
  193. block: Block{
  194. Offset: 128,
  195. Size: 128,
  196. Hash: []byte("some other foo hash bytes"),
  197. },
  198. index: 1,
  199. }
  200. actual, ok = q.Get("nodeID")
  201. if !ok {
  202. t.Error("Unexpected non-OK Get()")
  203. }
  204. if !reflect.DeepEqual(expected, actual) {
  205. t.Errorf("Incorrect block returned\n E: %+v\n A: %+v", expected, actual)
  206. }
  207. }
  208. func TestFileQueueThreadHandling(t *testing.T) {
  209. // This should pass with go test -race
  210. const n = 100
  211. var total int
  212. var blocks []Block
  213. for i := 1; i <= n; i++ {
  214. blocks = append(blocks, Block{Offset: int64(i), Size: 1})
  215. total += i
  216. }
  217. q := NewFileQueue()
  218. q.Add("foo", blocks, nil)
  219. q.SetAvailable("foo", []string{"nodeID"})
  220. var start = make(chan bool)
  221. var gotTot uint32
  222. var wg sync.WaitGroup
  223. wg.Add(n)
  224. for i := 1; i <= n; i++ {
  225. go func() {
  226. <-start
  227. b, _ := q.Get("nodeID")
  228. atomic.AddUint32(&gotTot, uint32(b.block.Offset))
  229. wg.Done()
  230. }()
  231. }
  232. close(start)
  233. wg.Wait()
  234. if int(gotTot) != total {
  235. t.Error("Total mismatch; %d != %d", gotTot, total)
  236. }
  237. }
  238. func TestDeleteAt(t *testing.T) {
  239. q := FileQueue{}
  240. for i := 0; i < 4; i++ {
  241. q.files = queuedFileList{{name: "a"}, {name: "b"}, {name: "c"}, {name: "d"}}
  242. q.deleteAt(i)
  243. if l := len(q.files); l != 3 {
  244. t.Fatal("deleteAt(%d) failed; %d != 3", i, l)
  245. }
  246. }
  247. q.files = queuedFileList{{name: "a"}}
  248. q.deleteAt(0)
  249. if l := len(q.files); l != 0 {
  250. t.Fatal("deleteAt(only) failed; %d != 0", l)
  251. }
  252. }