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  }