github.com/biogo/biogo@v1.0.4/morass/morass_test.go (about) 1 // Copyright ©2011-2012 The bíogo Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package morass 6 7 import ( 8 "io" 9 "math/rand" 10 "runtime" 11 "testing" 12 "unsafe" 13 14 "gopkg.in/check.v1" 15 ) 16 17 const minInt = -int(^uint(0)>>1) - 1 18 19 // Tests 20 func Test(t *testing.T) { check.TestingT(t) } 21 22 type S struct{} 23 24 const ( 25 chunk = 100 26 testLen = 10000 27 ) 28 29 var _ = check.Suite(&S{}) 30 31 type intLesser int 32 33 func (i intLesser) Less(j interface{}) bool { return i < j.(intLesser) } 34 35 type structLesser struct { 36 A int 37 B int 38 } 39 40 func (i structLesser) Less(j interface{}) bool { return i.A < j.(structLesser).A } 41 42 func (s *S) TestMorass(c *check.C) { 43 for _, concurrent := range []bool{false, true} { 44 if m, err := New(intLesser(0), "", "", chunk, concurrent); err != nil { 45 m.CleanUp() 46 c.Fatalf("New Morass failed: %v", err) 47 } else { 48 var i int 49 for i = 0; i < testLen; i++ { 50 c.Check(int64(i), check.Equals, m.Pos()) 51 if err = m.Push(intLesser(rand.Int())); err != nil { 52 m.CleanUp() 53 c.Fatalf("Push %d failed: %v", i, err) 54 } 55 } 56 if err = m.Finalise(); err != nil { 57 m.CleanUp() 58 c.Fatalf("Finalise failed: %v", err) 59 } 60 c.Logf("Pushed %d values", i) 61 c.Check(m.Len(), check.Equals, int64(testLen)) 62 L: 63 for i = 0; i <= testLen; i++ { 64 var v intLesser 65 lv := intLesser(minInt) 66 c.Check(int64(i), check.Equals, m.Pos()) 67 switch err = m.Pull(&v); err { 68 case nil: 69 c.Check(v.Less(lv), check.Equals, false) 70 case io.EOF: 71 c.Logf("Pulled %d values", i) 72 c.Check(i, check.Equals, testLen) 73 break L 74 default: 75 m.CleanUp() 76 c.Fatalf("Pull failed: %v", err) 77 } 78 } 79 if err = m.CleanUp(); err != nil { 80 c.Fatalf("CleanUp failed: %v", err) 81 } 82 } 83 } 84 } 85 86 func (s *S) TestFast1(c *check.C) { 87 if m, err := New(intLesser(0), "", "", chunk, false); err != nil { 88 m.CleanUp() 89 c.Fatalf("New Morass failed: %v", err) 90 } else { 91 for r := 1; r <= 2; r++ { 92 var i int 93 for i = 0; i < chunk/2; i++ { 94 c.Check(int64(i), check.Equals, m.Pos()) 95 if err = m.Push(intLesser(rand.Int())); err != nil { 96 m.CleanUp() 97 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 98 } 99 } 100 if err = m.Finalise(); err != nil { 101 m.CleanUp() 102 c.Fatalf("Finalise failed on use %d: %v", r, err) 103 } 104 c.Logf("Pushed %d values", i) 105 c.Check(m.Len(), check.Equals, int64(chunk/2)) 106 L: 107 for i = 0; i <= testLen; i++ { 108 var v intLesser 109 lv := intLesser(minInt) 110 c.Check(int64(i), check.Equals, m.Pos()) 111 switch err = m.Pull(&v); err { 112 case nil: 113 c.Check(v.Less(lv), check.Equals, false) 114 case io.EOF: 115 c.Logf("Pulled %d values", i) 116 c.Check(i, check.Equals, chunk/2) 117 break L 118 default: 119 m.CleanUp() 120 c.Fatalf("Pull failed on use %d: %v", r, err) 121 } 122 } 123 if err = m.Clear(); err != nil { 124 m.CleanUp() 125 c.Fatalf("Clear failed on use %d: %v", r, err) 126 } 127 } 128 if err = m.CleanUp(); err != nil { 129 c.Fatalf("CleanUp failed: %v", err) 130 } 131 } 132 } 133 134 func (s *S) TestFast2(c *check.C) { 135 if m, err := New(structLesser{}, "", "", chunk, false); err != nil { 136 m.CleanUp() 137 c.Fatalf("New Morass failed: %v", err) 138 } else { 139 for r := 1; r <= 2; r++ { 140 var i int 141 for i = 0; i < chunk/2; i++ { 142 c.Check(int64(i), check.Equals, m.Pos()) 143 if err = m.Push(structLesser{rand.Int(), r}); err != nil { 144 m.CleanUp() 145 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 146 } 147 } 148 if err = m.Finalise(); err != nil { 149 m.CleanUp() 150 c.Fatalf("Finalise failed on use %d: %v", r, err) 151 } 152 c.Logf("Pushed %d values", i) 153 c.Check(m.Len(), check.Equals, int64(chunk/2)) 154 L: 155 for i = 0; i <= testLen; i++ { 156 var v structLesser 157 lv := structLesser{minInt, 0} 158 c.Check(int64(i), check.Equals, m.Pos()) 159 switch err = m.Pull(&v); err { 160 case nil: 161 c.Check(v.Less(lv), check.Equals, false) 162 c.Check(v.B, check.Equals, r) 163 case io.EOF: 164 c.Logf("Pulled %d values", i) 165 c.Check(i, check.Equals, chunk/2) 166 break L 167 default: 168 m.CleanUp() 169 c.Fatalf("Pull failed on use %d: %v", r, err) 170 } 171 } 172 if err = m.Clear(); err != nil { 173 m.CleanUp() 174 c.Fatalf("Clear failed on use %d: %v", r, err) 175 } 176 } 177 if err = m.CleanUp(); err != nil { 178 c.Fatalf("CleanUp failed: %v", err) 179 } 180 } 181 } 182 183 func (s *S) TestReuse1(c *check.C) { 184 if m, err := New(intLesser(0), "", "", chunk, false); err != nil { 185 m.CleanUp() 186 c.Fatalf("New Morass failed: %v", err) 187 } else { 188 for r := 1; r <= 2; r++ { 189 var i int 190 for i = 0; i < testLen; i++ { 191 c.Check(int64(i), check.Equals, m.Pos()) 192 if err = m.Push(intLesser(rand.Int())); err != nil { 193 m.CleanUp() 194 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 195 } 196 } 197 if err = m.Finalise(); err != nil { 198 m.CleanUp() 199 c.Fatalf("Finalise failed on use %d: %v", r, err) 200 } 201 c.Logf("Pushed %d values", i) 202 c.Check(m.Len(), check.Equals, int64(testLen)) 203 L: 204 for i = 0; i <= testLen; i++ { 205 var v intLesser 206 lv := intLesser(minInt) 207 c.Check(int64(i), check.Equals, m.Pos()) 208 switch err = m.Pull(&v); err { 209 case nil: 210 c.Check(v.Less(lv), check.Equals, false) 211 case io.EOF: 212 c.Logf("Pulled %d values", i) 213 c.Check(i, check.Equals, testLen) 214 break L 215 default: 216 m.CleanUp() 217 c.Fatalf("Pull failed on use %d: %v", r, err) 218 } 219 } 220 if err = m.Clear(); err != nil { 221 m.CleanUp() 222 c.Fatalf("Clear failed on use %d: %v", r, err) 223 } 224 } 225 if err = m.CleanUp(); err != nil { 226 c.Fatalf("CleanUp failed: %v", err) 227 } 228 } 229 } 230 231 func (s *S) TestReuse2(c *check.C) { 232 if m, err := New(structLesser{}, "", "", chunk, false); err != nil { 233 m.CleanUp() 234 c.Fatalf("New Morass failed: %v", err) 235 } else { 236 for r := 1; r <= 2; r++ { 237 var i int 238 for i = 0; i < testLen; i++ { 239 c.Check(int64(i), check.Equals, m.Pos()) 240 if err = m.Push(structLesser{rand.Int(), r}); err != nil { 241 m.CleanUp() 242 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 243 } 244 } 245 if err = m.Finalise(); err != nil { 246 m.CleanUp() 247 c.Fatalf("Finalise failed on use %d: %v", r, err) 248 } 249 c.Logf("Pushed %d values", i) 250 c.Check(m.Len(), check.Equals, int64(testLen)) 251 L: 252 for i = 0; i <= testLen; i++ { 253 var v structLesser 254 lv := structLesser{minInt, 0} 255 c.Check(int64(i), check.Equals, m.Pos()) 256 switch err = m.Pull(&v); err { 257 case nil: 258 c.Check(v.Less(lv), check.Equals, false) 259 c.Check(v.B, check.Equals, r) 260 case io.EOF: 261 c.Logf("Pulled %d values", i) 262 c.Check(i, check.Equals, testLen) 263 break L 264 default: 265 m.CleanUp() 266 c.Fatalf("Pull failed on use %d: %v", r, err) 267 } 268 } 269 if err = m.Clear(); err != nil { 270 m.CleanUp() 271 c.Fatalf("Clear failed on use %d: %v", r, err) 272 } 273 } 274 if err = m.CleanUp(); err != nil { 275 c.Fatalf("CleanUp failed: %v", err) 276 } 277 } 278 } 279 280 func (s *S) TestAutoClear(c *check.C) { 281 if m, err := New(intLesser(0), "", "", chunk, false); err != nil { 282 m.CleanUp() 283 c.Fatalf("New Morass failed: %v", err) 284 } else { 285 m.AutoClear = true 286 for r := 1; r <= 2; r++ { 287 var i int 288 for i = 0; i < testLen; i++ { 289 c.Check(int64(i), check.Equals, m.Pos()) 290 if err = m.Push(intLesser(rand.Int())); err != nil { 291 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 292 } 293 } 294 if err = m.Finalise(); err != nil { 295 m.CleanUp() 296 c.Fatalf("Finalise failed on use %d: %v", r, err) 297 } 298 c.Logf("Pushed %d values", i) 299 c.Check(m.Len(), check.Equals, int64(testLen)) 300 L: 301 for i = 0; i <= testLen; i++ { 302 var v intLesser 303 lv := intLesser(minInt) 304 c.Check(int64(i), check.Equals, m.Pos()) 305 switch err = m.Pull(&v); err { 306 case nil: 307 c.Check(v.Less(lv), check.Equals, false) 308 case io.EOF: 309 c.Logf("Pulled %d values", i) 310 c.Check(i, check.Equals, testLen) 311 break L 312 default: 313 m.CleanUp() 314 c.Fatalf("Pull failed on repeat %d: %v", r, err) 315 } 316 } 317 } 318 if err = m.CleanUp(); err != nil { 319 c.Fatalf("CleanUp failed: %v", err) 320 } 321 } 322 } 323 324 func (s *S) TestAutoClearSafety(c *check.C) { 325 if m, err := New(intLesser(0), "", "", chunk, false); err != nil { 326 m.CleanUp() 327 c.Fatalf("New Morass failed: %v", err) 328 } else { 329 m.AutoClear = true 330 for r := 1; r <= 2; r++ { 331 var i int 332 for i = 0; i < testLen; i++ { 333 c.Check(int64(i), check.Equals, m.Pos()) 334 if err = m.Push(intLesser(rand.Int())); err != nil { 335 c.Fatalf("Push %d failed on use %d : %v", i, r, err) 336 } 337 } 338 if err = m.Finalise(); err != nil { 339 m.CleanUp() 340 c.Fatalf("Finalise failed on use %d: %v", r, err) 341 } 342 c.Logf("Pushed %d values", i) 343 c.Check(m.Len(), check.Equals, int64(testLen)) 344 L: 345 for i = 0; i <= testLen; i++ { 346 var v intLesser 347 lv := intLesser(minInt) 348 c.Check(int64(i), check.Equals, m.Pos()) 349 switch err = m.Pull(&v); err { 350 case nil: 351 c.Check(v.Less(lv), check.Equals, false) 352 case io.EOF: 353 c.Logf("Pulled %d values", i) 354 c.Check(i, check.Equals, testLen) 355 break L 356 default: 357 m.CleanUp() 358 c.Fatalf("Pull failed on repeat %d: %v", r, err) 359 } 360 } 361 if err = m.Clear(); err != nil { 362 m.CleanUp() 363 c.Fatalf("Clear failed on repeat %d: %v", r, err) 364 } 365 } 366 if err = m.CleanUp(); err != nil { 367 c.Fatalf("CleanUp failed: %v", err) 368 } 369 } 370 } 371 372 func BenchmarkFast(b *testing.B) { 373 benchmark(b, chunk, chunk/2, true) 374 } 375 376 func BenchmarkConcurrent(b *testing.B) { 377 benchmark(b, chunk, testLen, true) 378 } 379 380 func BenchmarkSequential(b *testing.B) { 381 benchmark(b, chunk, testLen, false) 382 } 383 384 func benchmark(b *testing.B, chunk, count int, concurrent bool) { 385 runtime.GC() // TODO: is this really necessary? If so, two calls are probably necessary. 386 b.ResetTimer() 387 b.SetBytes(int64(unsafe.Sizeof(intLesser(0))) * int64(count)) 388 if m, err := New(intLesser(0), "", "", chunk, concurrent); err == nil { 389 m.AutoClear = true 390 for i := 0; i < b.N; i++ { 391 for j := 0; j < count; j++ { 392 if err = m.Push(intLesser(rand.Int())); err != nil { 393 m.CleanUp() 394 b.Fatalf("Push %d failed: %v", j, err) 395 } 396 } 397 if err = m.Finalise(); err != nil { 398 m.CleanUp() 399 b.Fatalf("Finalise failed: %v", err) 400 } 401 L: 402 for j := 0; j <= count; j++ { 403 var v intLesser 404 switch err = m.Pull(&v); err { 405 case nil: 406 case io.EOF: 407 m.Clear() 408 break L 409 default: 410 m.CleanUp() 411 b.Fatalf("Pull %d failed: %v", j, err) 412 } 413 } 414 } 415 if err = m.CleanUp(); err != nil { 416 b.Fatalf("Finalise failed: %v", err) 417 } 418 } 419 }