github.com/Schaudge/hts@v0.0.0-20240223063651-737b4d69d68c/bam/bam_test.go (about)

     1  // Copyright ©2013 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 bam
     6  
     7  import (
     8  	"bytes"
     9  	"compress/gzip"
    10  	"flag"
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"os"
    15  	"reflect"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/Schaudge/hts/bgzf"
    20  	"github.com/Schaudge/hts/bgzf/index"
    21  	"github.com/Schaudge/hts/internal"
    22  	"github.com/Schaudge/hts/sam"
    23  	"gopkg.in/check.v1"
    24  )
    25  
    26  var (
    27  	bam    = flag.Bool("bam", false, "output failing bam data for inspection")
    28  	allbam = flag.Bool("allbam", false, "output all bam data for inspection")
    29  )
    30  
    31  type failure bool
    32  
    33  func (f failure) String() string {
    34  	if f {
    35  		return "fail"
    36  	}
    37  	return "ok"
    38  }
    39  
    40  func clonedRefs(refs []*sam.Reference) []*sam.Reference {
    41  	c := make([]*sam.Reference, len(refs))
    42  	for i, r := range refs {
    43  		c[i] = r.Clone()
    44  	}
    45  	return c
    46  }
    47  
    48  func clonedRGs(rgs []*sam.ReadGroup) []*sam.ReadGroup {
    49  	c := make([]*sam.ReadGroup, len(rgs))
    50  	for i, r := range rgs {
    51  		c[i] = r.Clone()
    52  	}
    53  	return c
    54  }
    55  
    56  func clonedProgs(progs []*sam.Program) []*sam.Program {
    57  	c := make([]*sam.Program, len(progs))
    58  	for i, p := range progs {
    59  		c[i] = p.Clone()
    60  	}
    61  	return c
    62  }
    63  
    64  func Test(t *testing.T) {
    65  	t.Skip("these tests fail because the Scratch field does not match")
    66  	check.TestingT(t)
    67  }
    68  
    69  type S struct{}
    70  
    71  var _ = check.Suite(&S{})
    72  
    73  const maxInt = int(^uint(0) >> 1)
    74  
    75  var (
    76  	file   = flag.String("bench.file", "", "file to read for benchmarking")
    77  	findex = flag.String("bench.index", "", "index file to read for benchmarking")
    78  	conc   = flag.Int("conc", 1, "sets the level of concurrency for compression")
    79  )
    80  
    81  func (s *S) TestRead(c *check.C) {
    82  	for i, t := range []struct {
    83  		in     []byte
    84  		header *sam.Header
    85  		lines  int
    86  	}{
    87  		{
    88  			in:     bamHG00096_1000,
    89  			header: headerHG00096_1000,
    90  			lines:  1000,
    91  		},
    92  	} {
    93  		for omit := None; omit <= AllVariableLengthData; omit++ {
    94  			br, err := NewReader(bytes.NewBuffer(t.in), *conc)
    95  			c.Assert(err, check.Equals, nil)
    96  
    97  			c.Check(br.Header().Version, check.Equals, t.header.Version)
    98  			c.Check(br.Header().SortOrder, check.Equals, t.header.SortOrder)
    99  			c.Check(br.Header().GroupOrder, check.Equals, t.header.GroupOrder)
   100  			c.Check(br.Header().Comments, check.DeepEquals, t.header.Comments)
   101  			c.Check(clonedRefs(br.Header().Refs()), check.DeepEquals, clonedRefs(t.header.Refs()))
   102  			c.Check(clonedRGs(br.Header().RGs()), check.DeepEquals, clonedRGs(t.header.RGs()))
   103  			c.Check(clonedProgs(br.Header().Progs()), check.DeepEquals, clonedProgs(t.header.Progs()))
   104  
   105  			var lines int
   106  			for {
   107  				_, err := br.Read()
   108  				if err != nil {
   109  					c.Assert(err, check.Equals, io.EOF)
   110  					break
   111  				}
   112  				lines++
   113  			}
   114  			c.Check(lines, check.Equals, t.lines,
   115  				check.Commentf("got:%d expected:%d when omit=%d", lines, t.lines, omit))
   116  			if ok := reflect.DeepEqual(br.Header(), t.header) && lines == t.lines; *bam && !ok || *allbam {
   117  				bf, err := os.Create(fmt.Sprintf("read-%d-%s.bam", i, failure(!ok)))
   118  				c.Assert(err, check.Equals, nil)
   119  				bf.Write(t.in)
   120  				bf.Close()
   121  			}
   122  		}
   123  	}
   124  }
   125  
   126  func headerText(h *sam.Header) []byte {
   127  	b, _ := h.MarshalText()
   128  	return b
   129  }
   130  
   131  func (s *S) TestRoundTrip(c *check.C) {
   132  	for i, t := range []struct {
   133  		in     []byte
   134  		header *sam.Header
   135  		conc   int
   136  		lines  int
   137  	}{
   138  		{
   139  			in:     bamHG00096_1000,
   140  			header: headerHG00096_1000,
   141  			conc:   2,
   142  			lines:  1000,
   143  		},
   144  	} {
   145  		br, err := NewReader(bytes.NewBuffer(t.in), *conc)
   146  		c.Assert(err, check.Equals, nil)
   147  
   148  		var buf bytes.Buffer
   149  		bw, err := NewWriter(&buf, br.Header().Clone(), t.conc)
   150  		for {
   151  			r, err := br.Read()
   152  			if err != nil {
   153  				c.Assert(err, check.Equals, io.EOF)
   154  				break
   155  			}
   156  			bw.Write(r)
   157  		}
   158  		c.Assert(bw.Close(), check.Equals, nil)
   159  
   160  		br, err = NewReader(bytes.NewBuffer(t.in), *conc)
   161  		c.Assert(err, check.Equals, nil)
   162  		brr, err := NewReader(&buf, *conc)
   163  		c.Assert(err, check.Equals, nil)
   164  		c.Check(headerText(brr.Header()), check.DeepEquals, headerText(br.Header()))
   165  		c.Check(brr.Header(), check.DeepEquals, br.Header())
   166  		if !reflect.DeepEqual(brr.Header(), br.Header()) {
   167  			c.Check(brr.Header().Refs(), check.DeepEquals, br.Header().Refs())
   168  			c.Check(brr.Header().RGs(), check.DeepEquals, br.Header().RGs())
   169  			c.Check(brr.Header().Progs(), check.DeepEquals, br.Header().Progs())
   170  			c.Check(brr.Header().Comments, check.DeepEquals, br.Header().Comments)
   171  		}
   172  		allOK := true
   173  		for {
   174  			r, err := br.Read()
   175  			if err != nil {
   176  				c.Assert(err, check.Equals, io.EOF)
   177  			}
   178  			rr, err := brr.Read()
   179  			if err != nil {
   180  				c.Assert(err, check.Equals, io.EOF)
   181  				break
   182  			}
   183  			c.Check(rr, check.DeepEquals, r)
   184  			if !reflect.DeepEqual(rr, r) {
   185  				allOK = false
   186  			}
   187  		}
   188  		if ok := reflect.DeepEqual(br.Header(), brr.Header()) && allOK; *bam && !ok || *allbam {
   189  			bf, err := os.Create(fmt.Sprintf("roundtrip-%d-%s.bam", i, failure(!ok)))
   190  			c.Assert(err, check.Equals, nil)
   191  			bf.Write(t.in)
   192  			bf.Close()
   193  		}
   194  	}
   195  }
   196  
   197  func BenchmarkRead(b *testing.B) {
   198  	if *file == "" {
   199  		b.Skip("no file specified")
   200  	}
   201  	b.StopTimer()
   202  	f, err := os.Open(*file)
   203  	if err != nil {
   204  		b.Fatalf("Open failed: %v", err)
   205  	}
   206  	br, err := NewReader(f, *conc)
   207  	if err != nil {
   208  		b.Fatalf("NewReader failed: %v", err)
   209  	}
   210  	b.StartTimer()
   211  
   212  	for i := 0; i < b.N; i++ {
   213  		for {
   214  			_, err := br.Read()
   215  			if err != nil {
   216  				break
   217  			}
   218  		}
   219  	}
   220  	f.Close()
   221  }
   222  
   223  func BenchmarkReadIndex(b *testing.B) {
   224  	if *findex == "" {
   225  		b.Skip("no index file specified")
   226  	}
   227  	buf, err := ioutil.ReadFile(*findex)
   228  	if err != nil {
   229  		b.Fatalf("Index read failed: %v", err)
   230  	}
   231  	r := bytes.NewReader(buf)
   232  
   233  	b.ResetTimer()
   234  	for i := 0; i < b.N; i++ {
   235  		r.Seek(0, os.SEEK_SET)
   236  		_, err = ReadIndex(r)
   237  		if err != nil {
   238  			b.Fatal(err)
   239  		}
   240  	}
   241  }
   242  
   243  func BenchmarkReadCoreAndSeq(b *testing.B) {
   244  	if *file == "" {
   245  		b.Skip("no file specified")
   246  	}
   247  	b.StopTimer()
   248  	f, err := os.Open(*file)
   249  	if err != nil {
   250  		b.Fatalf("Open failed: %v", err)
   251  	}
   252  	br, err := NewReader(f, *conc)
   253  	if err != nil {
   254  		b.Fatalf("NewReader failed: %v", err)
   255  	}
   256  	b.StartTimer()
   257  
   258  	br.Omit(AuxTags)
   259  	for i := 0; i < b.N; i++ {
   260  		for {
   261  			_, err := br.Read()
   262  			if err != nil {
   263  				break
   264  			}
   265  		}
   266  	}
   267  	f.Close()
   268  }
   269  
   270  func BenchmarkReadCoreOnly(b *testing.B) {
   271  	if *file == "" {
   272  		b.Skip("no file specified")
   273  	}
   274  	b.StopTimer()
   275  	f, err := os.Open(*file)
   276  	if err != nil {
   277  		b.Fatalf("Open failed: %v", err)
   278  	}
   279  	br, err := NewReader(f, *conc)
   280  	if err != nil {
   281  		b.Fatalf("NewReader failed: %v", err)
   282  	}
   283  	b.StartTimer()
   284  
   285  	br.Omit(AllVariableLengthData)
   286  	for i := 0; i < b.N; i++ {
   287  		for {
   288  			_, err := br.Read()
   289  			if err != nil {
   290  				break
   291  			}
   292  		}
   293  	}
   294  	f.Close()
   295  }
   296  
   297  func BenchmarkWrite(b *testing.B) {
   298  	b.StopTimer()
   299  	br, err := NewReader(bytes.NewReader(bamHG00096_1000), *conc)
   300  	if err != nil {
   301  		b.Fatalf("NewReader failed: %v", err)
   302  	}
   303  	r, err := br.Read()
   304  	if err != nil {
   305  		b.Fatalf("Read failed: %v", err)
   306  	}
   307  	bw, err := NewWriter(ioutil.Discard, br.Header().Clone(), *conc)
   308  	if err != nil {
   309  		b.Fatalf("NewWriter failed: %v", err)
   310  	}
   311  	b.StartTimer()
   312  
   313  	for i := 0; i < b.N; i++ {
   314  		err = bw.Write(r)
   315  		if err != nil {
   316  			b.Fatalf("Write failed: %v", err)
   317  		}
   318  	}
   319  }
   320  
   321  func BenchmarkReadFile(b *testing.B) {
   322  	if *file == "" {
   323  		b.Skip("no file specified")
   324  	}
   325  
   326  	for i := 0; i < b.N; i++ {
   327  		f, err := os.Open(*file)
   328  		if err != nil {
   329  			b.Fatalf("Open failed: %v", err)
   330  		}
   331  		br, err := NewReader(f, *conc)
   332  		if err != nil {
   333  			b.Fatalf("NewReader failed: %v", err)
   334  		}
   335  		for {
   336  			_, err := br.Read()
   337  			if err != nil {
   338  				break
   339  			}
   340  		}
   341  		f.Close()
   342  	}
   343  }
   344  
   345  // The is to comparable to `time samtools view -b $file > /dev/null'.
   346  func BenchmarkRoundtripFile(b *testing.B) {
   347  	if *file == "" {
   348  		b.Skip("no file specified")
   349  	}
   350  
   351  	for i := 0; i < b.N; i++ {
   352  		f, err := os.Open(*file)
   353  		if err != nil {
   354  			b.Fatalf("Open failed: %v", err)
   355  		}
   356  		br, err := NewReader(f, *conc)
   357  		if err != nil {
   358  			b.Fatalf("NewReader failed: %v", err)
   359  		}
   360  		bw, err := NewWriter(ioutil.Discard, br.Header().Clone(), *conc)
   361  		if err != nil {
   362  			b.Fatalf("NewWriter failed: %v", err)
   363  		}
   364  		for {
   365  			r, err := br.Read()
   366  			if err != nil {
   367  				break
   368  			}
   369  			err = bw.Write(r)
   370  			if err != nil {
   371  				b.Fatalf("Write failed: %v", err)
   372  			}
   373  		}
   374  		f.Close()
   375  	}
   376  }
   377  
   378  func (s *S) TestSpecExamples(c *check.C) {
   379  	br, err := NewReader(bytes.NewReader(specExamples.data), *conc)
   380  	c.Assert(err, check.Equals, nil)
   381  	bh := br.Header()
   382  	c.Check(bh.Version, check.Equals, specExamples.header.Version)
   383  	c.Check(bh.SortOrder, check.Equals, specExamples.header.SortOrder)
   384  	c.Check(bh.GroupOrder, check.Equals, specExamples.header.GroupOrder)
   385  	c.Check(bh.Comments, check.DeepEquals, specExamples.header.Comments)
   386  	for i, expect := range specExamples.records {
   387  		r, err := br.Read()
   388  		if err != nil {
   389  			c.Errorf("Unexpected early error: %v", err)
   390  		}
   391  		c.Check(r.Name, check.Equals, expect.Name)
   392  		c.Check(r.Pos, check.Equals, expect.Pos) // Zero-based here.
   393  		c.Check(r.Flags, check.Equals, expect.Flags)
   394  		if r.Flags&sam.Unmapped == 0 {
   395  			c.Check(r.Ref, check.Not(check.Equals), nil)
   396  			if r.Ref != nil {
   397  				c.Check(r.Ref.Name(), check.Equals, bh.Refs()[0].Name())
   398  			}
   399  		} else {
   400  			c.Check(r.Ref, check.Equals, nil)
   401  		}
   402  		c.Check(r.MatePos, check.Equals, expect.MatePos) // Zero-based here.
   403  		c.Check(r.Cigar, check.DeepEquals, expect.Cigar)
   404  		c.Check(r.Cigar.IsValid(r.Seq.Length), check.Equals, true)
   405  		c.Check(r.TempLen, check.Equals, expect.TempLen)
   406  		c.Check(r.Seq, check.DeepEquals, expect.Seq, check.Commentf("got:%q expected:%q", r.Seq.Expand(), expect.Seq.Expand()))
   407  		c.Check(r.Qual, check.DeepEquals, expect.Qual) // No valid qualities here.
   408  		c.Check(r.End(), check.Equals, specExamples.readEnds[i], check.Commentf("unexpected end position for %q at %v, got:%d expected:%d", r.Name, r.Pos, r.End(), specExamples.readEnds[i]))
   409  		c.Check(r.AuxFields, check.DeepEquals, expect.AuxFields)
   410  
   411  		parsedCigar, err := sam.ParseCigar([]byte(specExamples.cigars[i]))
   412  		c.Check(err, check.Equals, nil)
   413  		c.Check(parsedCigar, check.DeepEquals, expect.Cigar)
   414  
   415  		// In all the examples the last base of the read and the last
   416  		// base of the ref are valid, so we can check this.
   417  		expSeq := r.Seq.Expand()
   418  		c.Check(specExamples.ref[r.End()-1], check.Equals, expSeq[len(expSeq)-1])
   419  	}
   420  }
   421  
   422  func (s *S) TestSpecExamplesIterator(c *check.C) {
   423  	br, err := NewReader(bytes.NewReader(specExamples.data), *conc)
   424  	c.Assert(err, check.Equals, nil)
   425  	it, err := NewIterator(br, nil)
   426  	c.Assert(err, check.Equals, nil)
   427  	for i := 0; it.Next(); i++ {
   428  		expect := specExamples.records[i]
   429  		r := it.Record()
   430  		c.Check(r.Name, check.Equals, expect.Name)
   431  		c.Check(r.Pos, check.Equals, expect.Pos)
   432  	}
   433  	c.Assert(it.Error(), check.Equals, nil)
   434  }
   435  
   436  func mustAux(a sam.Aux, err error) sam.Aux {
   437  	if err != nil {
   438  		panic(err)
   439  	}
   440  	return a
   441  }
   442  
   443  // The following data is the BAM file created from the following SAM using:
   444  //
   445  // samtools view -Sb spec-example.sam > spec-example.bam
   446  //
   447  // @HD	VN:1.5	SO:coordinate
   448  // @SQ	SN:ref	LN:45
   449  // @CO	--------------------------------------------------------
   450  // @CO	Coor     12345678901234  5678901234567890123456789012345
   451  // @CO	ref      AGCATGTTAGATAA**GATAGCTGTGCTAGTAGGCAGTCAGCGCCAT
   452  // @CO	--------------------------------------------------------
   453  // @CO	+r001/1        TTAGATAAAGGATA*CTG
   454  // @CO	+r002         aaaAGATAA*GGATA
   455  // @CO	+r003       gcctaAGCTAA
   456  // @CO	+r004                     ATAGCT..............TCAGC
   457  // @CO	-r003                            ttagctTAGGC
   458  // @CO	-r001/2                                        CAGCGGCAT
   459  // @CO	--------------------------------------------------------
   460  // r001	99	ref	7	30	8M2I4M1D3M	=	37	39	TTAGATAAAGGATACTG	*
   461  // r002	0	ref	9	30	3S6M1P1I4M	*	0	0	AAAAGATAAGGATA	*
   462  // r003	0	ref	9	30	5S6M	*	0	0	GCCTAAGCTAA	*	SA:Z:ref,29,-,6H5M,17,0;
   463  // r004	0	ref	16	30	6M14N5M	*	0	0	ATAGCTTCAGC	*
   464  // r003	2064	ref	29	17	6H5M	*	0	0	TAGGC	*	SA:Z:ref,9,+,5S6M,30,1;
   465  // r001	147	ref	37	30	9M	=	7	-39	CAGCGGCAT	*	NM:i:1
   466  var specExamples = struct {
   467  	ref      string
   468  	data     []byte
   469  	header   sam.Header
   470  	records  []*sam.Record
   471  	cigars   []string
   472  	readEnds []int
   473  }{
   474  	ref: "AGCATGTTAGATAAGATAGCTGTGCTAGTAGGCAGTCAGCGCCAT",
   475  	data: []byte{
   476  		0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   477  		0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   478  		0xf7, 0x00, 0xa5, 0x51, 0xcb, 0x0a, 0xc2, 0x30,
   479  		0x10, 0x8c, 0xe2, 0x25, 0xfd, 0x8a, 0x9c, 0x2b,
   480  		0x6a, 0x53, 0x5b, 0x1f, 0x3d, 0x75, 0x8d, 0x10,
   481  		0x0f, 0x5a, 0x91, 0x06, 0xef, 0xa1, 0x56, 0xf1,
   482  		0xa2, 0x50, 0xf2, 0xff, 0xb8, 0x4d, 0x5f, 0x0a,
   483  		0xc5, 0x83, 0x0e, 0x49, 0x76, 0xc9, 0xce, 0x64,
   484  		0x1f, 0xd9, 0xc0, 0x61, 0x90, 0x0f, 0x09, 0x89,
   485  		0x77, 0x5b, 0x7a, 0x4e, 0x22, 0x3e, 0x0d, 0x69,
   486  		0x7a, 0x8c, 0xb2, 0xe7, 0xb3, 0xb8, 0xdc, 0x1f,
   487  		0xda, 0xe4, 0x4e, 0x9c, 0x9e, 0x68, 0x9a, 0x44,
   488  		0x45, 0x7e, 0xa5, 0xfb, 0x24, 0x0a, 0x42, 0x27,
   489  		0x16, 0x47, 0x3a, 0xf9, 0x11, 0x56, 0x2c, 0xf0,
   490  		0x71, 0x56, 0x82, 0xfb, 0xf3, 0x20, 0x5c, 0x2c,
   491  		0x57, 0x6b, 0xaf, 0xf4, 0x18, 0xeb, 0xfc, 0x5e,
   492  		0xcf, 0x8a, 0xb1, 0x0e, 0xab, 0x65, 0x20, 0x05,
   493  		0x28, 0xa9, 0x14, 0x48, 0x50, 0x00, 0xae, 0x5b,
   494  		0x1a, 0x29, 0xf0, 0x06, 0x0f, 0x90, 0xb8, 0x30,
   495  		0x2e, 0x15, 0x6e, 0x21, 0x05, 0x32, 0xff, 0x2f,
   496  		0x7b, 0x5c, 0x78, 0x1e, 0x9f, 0x71, 0x56, 0xa3,
   497  		0xc9, 0x8c, 0x89, 0xd0, 0xb8, 0x98, 0xb9, 0x65,
   498  		0xf9, 0x0d, 0x87, 0x69, 0xad, 0xeb, 0xfa, 0x2c,
   499  		0xab, 0x65, 0xcc, 0xeb, 0xf8, 0x2d, 0xcb, 0x8c,
   500  		0x2e, 0xcb, 0x86, 0x2e, 0x16, 0xb0, 0x3e, 0x54,
   501  		0xdd, 0x4d, 0x3f, 0x60, 0xbb, 0xab, 0x1a, 0x7b,
   502  		0x7b, 0xb3, 0x17, 0xc6, 0xe8, 0x5b, 0x66, 0xec,
   503  		0x54, 0x5a, 0x01, 0x9f, 0xf9, 0xdf, 0x24, 0xef,
   504  		0xb0, 0x63, 0x94, 0x7f, 0x8f, 0x71, 0x40, 0x08,
   505  		0x19, 0xe1, 0xc6, 0x4f, 0x24, 0x13, 0xb4, 0x2f,
   506  		0x02, 0xfe, 0x37, 0xdf, 0x7d, 0x02, 0x00, 0x00,
   507  		0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   508  		0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   509  		0x01, 0x01, 0x0b, 0x66, 0x80, 0x00, 0x36, 0x20,
   510  		0x66, 0x95, 0xf3, 0x14, 0x62, 0x65, 0x48, 0x66,
   511  		0x10, 0x84, 0x8a, 0xa9, 0x00, 0xb1, 0x3a, 0x10,
   512  		0x17, 0x19, 0x18, 0x18, 0x32, 0x34, 0x00, 0x19,
   513  		0x8a, 0x40, 0xec, 0x00, 0xc4, 0x42, 0x40, 0x6c,
   514  		0x00, 0xc4, 0x1d, 0x22, 0x12, 0x82, 0x22, 0x8e,
   515  		0x8d, 0x1a, 0x0e, 0xff, 0xd1, 0x81, 0x1f, 0xd4,
   516  		0x08, 0x0e, 0xb8, 0xb1, 0x0c, 0x0c, 0x7c, 0x40,
   517  		0x0c, 0x93, 0x67, 0x80, 0x18, 0x6b, 0xc4, 0x60,
   518  		0x02, 0x64, 0x24, 0x00, 0xb1, 0x18, 0x10, 0x0b,
   519  		0x42, 0x8d, 0x17, 0x14, 0x74, 0x6c, 0x04, 0x1a,
   520  		0x8b, 0x6a, 0x62, 0x28, 0x9a, 0x89, 0x4c, 0x40,
   521  		0x9a, 0x1b, 0xd3, 0x44, 0x63, 0x86, 0x10, 0xa8,
   522  		0x89, 0x4e, 0x1a, 0x82, 0x4e, 0x8d, 0x02, 0x48,
   523  		0x26, 0x04, 0x3b, 0x46, 0x15, 0xa5, 0xa6, 0xe9,
   524  		0x18, 0x59, 0xea, 0xe8, 0xea, 0x98, 0x79, 0x98,
   525  		0xfa, 0xea, 0x18, 0x9a, 0xeb, 0x18, 0x58, 0x33,
   526  		0x38, 0x41, 0x0d, 0xe6, 0x87, 0x1a, 0xcc, 0x8c,
   527  		0xdd, 0x60, 0x13, 0xb0, 0xa1, 0x8f, 0x81, 0x38,
   528  		0x00, 0x88, 0x25, 0x44, 0x34, 0x9a, 0x44, 0x14,
   529  		0x90, 0x0c, 0xf7, 0x86, 0x9a, 0x22, 0x03, 0x32,
   530  		0x45, 0x10, 0xe4, 0x3c, 0x01, 0x0e, 0x56, 0x6c,
   531  		0xce, 0x4b, 0x85, 0x9a, 0xd0, 0xe8, 0xa2, 0x80,
   532  		0xec, 0x2a, 0x4b, 0x1d, 0x6d, 0x1d, 0xd3, 0x60,
   533  		0x33, 0x5f, 0x1d, 0x63, 0x03, 0x1d, 0x43, 0x6b,
   534  		0x06, 0x6b, 0xa4, 0x28, 0x00, 0x39, 0x8a, 0x91,
   535  		0x61, 0x32, 0x03, 0x27, 0x52, 0x54, 0xdd, 0x04,
   536  		0xea, 0x04, 0x47, 0xcb, 0x04, 0x50, 0xb4, 0x38,
   537  		0xb9, 0x28, 0x36, 0x20, 0x82, 0xde, 0xd7, 0x99,
   538  		0x11, 0x00, 0x9e, 0x55, 0xee, 0x4f, 0xd6, 0x01,
   539  		0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
   540  		0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
   541  		0x02, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x00, 0x00,
   542  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   543  	},
   544  	header: sam.Header{
   545  		Version:    "1.5",
   546  		SortOrder:  sam.Coordinate,
   547  		GroupOrder: sam.GroupUnspecified,
   548  		Comments: []string{
   549  			"--------------------------------------------------------",
   550  			"Coor     12345678901234  5678901234567890123456789012345",
   551  			"ref      AGCATGTTAGATAA**GATAGCTGTGCTAGTAGGCAGTCAGCGCCAT",
   552  			"--------------------------------------------------------",
   553  			"+r001/1        TTAGATAAAGGATA*CTG",
   554  			"+r002         aaaAGATAA*GGATA",
   555  			"+r003       gcctaAGCTAA",
   556  			"+r004                     ATAGCT..............TCAGC",
   557  			"-r003                            ttagctTAGGC",
   558  			"-r001/2                                        CAGCGGCAT",
   559  			"--------------------------------------------------------",
   560  		},
   561  	},
   562  	records: []*sam.Record{
   563  		{
   564  			Name: "r001",
   565  			Pos:  6,
   566  			MapQ: 30,
   567  			Cigar: sam.Cigar{
   568  				sam.NewCigarOp(sam.CigarMatch, 8),
   569  				sam.NewCigarOp(sam.CigarInsertion, 2),
   570  				sam.NewCigarOp(sam.CigarMatch, 4),
   571  				sam.NewCigarOp(sam.CigarDeletion, 1),
   572  				sam.NewCigarOp(sam.CigarMatch, 3),
   573  			},
   574  			Flags:   sam.Paired | sam.ProperPair | sam.MateReverse | sam.Read1,
   575  			MatePos: 36,
   576  			TempLen: 39,
   577  			Seq:     sam.NewSeq([]byte("TTAGATAAAGGATACTG")),
   578  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   579  		},
   580  		{
   581  			Name: "r002",
   582  			Pos:  8,
   583  			MapQ: 30,
   584  			Cigar: sam.Cigar{
   585  				sam.NewCigarOp(sam.CigarSoftClipped, 3),
   586  				sam.NewCigarOp(sam.CigarMatch, 6),
   587  				sam.NewCigarOp(sam.CigarPadded, 1),
   588  				sam.NewCigarOp(sam.CigarInsertion, 1),
   589  				sam.NewCigarOp(sam.CigarMatch, 4),
   590  			},
   591  			MatePos: -1,
   592  			TempLen: 0,
   593  			Seq:     sam.NewSeq([]byte("AAAAGATAAGGATA")),
   594  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   595  		},
   596  		{
   597  			Name: "r003",
   598  			Pos:  8,
   599  			MapQ: 30,
   600  			Cigar: sam.Cigar{
   601  				sam.NewCigarOp(sam.CigarSoftClipped, 5),
   602  				sam.NewCigarOp(sam.CigarMatch, 6),
   603  			},
   604  			MatePos: -1,
   605  			TempLen: 0,
   606  			Seq:     sam.NewSeq([]byte("GCCTAAGCTAA")),
   607  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   608  			AuxFields: []sam.Aux{
   609  				mustAux(sam.NewAux(sam.NewTag("SA"), "ref,29,-,6H5M,17,0;")),
   610  			},
   611  		},
   612  		{
   613  			Name: "r004",
   614  			Pos:  15,
   615  			MapQ: 30,
   616  			Cigar: sam.Cigar{
   617  				sam.NewCigarOp(sam.CigarMatch, 6),
   618  				sam.NewCigarOp(sam.CigarSkipped, 14),
   619  				sam.NewCigarOp(sam.CigarMatch, 5),
   620  			},
   621  			MatePos: -1,
   622  			TempLen: 0,
   623  			Seq:     sam.NewSeq([]byte("ATAGCTTCAGC")),
   624  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   625  		},
   626  		{
   627  			Name: "r003",
   628  			Pos:  28,
   629  			MapQ: 17,
   630  			Cigar: sam.Cigar{
   631  				sam.NewCigarOp(sam.CigarHardClipped, 6),
   632  				sam.NewCigarOp(sam.CigarMatch, 5),
   633  			},
   634  			Flags:   sam.Reverse | sam.Supplementary,
   635  			MatePos: -1,
   636  			TempLen: 0,
   637  			Seq:     sam.NewSeq([]byte("TAGGC")),
   638  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff},
   639  			AuxFields: []sam.Aux{
   640  				mustAux(sam.NewAux(sam.NewTag("SA"), "ref,9,+,5S6M,30,1;")),
   641  			},
   642  		},
   643  		{
   644  			Name: "r001",
   645  			Pos:  36,
   646  			MapQ: 30,
   647  			Cigar: sam.Cigar{
   648  				sam.NewCigarOp(sam.CigarMatch, 9),
   649  			},
   650  			Flags:   sam.Paired | sam.ProperPair | sam.Reverse | sam.Read2,
   651  			MatePos: 6,
   652  			TempLen: -39,
   653  			Seq:     sam.NewSeq([]byte("CAGCGGCAT")),
   654  			Qual:    []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   655  			AuxFields: []sam.Aux{
   656  				mustAux(sam.NewAux(sam.NewTag("NM"), uint(1))),
   657  			},
   658  		},
   659  	},
   660  	cigars: []string{
   661  		"8M2I4M1D3M",
   662  		"3S6M1P1I4M",
   663  		"5S6M",
   664  		"6M14N5M",
   665  		"6H5M",
   666  		"9M",
   667  	},
   668  	// These coordinates are all open (and zero-based) so that
   669  	// a slice of the reference doesn't need any alteration.
   670  	readEnds: []int{
   671  		22,
   672  		18,
   673  		14,
   674  		40,
   675  		33,
   676  		45,
   677  	},
   678  }
   679  
   680  func (s *S) TestIssue3(c *check.C) {
   681  	for _, test := range issue3 {
   682  		br, err := NewReader(bytes.NewReader(test), *conc)
   683  		c.Assert(err, check.Equals, nil, check.Commentf("Failed to open BAM"))
   684  
   685  		for {
   686  			_, err := br.Read()
   687  			if err != nil {
   688  				c.Check(err, check.Equals, io.EOF)
   689  				break
   690  			}
   691  		}
   692  	}
   693  }
   694  
   695  var issue3 = [][]byte{
   696  	// Specific case posted at https://code.google.com/p/biogo/issues/detail?id=3#c6
   697  	// edited to a minimal reproducer.
   698  	[]byte{
   699  		0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   700  		0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   701  		0x61, 0x00, 0x73, 0x72, 0xf4, 0x65, 0x34, 0x62,
   702  		0x60, 0x60, 0x70, 0xf0, 0x70, 0xe1, 0x0c, 0xf3,
   703  		0xb3, 0x32, 0xd4, 0x33, 0xe0, 0x0c, 0xf6, 0xb7,
   704  		0x4a, 0xce, 0xcf, 0x2f, 0x4a, 0xc9, 0xcc, 0x4b,
   705  		0x2c, 0x49, 0xe5, 0x72, 0x08, 0x0e, 0xe4, 0x0c,
   706  		0xf6, 0xb3, 0x8a, 0x2a, 0xb3, 0x8c, 0xf7, 0x73,
   707  		0x34, 0x34, 0xe0, 0xf4, 0xf1, 0xb3, 0x32, 0xb1,
   708  		0x30, 0x30, 0x33, 0xe2, 0x62, 0x04, 0xea, 0xe2,
   709  		0x04, 0x62, 0x98, 0x0c, 0xc3, 0xbe, 0xdd, 0x0c,
   710  		0x0c, 0x00, 0xaa, 0x89, 0xab, 0xc2, 0x4f, 0x00,
   711  		0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
   712  		0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
   713  		0x02, 0x00, 0xa2, 0x00, 0x9b, 0xc5, 0x00, 0x01,
   714  		0xb3, 0xa5, 0x19, 0x18, 0xf8, 0x19, 0x3c, 0x85,
   715  		0x18, 0x19, 0x18, 0x18, 0x25, 0x81, 0xfc, 0xff,
   716  		0x50, 0x00, 0x92, 0x33, 0x34, 0x28, 0x30, 0x30,
   717  		0xcc, 0x4a, 0x4b, 0xce, 0x53, 0x76, 0x76, 0x76,
   718  		0x0f, 0x61, 0x98, 0x00, 0x54, 0x23, 0xd4, 0x01,
   719  		0x05, 0x4a, 0x1d, 0x1d, 0x0d, 0xaa, 0xca, 0xca,
   720  		0xca, 0x8a, 0xaa, 0xea, 0xea, 0xea, 0x1a, 0x9a,
   721  		0x9a, 0x9a, 0x1a, 0x40, 0x52, 0x55, 0x59, 0x51,
   722  		0x45, 0x55, 0x55, 0x45, 0xc9, 0x31, 0x38, 0xf9,
   723  		0x77, 0x84, 0x9f, 0x33, 0x43, 0x84, 0xaf, 0x33,
   724  		0x63, 0x84, 0x3f, 0x90, 0x76, 0x77, 0x66, 0xf0,
   725  		0x03, 0xb2, 0x7d, 0x5d, 0xa2, 0x8c, 0x8c, 0x1d,
   726  		0x0d, 0x19, 0x22, 0x43, 0xa2, 0x42, 0x43, 0x19,
   727  		0xfc, 0x3c, 0x9c, 0x45, 0x9c, 0x9d, 0xa3, 0x92,
   728  		0x33, 0x8a, 0x0c, 0x19, 0x9c, 0x03, 0x3c, 0xf7,
   729  		0x9a, 0x3f, 0x67, 0x8a, 0x08, 0x76, 0xd4, 0xf6,
   730  		0xf0, 0x74, 0x66, 0x00, 0x00, 0xa6, 0xdc, 0x77,
   731  		0x77, 0x9e, 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08,
   732  		0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06,
   733  		0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00, 0x03,
   734  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   735  		0x00,
   736  	},
   737  
   738  	// More general testing: sequence lengths range from 19 to 26 inclusive.
   739  	[]byte{
   740  		0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   741  		0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   742  		0x61, 0x00, 0x73, 0x72, 0xf4, 0x65, 0x34, 0x62,
   743  		0x60, 0x60, 0x70, 0xf0, 0x70, 0xe1, 0x0c, 0xf3,
   744  		0xb3, 0x32, 0xd4, 0x33, 0xe0, 0x0c, 0xf6, 0xb7,
   745  		0x4a, 0xce, 0xcf, 0x2f, 0x4a, 0xc9, 0xcc, 0x4b,
   746  		0x2c, 0x49, 0xe5, 0x72, 0x08, 0x0e, 0xe4, 0x0c,
   747  		0xf6, 0xb3, 0x8a, 0x2a, 0xb3, 0x8c, 0xf7, 0x73,
   748  		0x34, 0x34, 0xe0, 0xf4, 0xf1, 0xb3, 0x32, 0xb1,
   749  		0x30, 0x30, 0x33, 0xe2, 0x62, 0x04, 0xea, 0xe2,
   750  		0x04, 0x62, 0x98, 0x0c, 0xc3, 0xbe, 0xdd, 0x0c,
   751  		0x0c, 0x00, 0xaa, 0x89, 0xab, 0xc2, 0x4f, 0x00,
   752  		0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
   753  		0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
   754  		0x02, 0x00, 0x12, 0x01, 0x9b, 0xc8, 0x00, 0x01,
   755  		0xb3, 0xa5, 0x19, 0x18, 0xf8, 0x19, 0x3c, 0x85,
   756  		0x18, 0x19, 0x18, 0x18, 0x85, 0x81, 0xfc, 0xff,
   757  		0x50, 0x00, 0x92, 0x33, 0x34, 0x28, 0x30, 0x30,
   758  		0xcc, 0x4a, 0x4b, 0xce, 0x53, 0x76, 0x76, 0x76,
   759  		0x0f, 0x61, 0x30, 0x00, 0xaa, 0x11, 0xea, 0x80,
   760  		0x02, 0x05, 0x55, 0x65, 0x65, 0x65, 0x45, 0x55,
   761  		0x75, 0x75, 0x75, 0x0d, 0x4d, 0x4d, 0x4d, 0x0d,
   762  		0x20, 0xa9, 0xaa, 0xec, 0x18, 0x9c, 0xfc, 0x3b,
   763  		0xc2, 0xcf, 0x99, 0x21, 0xc2, 0xd7, 0x99, 0x31,
   764  		0xc2, 0x1f, 0x48, 0xbb, 0x3b, 0x33, 0xf8, 0x01,
   765  		0xd9, 0xbe, 0x2e, 0x51, 0x46, 0xc6, 0x8e, 0x86,
   766  		0x0c, 0x91, 0x21, 0x51, 0xa1, 0xa1, 0x0c, 0x7e,
   767  		0x1e, 0xce, 0x22, 0xce, 0xce, 0x51, 0xc9, 0x19,
   768  		0x45, 0x86, 0x0c, 0xce, 0x01, 0x9e, 0x7b, 0xcd,
   769  		0x9f, 0x33, 0x45, 0x04, 0x3b, 0x6a, 0x7b, 0x78,
   770  		0x3a, 0x33, 0x4c, 0xc2, 0xe2, 0x28, 0x11, 0xfc,
   771  		0x8e, 0x72, 0x40, 0x76, 0x94, 0x12, 0x16, 0x47,
   772  		0x29, 0x52, 0xec, 0xaa, 0x29, 0x58, 0x5c, 0x25,
   773  		0x8a, 0xdf, 0x55, 0x01, 0x28, 0xae, 0x6a, 0xc0,
   774  		0xe6, 0x2c, 0x15, 0x8a, 0xdd, 0x35, 0x15, 0x8b,
   775  		0xbb, 0xc4, 0xf0, 0xbb, 0x2b, 0x01, 0xc5, 0x5d,
   776  		0x1d, 0x58, 0xdd, 0xa5, 0x4a, 0xb1, 0xc3, 0xa6,
   777  		0x63, 0x71, 0x98, 0x38, 0x7e, 0x87, 0x15, 0xa0,
   778  		0x3a, 0x0c, 0x7b, 0x88, 0xa9, 0x52, 0xee, 0xb4,
   779  		0x19, 0x58, 0x9c, 0x26, 0x81, 0xdf, 0x69, 0x0d,
   780  		0xa8, 0x4e, 0xc3, 0x11, 0x68, 0xaa, 0x94, 0xc7,
   781  		0xe7, 0x2c, 0x2c, 0x6e, 0x93, 0xc4, 0xef, 0xb6,
   782  		0x09, 0x68, 0x6e, 0xc3, 0x15, 0x6e, 0x2a, 0x4a,
   783  		0x14, 0xbb, 0x6e, 0x36, 0x16, 0xd7, 0x49, 0xe1,
   784  		0x77, 0xdd, 0x02, 0x34, 0xd7, 0xe1, 0x0c, 0x3a,
   785  		0x25, 0xca, 0x9d, 0x07, 0x00, 0x31, 0x91, 0x24,
   786  		0x5a, 0xd0, 0x04, 0x00, 0x00, 0x1f, 0x8b, 0x08,
   787  		0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06,
   788  		0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00, 0x03,
   789  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   790  		0x00,
   791  	},
   792  }
   793  
   794  func (s *S) TestIssue11(c *check.C) {
   795  	for _, test := range issue11 {
   796  		br, err := NewReader(bytes.NewReader(test.input), *conc)
   797  		c.Check(err, check.Equals, nil)
   798  		c.Check(br.Header().GroupOrder, check.Equals, test.expect)
   799  	}
   800  }
   801  
   802  var issue11 = []struct {
   803  	input  []byte
   804  	expect sam.GroupOrder
   805  }{
   806  	{
   807  		// 1000 genomes file hand edited to reduce number of Refs and reads;
   808  		// no specified group ordering.
   809  		input: []byte{
   810  			0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   811  			0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   812  			0xec, 0x01, 0xad, 0x92, 0xcd, 0x8e, 0xda, 0x30,
   813  			0x10, 0xc7, 0xb3, 0xdd, 0x93, 0x79, 0x8a, 0x1c,
   814  			0x38, 0xb4, 0x07, 0x1c, 0xe7, 0xc3, 0x81, 0x58,
   815  			0xaa, 0xc4, 0x97, 0x04, 0x48, 0x21, 0x9b, 0x12,
   816  			0xd1, 0x6a, 0x4f, 0x91, 0x93, 0xd8, 0xc1, 0x5a,
   817  			0xe3, 0x00, 0x0e, 0xd0, 0xf6, 0x0d, 0xfa, 0xc4,
   818  			0xbd, 0x55, 0x35, 0xd1, 0xb6, 0x5d, 0xb5, 0x3d,
   819  			0xee, 0xc1, 0x23, 0xfb, 0x3f, 0x33, 0xbf, 0x19,
   820  			0xdb, 0x33, 0x9d, 0xac, 0xef, 0xb2, 0x7b, 0xcb,
   821  			0x1a, 0x2f, 0xe7, 0xe0, 0x63, 0x42, 0x5c, 0x88,
   822  			0x40, 0xf6, 0x40, 0xca, 0xa6, 0x39, 0x55, 0x42,
   823  			0xd1, 0x96, 0xf5, 0xc6, 0xd9, 0x07, 0x90, 0x25,
   824  			0xe4, 0x11, 0xc4, 0x09, 0xc1, 0x91, 0x3f, 0xf4,
   825  			0x71, 0x18, 0x82, 0x35, 0x26, 0x2e, 0xa7, 0x7e,
   826  			0x30, 0x0c, 0x86, 0x18, 0x51, 0x8e, 0xa2, 0x60,
   827  			0x54, 0x54, 0x3c, 0x1a, 0x56, 0x98, 0x22, 0xc6,
   828  			0xb0, 0xc7, 0xb0, 0x0b, 0xb6, 0x1b, 0xc2, 0xdb,
   829  			0x03, 0x71, 0x1c, 0x63, 0xa1, 0x8b, 0x10, 0xaa,
   830  			0x99, 0x6a, 0xf6, 0x4c, 0x43, 0x56, 0x08, 0x48,
   831  			0x4b, 0x78, 0x7e, 0x72, 0x2e, 0x8d, 0x74, 0x6f,
   832  			0x6e, 0xa7, 0x65, 0xe5, 0x4e, 0x89, 0x92, 0x4a,
   833  			0xe7, 0xc4, 0x38, 0x3b, 0x31, 0x55, 0x32, 0xe7,
   834  			0xb0, 0xa3, 0x9a, 0x79, 0xf9, 0x6f, 0x21, 0xa7,
   835  			0x5a, 0xb3, 0x7d, 0x21, 0xbf, 0xe4, 0x9a, 0x1d,
   836  			0xcf, 0x5d, 0xc8, 0x4e, 0xfb, 0xa6, 0x24, 0xe4,
   837  			0x14, 0xd6, 0x5f, 0xc1, 0x24, 0x23, 0xc9, 0x6c,
   838  			0xba, 0xf2, 0x87, 0x20, 0x4b, 0xc9, 0xf2, 0xbc,
   839  			0xa7, 0xaa, 0x37, 0xde, 0x2c, 0xc0, 0x6a, 0x4e,
   840  			0xb2, 0xcd, 0x06, 0x85, 0x5e, 0xe8, 0x07, 0x20,
   841  			0x9e, 0x12, 0x6f, 0x14, 0xe0, 0x11, 0x0e, 0x47,
   842  			0xd8, 0x5c, 0x74, 0x4d, 0x96, 0x0b, 0xd3, 0x58,
   843  			0x14, 0x82, 0x74, 0x45, 0x3c, 0x14, 0x82, 0x59,
   844  			0x42, 0x3e, 0x6d, 0x17, 0xd9, 0x0c, 0xa4, 0x31,
   845  			0x59, 0xc5, 0xf1, 0x76, 0xbd, 0x4a, 0x26, 0x60,
   846  			0x9e, 0x19, 0x42, 0x8a, 0x90, 0xeb, 0x45, 0xc1,
   847  			0xdf, 0x48, 0xfc, 0xea, 0xc8, 0xc0, 0x7d, 0x0d,
   848  			0x64, 0xda, 0x21, 0x8b, 0x2b, 0xcd, 0x85, 0xaa,
   849  			0xd8, 0x67, 0x90, 0x26, 0xb7, 0xc3, 0xed, 0x87,
   850  			0x11, 0xc4, 0x30, 0x1a, 0x9c, 0x5c, 0x83, 0x89,
   851  			0x6f, 0x9a, 0xdd, 0x05, 0xd8, 0x03, 0x6a, 0x17,
   852  			0xd7, 0x56, 0x5f, 0xed, 0xfe, 0x9f, 0x07, 0xe7,
   853  			0x54, 0xb7, 0xf4, 0x25, 0x8b, 0x4a, 0xd5, 0x89,
   854  			0xc7, 0x5f, 0xbc, 0x34, 0x7d, 0x51, 0xe3, 0x7f,
   855  			0x70, 0x93, 0x61, 0x0f, 0x8e, 0xb6, 0x8b, 0xed,
   856  			0x01, 0xb7, 0xfb, 0x9a, 0x8a, 0x9c, 0x0b, 0xc9,
   857  			0xfe, 0x29, 0x62, 0xf7, 0x3b, 0x6c, 0xe7, 0xec,
   858  			0x8d, 0x67, 0x0f, 0xa0, 0xff, 0xa4, 0x9a, 0xab,
   859  			0xea, 0xc0, 0x52, 0x77, 0xf2, 0x5b, 0xfd, 0xce,
   860  			0x7e, 0x6f, 0xbf, 0xc6, 0x44, 0xed, 0xe9, 0xe1,
   861  			0x20, 0x54, 0x6d, 0x26, 0x4b, 0x37, 0xe7, 0x53,
   862  			0xc9, 0xb4, 0x33, 0x89, 0x63, 0x78, 0xad, 0x35,
   863  			0x7c, 0x2e, 0xb7, 0x17, 0xd2, 0xd8, 0x8a, 0x5d,
   864  			0x84, 0x62, 0xf9, 0xae, 0x76, 0xa3, 0x5c, 0x32,
   865  			0xde, 0x4e, 0xa4, 0xa8, 0x15, 0xab, 0xf2, 0xb2,
   866  			0x91, 0x92, 0x1e, 0xb4, 0xd9, 0x55, 0xcd, 0xb9,
   867  			0x90, 0x26, 0x42, 0xb4, 0xcf, 0x99, 0x50, 0x8b,
   868  			0xd6, 0xb4, 0x73, 0x29, 0xb9, 0x19, 0xc8, 0xde,
   869  			0x9d, 0x65, 0x59, 0x6f, 0xcc, 0x7a, 0xb4, 0x7e,
   870  			0x7c, 0xff, 0x76, 0xff, 0x13, 0x01, 0xfd, 0x62,
   871  			0x77, 0x69, 0x03, 0x00, 0x00, 0x1f, 0x8b, 0x08,
   872  			0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06,
   873  			0x00, 0x42, 0x43, 0x02, 0x00, 0xcf, 0x00, 0x4d,
   874  			0xce, 0x31, 0x6a, 0xc3, 0x30, 0x18, 0x05, 0x60,
   875  			0x41, 0x0f, 0x50, 0xd2, 0x66, 0x30, 0x74, 0x88,
   876  			0xab, 0x18, 0xeb, 0x59, 0xb2, 0xa5, 0xff, 0xb7,
   877  			0xa9, 0x93, 0x8c, 0x32, 0x82, 0x6a, 0x76, 0xb6,
   878  			0xce, 0x3d, 0x40, 0x2e, 0x90, 0x41, 0xc1, 0x83,
   879  			0x73, 0xc1, 0xdc, 0xa4, 0x74, 0xad, 0x4b, 0xa0,
   880  			0xf4, 0x5b, 0xde, 0xe3, 0x4d, 0xef, 0x26, 0xee,
   881  			0xbe, 0xbe, 0xaf, 0x0f, 0xcf, 0xe2, 0x94, 0x0b,
   882  			0x71, 0x16, 0x9f, 0xff, 0xb6, 0xdf, 0x3c, 0x8e,
   883  			0x23, 0xf5, 0x6d, 0xdf, 0xbd, 0x59, 0x3e, 0xf4,
   884  			0xdd, 0x6e, 0xdf, 0xb6, 0x62, 0xb8, 0xc8, 0xe8,
   885  			0x63, 0x98, 0x57, 0x29, 0x44, 0x9f, 0xbc, 0x9c,
   886  			0xa6, 0x4c, 0x66, 0xc5, 0x94, 0x45, 0xa4, 0x39,
   887  			0xad, 0x83, 0x7f, 0x8a, 0x31, 0x0c, 0x4b, 0x0d,
   888  			0x98, 0xb3, 0x20, 0xe1, 0xd7, 0xe9, 0x55, 0xe6,
   889  			0x79, 0xfe, 0x52, 0xa0, 0xd2, 0xa5, 0xde, 0x42,
   890  			0xab, 0x2d, 0x60, 0xea, 0x1a, 0xc6, 0x28, 0x65,
   891  			0xa1, 0x01, 0xab, 0x6c, 0xa9, 0x50, 0x35, 0x0a,
   892  			0x1b, 0xc7, 0xda, 0xb0, 0x61, 0xaa, 0x1d, 0xa1,
   893  			0xd4, 0xa6, 0x65, 0x36, 0x64, 0xa0, 0x1c, 0x3b,
   894  			0x66, 0x22, 0x76, 0x8e, 0xc8, 0x71, 0x45, 0x0b,
   895  			0x0b, 0xba, 0xb3, 0x4d, 0xa3, 0xf1, 0x38, 0xbe,
   896  			0x7f, 0xfc, 0x7d, 0x15, 0x3f, 0xf2, 0x15, 0x80,
   897  			0x8f, 0xda, 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08,
   898  			0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06,
   899  			0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00, 0x03,
   900  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   901  			0x00,
   902  		},
   903  		expect: sam.GroupUnspecified,
   904  	},
   905  	{
   906  		input: []byte{
   907  			0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
   908  			0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
   909  			0xf3, 0x01, 0xad, 0x92, 0xcd, 0x8e, 0xda, 0x30,
   910  			0x10, 0xc7, 0xb3, 0xdd, 0x93, 0x79, 0x8a, 0x1c,
   911  			0x38, 0xb4, 0x07, 0x1c, 0xe7, 0xc3, 0x81, 0x58,
   912  			0xaa, 0xc4, 0x97, 0x04, 0x48, 0x21, 0xa4, 0x44,
   913  			0xb4, 0x5a, 0xf5, 0x10, 0x39, 0x89, 0x13, 0xac,
   914  			0x35, 0x0e, 0xe0, 0x00, 0xdb, 0xbe, 0xc1, 0x3e,
   915  			0xf1, 0xde, 0xaa, 0x9a, 0x68, 0xdb, 0xae, 0xda,
   916  			0x1e, 0x39, 0x78, 0x64, 0xff, 0x67, 0xe6, 0x37,
   917  			0x63, 0x7b, 0xc6, 0xa3, 0xe5, 0xdd, 0xd7, 0x7b,
   918  			0xc3, 0x18, 0xce, 0xa7, 0xe0, 0x73, 0x44, 0x6c,
   919  			0x88, 0x40, 0xb2, 0x22, 0x79, 0x5d, 0x1f, 0x0b,
   920  			0x2e, 0x69, 0xc3, 0xc0, 0x6c, 0x45, 0x64, 0x2d,
   921  			0x59, 0x67, 0x98, 0x7c, 0x02, 0x49, 0x44, 0x1e,
   922  			0x40, 0x18, 0x11, 0x1c, 0xb8, 0x7d, 0x17, 0xfb,
   923  			0x3e, 0x58, 0x62, 0x62, 0x97, 0xd4, 0xf5, 0xfa,
   924  			0x5e, 0x1f, 0x23, 0x5a, 0xa2, 0xc0, 0x1b, 0x64,
   925  			0x45, 0x19, 0xf4, 0x0b, 0x4c, 0x11, 0x63, 0xd8,
   926  			0x61, 0xd8, 0x06, 0x9b, 0x35, 0x29, 0x9b, 0x3d,
   927  			0xb1, 0x2c, 0x6d, 0xa1, 0x8d, 0x10, 0xaa, 0x98,
   928  			0xac, 0x77, 0x4c, 0x41, 0x96, 0x71, 0x48, 0x73,
   929  			0x78, 0x7a, 0xb4, 0xce, 0xb5, 0xb0, 0xaf, 0x6e,
   930  			0xab, 0x61, 0xf9, 0x56, 0xf2, 0x9c, 0x0a, 0xeb,
   931  			0xc8, 0x4a, 0x76, 0x64, 0x32, 0x67, 0xd6, 0x7e,
   932  			0x4b, 0x15, 0x73, 0xd2, 0xdf, 0x42, 0x4a, 0x95,
   933  			0x62, 0xbb, 0x4c, 0x7c, 0x4b, 0x15, 0x3b, 0x9c,
   934  			0xda, 0x90, 0xad, 0x72, 0x75, 0x49, 0x58, 0x52,
   935  			0x58, 0x7d, 0x07, 0xa3, 0x84, 0x44, 0x93, 0xf1,
   936  			0xc2, 0xed, 0x83, 0x24, 0x26, 0xf3, 0xd3, 0x8e,
   937  			0xca, 0xce, 0x70, 0x3d, 0x03, 0x8b, 0x29, 0x49,
   938  			0xd6, 0x6b, 0xe4, 0x3b, 0xbe, 0xeb, 0x81, 0x70,
   939  			0x4c, 0x9c, 0x81, 0x87, 0x07, 0xd8, 0x1f, 0x60,
   940  			0x7d, 0xe1, 0x25, 0x99, 0xcf, 0x74, 0x63, 0x81,
   941  			0x0f, 0xe2, 0x05, 0x71, 0x90, 0x0f, 0x26, 0x11,
   942  			0xf9, 0xb2, 0x99, 0x25, 0x13, 0x10, 0x87, 0x64,
   943  			0x11, 0x86, 0x9b, 0xe5, 0x22, 0x1a, 0x81, 0x69,
   944  			0xa2, 0x09, 0x31, 0x42, 0xb6, 0x13, 0x78, 0x7f,
   945  			0x23, 0xf1, 0xcd, 0x91, 0x9e, 0x7d, 0x0b, 0x64,
   946  			0xdc, 0x22, 0xb3, 0x0b, 0x4d, 0xb9, 0x2c, 0xd8,
   947  			0x13, 0x88, 0xa3, 0xeb, 0xe1, 0xfa, 0xd3, 0x08,
   948  			0x62, 0x18, 0xf4, 0x8e, 0xb6, 0xc6, 0x84, 0x57,
   949  			0xcd, 0x6c, 0x03, 0xcc, 0x1e, 0x35, 0xb3, 0x4b,
   950  			0xa3, 0x2e, 0x66, 0xf7, 0xcf, 0x83, 0x97, 0x54,
   951  			0x35, 0xf4, 0x2d, 0x8b, 0x0a, 0xd9, 0x8a, 0x87,
   952  			0x5f, 0xbc, 0x38, 0x7e, 0x53, 0xe3, 0x7f, 0x70,
   953  			0x9d, 0x61, 0xf6, 0x0e, 0xa6, 0x8d, 0xcd, 0x5e,
   954  			0x69, 0x76, 0x15, 0xe5, 0x69, 0xc9, 0x05, 0xfb,
   955  			0xa7, 0x88, 0xd9, 0x6d, 0xb1, 0xad, 0xb3, 0x33,
   956  			0x9c, 0xac, 0x40, 0xf7, 0x51, 0xd6, 0x17, 0xd9,
   957  			0x82, 0x85, 0x6a, 0xe5, 0xf7, 0xea, 0x83, 0xf9,
   958  			0xd1, 0xbc, 0xc5, 0x44, 0xed, 0xe8, 0x7e, 0xcf,
   959  			0x65, 0xa5, 0x27, 0x4b, 0xd5, 0xa7, 0x63, 0xce,
   960  			0x94, 0x35, 0x0a, 0x43, 0x78, 0xa9, 0x14, 0x7c,
   961  			0x2d, 0xb7, 0xe3, 0x42, 0xdb, 0x82, 0x9d, 0xb9,
   962  			0x64, 0xe9, 0xb6, 0xb2, 0x83, 0x54, 0xb0, 0xb2,
   963  			0x19, 0x09, 0x5e, 0x49, 0x56, 0xa4, 0x79, 0x2d,
   964  			0x04, 0xdd, 0x2b, 0xbd, 0x2b, 0xea, 0x53, 0x26,
   965  			0x74, 0x04, 0x6f, 0x5e, 0x33, 0xa1, 0xe2, 0x8d,
   966  			0x6e, 0xe7, 0x9c, 0x97, 0x7a, 0x20, 0x3b, 0x77,
   967  			0x86, 0x61, 0xbc, 0xd3, 0xeb, 0xc1, 0xf8, 0xf1,
   968  			0xf2, 0x7c, 0xff, 0x13, 0x5a, 0x38, 0x56, 0x0a,
   969  			0x71, 0x03, 0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04,
   970  			0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x00,
   971  			0x42, 0x43, 0x02, 0x00, 0xcf, 0x00, 0x4d, 0xce,
   972  			0x31, 0x6a, 0xc3, 0x30, 0x18, 0x05, 0x60, 0x41,
   973  			0x0f, 0x50, 0xd2, 0x66, 0x30, 0x74, 0x88, 0xab,
   974  			0x18, 0xeb, 0x59, 0xb2, 0xa5, 0xff, 0xb7, 0xa9,
   975  			0x93, 0x8c, 0x32, 0x82, 0x6a, 0x76, 0xb6, 0xce,
   976  			0x3d, 0x40, 0x2e, 0x90, 0x41, 0xc1, 0x83, 0x73,
   977  			0xc1, 0xdc, 0xa4, 0x74, 0xad, 0x4b, 0xa0, 0xf4,
   978  			0x5b, 0xde, 0xe3, 0x4d, 0xef, 0x26, 0xee, 0xbe,
   979  			0xbe, 0xaf, 0x0f, 0xcf, 0xe2, 0x94, 0x0b, 0x71,
   980  			0x16, 0x9f, 0xff, 0xb6, 0xdf, 0x3c, 0x8e, 0x23,
   981  			0xf5, 0x6d, 0xdf, 0xbd, 0x59, 0x3e, 0xf4, 0xdd,
   982  			0x6e, 0xdf, 0xb6, 0x62, 0xb8, 0xc8, 0xe8, 0x63,
   983  			0x98, 0x57, 0x29, 0x44, 0x9f, 0xbc, 0x9c, 0xa6,
   984  			0x4c, 0x66, 0xc5, 0x94, 0x45, 0xa4, 0x39, 0xad,
   985  			0x83, 0x7f, 0x8a, 0x31, 0x0c, 0x4b, 0x0d, 0x98,
   986  			0xb3, 0x20, 0xe1, 0xd7, 0xe9, 0x55, 0xe6, 0x79,
   987  			0xfe, 0x52, 0xa0, 0xd2, 0xa5, 0xde, 0x42, 0xab,
   988  			0x2d, 0x60, 0xea, 0x1a, 0xc6, 0x28, 0x65, 0xa1,
   989  			0x01, 0xab, 0x6c, 0xa9, 0x50, 0x35, 0x0a, 0x1b,
   990  			0xc7, 0xda, 0xb0, 0x61, 0xaa, 0x1d, 0xa1, 0xd4,
   991  			0xa6, 0x65, 0x36, 0x64, 0xa0, 0x1c, 0x3b, 0x66,
   992  			0x22, 0x76, 0x8e, 0xc8, 0x71, 0x45, 0x0b, 0x0b,
   993  			0xba, 0xb3, 0x4d, 0xa3, 0xf1, 0x38, 0xbe, 0x7f,
   994  			0xfc, 0x7d, 0x15, 0x3f, 0xf2, 0x15, 0x80, 0x8f,
   995  			0xda, 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04,
   996  			0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x00,
   997  			0x42, 0x43, 0x02, 0x00, 0x1b, 0x00, 0x03, 0x00,
   998  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   999  		},
  1000  		expect: sam.GroupNone,
  1001  	},
  1002  	{
  1003  		input: []byte{
  1004  			0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
  1005  			0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
  1006  			0xf5, 0x01, 0xad, 0x92, 0xcb, 0x8e, 0xda, 0x30,
  1007  			0x14, 0x86, 0x33, 0x9d, 0x95, 0x79, 0x8a, 0x2c,
  1008  			0x58, 0xb4, 0x0b, 0x1c, 0xe7, 0xe2, 0x40, 0x2c,
  1009  			0x55, 0xe2, 0x26, 0x01, 0x52, 0x08, 0x29, 0x11,
  1010  			0xad, 0x46, 0xaa, 0x14, 0x39, 0x89, 0x13, 0xac,
  1011  			0x31, 0x0e, 0x13, 0x07, 0xe8, 0xf4, 0x0d, 0xfa,
  1012  			0xc4, 0xdd, 0x55, 0x35, 0xd1, 0xb4, 0x1d, 0xb5,
  1013  			0x5d, 0xb2, 0xf0, 0x91, 0x7d, 0x2e, 0xdf, 0x7f,
  1014  			0x6c, 0x9f, 0xe9, 0x64, 0x7d, 0xf7, 0xf9, 0xde,
  1015  			0x30, 0xc6, 0xcb, 0x39, 0xf8, 0x18, 0x11, 0x1b,
  1016  			0x22, 0x90, 0x6c, 0x48, 0x5e, 0xd7, 0x4d, 0xc1,
  1017  			0x25, 0x6d, 0x19, 0x58, 0x6c, 0xc8, 0xd3, 0x89,
  1018  			0x35, 0xcf, 0xbd, 0x71, 0xf2, 0x01, 0x24, 0x11,
  1019  			0x79, 0x00, 0x61, 0x44, 0x70, 0xe0, 0x0e, 0x5d,
  1020  			0xec, 0xfb, 0x60, 0x8d, 0x89, 0x5d, 0x52, 0xd7,
  1021  			0x1b, 0x7a, 0x43, 0x8c, 0x68, 0x89, 0x02, 0x6f,
  1022  			0x94, 0x15, 0x65, 0x30, 0x2c, 0x30, 0x45, 0x8c,
  1023  			0x61, 0x87, 0x61, 0x1b, 0xec, 0xb6, 0xa4, 0x6c,
  1024  			0x8f, 0xc4, 0xb2, 0xb4, 0x85, 0x36, 0x42, 0xa8,
  1025  			0x62, 0xb2, 0x3e, 0x30, 0x05, 0x59, 0xc6, 0x21,
  1026  			0xcd, 0xe1, 0xe9, 0xd1, 0x3a, 0xd7, 0xc2, 0xbe,
  1027  			0x86, 0xad, 0x96, 0xe5, 0x7b, 0xc9, 0x73, 0x2a,
  1028  			0xac, 0x86, 0x95, 0xac, 0x61, 0x32, 0x67, 0xd6,
  1029  			0x71, 0x4f, 0x15, 0x73, 0xd2, 0xdf, 0x8e, 0x94,
  1030  			0x2a, 0xc5, 0x0e, 0x99, 0x78, 0x4e, 0x15, 0xd3,
  1031  			0xad, 0x5d, 0x53, 0xf6, 0xca, 0xd5, 0x92, 0xb0,
  1032  			0xa4, 0xb0, 0xfa, 0x0a, 0x26, 0x09, 0x89, 0x66,
  1033  			0xd3, 0x95, 0x3b, 0x04, 0x49, 0x4c, 0x96, 0xa7,
  1034  			0x03, 0x95, 0xbd, 0xf1, 0x76, 0x01, 0x56, 0x73,
  1035  			0x92, 0x6c, 0xb7, 0xc8, 0x77, 0x7c, 0xd7, 0x03,
  1036  			0xe1, 0x94, 0x38, 0x23, 0x0f, 0x8f, 0xb0, 0x3f,
  1037  			0xc2, 0xfa, 0xc6, 0x6b, 0xb2, 0x5c, 0xe8, 0xc6,
  1038  			0x02, 0x1f, 0xc4, 0x2b, 0xe2, 0x20, 0x1f, 0xcc,
  1039  			0x22, 0xf2, 0x69, 0xb7, 0x48, 0x66, 0x20, 0x0e,
  1040  			0xc9, 0x2a, 0x0c, 0x77, 0xeb, 0x55, 0x34, 0x01,
  1041  			0xf3, 0x44, 0x13, 0x62, 0x84, 0x6c, 0x27, 0xf0,
  1042  			0xfe, 0x46, 0xe2, 0x9b, 0x23, 0x3d, 0xfb, 0x16,
  1043  			0xc8, 0xb8, 0x43, 0x66, 0x17, 0x9a, 0x72, 0x59,
  1044  			0xb0, 0x2f, 0x20, 0x8e, 0xae, 0x87, 0xeb, 0x57,
  1045  			0x23, 0x88, 0x61, 0x30, 0x68, 0x6c, 0x8d, 0x09,
  1046  			0xaf, 0x3e, 0xb3, 0x4b, 0x30, 0x07, 0xd4, 0xcc,
  1047  			0x2e, 0xad, 0xba, 0x98, 0xfd, 0x3f, 0x0f, 0x5e,
  1048  			0x52, 0xd5, 0xd2, 0xd7, 0x2c, 0x2a, 0x64, 0xe7,
  1049  			0x7c, 0xfa, 0xc5, 0x8b, 0xe3, 0x57, 0x1a, 0xff,
  1050  			0x83, 0xeb, 0x0a, 0x73, 0xf0, 0x64, 0xda, 0xd8,
  1051  			0x1c, 0x94, 0x66, 0x5f, 0x51, 0x9e, 0x96, 0x5c,
  1052  			0xb0, 0x7f, 0x44, 0xcc, 0x7e, 0x87, 0xed, 0x82,
  1053  			0xbd, 0xf1, 0x6c, 0x03, 0xfa, 0x8f, 0xb2, 0xbe,
  1054  			0xc8, 0x0e, 0x2c, 0x54, 0xe7, 0x7e, 0xab, 0xde,
  1055  			0x99, 0xef, 0xcd, 0x5b, 0x4c, 0xd4, 0x81, 0x1e,
  1056  			0x8f, 0x5c, 0x56, 0x7a, 0xb2, 0x54, 0x7d, 0x6a,
  1057  			0x72, 0xa6, 0xac, 0x49, 0x18, 0xc2, 0x4b, 0xa5,
  1058  			0xe0, 0x8b, 0xdc, 0x81, 0x0b, 0x6d, 0x0b, 0x76,
  1059  			0xe6, 0x92, 0xa5, 0xfb, 0xca, 0x0e, 0x52, 0xc1,
  1060  			0xca, 0x76, 0x22, 0x78, 0x25, 0x59, 0x91, 0xe6,
  1061  			0xb5, 0x10, 0xf4, 0xa8, 0xf4, 0xae, 0xa8, 0x4f,
  1062  			0x99, 0xd0, 0x19, 0xbc, 0x7d, 0xa9, 0x84, 0x8a,
  1063  			0xb7, 0xba, 0x9d, 0x73, 0x5e, 0xea, 0x81, 0xec,
  1064  			0xdd, 0x19, 0x86, 0xf1, 0x46, 0xaf, 0x07, 0xe3,
  1065  			0xc7, 0xf7, 0x6f, 0xf7, 0x3f, 0x01, 0x63, 0x09,
  1066  			0x85, 0xc2, 0x72, 0x03, 0x00, 0x00, 0x1f, 0x8b,
  1067  			0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1068  			0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0xcf, 0x00,
  1069  			0x4d, 0xce, 0x31, 0x6a, 0xc3, 0x30, 0x18, 0x05,
  1070  			0x60, 0x41, 0x0f, 0x50, 0xd2, 0x66, 0x30, 0x74,
  1071  			0x88, 0xab, 0x18, 0xeb, 0x59, 0xb2, 0xa5, 0xff,
  1072  			0xb7, 0xa9, 0x93, 0x8c, 0x32, 0x82, 0x6a, 0x76,
  1073  			0xb6, 0xce, 0x3d, 0x40, 0x2e, 0x90, 0x41, 0xc1,
  1074  			0x83, 0x73, 0xc1, 0xdc, 0xa4, 0x74, 0xad, 0x4b,
  1075  			0xa0, 0xf4, 0x5b, 0xde, 0xe3, 0x4d, 0xef, 0x26,
  1076  			0xee, 0xbe, 0xbe, 0xaf, 0x0f, 0xcf, 0xe2, 0x94,
  1077  			0x0b, 0x71, 0x16, 0x9f, 0xff, 0xb6, 0xdf, 0x3c,
  1078  			0x8e, 0x23, 0xf5, 0x6d, 0xdf, 0xbd, 0x59, 0x3e,
  1079  			0xf4, 0xdd, 0x6e, 0xdf, 0xb6, 0x62, 0xb8, 0xc8,
  1080  			0xe8, 0x63, 0x98, 0x57, 0x29, 0x44, 0x9f, 0xbc,
  1081  			0x9c, 0xa6, 0x4c, 0x66, 0xc5, 0x94, 0x45, 0xa4,
  1082  			0x39, 0xad, 0x83, 0x7f, 0x8a, 0x31, 0x0c, 0x4b,
  1083  			0x0d, 0x98, 0xb3, 0x20, 0xe1, 0xd7, 0xe9, 0x55,
  1084  			0xe6, 0x79, 0xfe, 0x52, 0xa0, 0xd2, 0xa5, 0xde,
  1085  			0x42, 0xab, 0x2d, 0x60, 0xea, 0x1a, 0xc6, 0x28,
  1086  			0x65, 0xa1, 0x01, 0xab, 0x6c, 0xa9, 0x50, 0x35,
  1087  			0x0a, 0x1b, 0xc7, 0xda, 0xb0, 0x61, 0xaa, 0x1d,
  1088  			0xa1, 0xd4, 0xa6, 0x65, 0x36, 0x64, 0xa0, 0x1c,
  1089  			0x3b, 0x66, 0x22, 0x76, 0x8e, 0xc8, 0x71, 0x45,
  1090  			0x0b, 0x0b, 0xba, 0xb3, 0x4d, 0xa3, 0xf1, 0x38,
  1091  			0xbe, 0x7f, 0xfc, 0x7d, 0x15, 0x3f, 0xf2, 0x15,
  1092  			0x80, 0x8f, 0xda, 0x00, 0x00, 0x00, 0x1f, 0x8b,
  1093  			0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1094  			0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00,
  1095  			0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1096  			0x00, 0x00,
  1097  		},
  1098  		expect: sam.GroupQuery,
  1099  	},
  1100  	{
  1101  		input: []byte{
  1102  			0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
  1103  			0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
  1104  			0xf1, 0x01, 0xad, 0x92, 0xcb, 0x8e, 0xda, 0x30,
  1105  			0x14, 0x86, 0x33, 0x9d, 0x95, 0x79, 0x8a, 0x2c,
  1106  			0x58, 0xb4, 0x0b, 0x1c, 0xe7, 0xe2, 0x40, 0x2c,
  1107  			0x55, 0xe2, 0x26, 0x01, 0x52, 0x08, 0x29, 0x11,
  1108  			0xad, 0x66, 0x95, 0x3a, 0x89, 0x13, 0xac, 0x31,
  1109  			0x0e, 0xe0, 0x00, 0x6d, 0xdf, 0xa0, 0x4f, 0x3c,
  1110  			0xbb, 0x51, 0x4d, 0x34, 0x9d, 0x8e, 0xda, 0x2e,
  1111  			0x59, 0xf8, 0xc8, 0x3e, 0x97, 0xef, 0x3f, 0xb6,
  1112  			0xcf, 0x78, 0xb4, 0xbc, 0xfb, 0x7a, 0x6f, 0x18,
  1113  			0xc3, 0xf9, 0x14, 0x7c, 0x8e, 0x88, 0x0d, 0x11,
  1114  			0x48, 0x56, 0x24, 0xaf, 0xeb, 0x63, 0xc1, 0x25,
  1115  			0x6d, 0x18, 0x98, 0xad, 0xc8, 0x91, 0x95, 0xec,
  1116  			0xc8, 0x64, 0xce, 0x3a, 0xc3, 0xe4, 0x13, 0x48,
  1117  			0x22, 0xf2, 0x00, 0xc2, 0x88, 0xe0, 0xc0, 0xed,
  1118  			0xbb, 0xd8, 0xf7, 0xc1, 0x12, 0x13, 0xbb, 0xa4,
  1119  			0xae, 0xd7, 0xf7, 0xfa, 0x18, 0xd1, 0x12, 0x05,
  1120  			0xde, 0x20, 0x2b, 0xca, 0xa0, 0x5f, 0x60, 0x8a,
  1121  			0x18, 0xc3, 0x0e, 0xc3, 0x36, 0xd8, 0xac, 0x49,
  1122  			0xd9, 0xec, 0x89, 0x65, 0x69, 0x0b, 0x6d, 0x84,
  1123  			0x50, 0xc5, 0x64, 0xbd, 0x63, 0x0a, 0xb2, 0x8c,
  1124  			0x43, 0x9a, 0xc3, 0xd3, 0xa3, 0x75, 0xae, 0x85,
  1125  			0x7d, 0x0d, 0x5b, 0x0d, 0xcb, 0xb7, 0x92, 0xe7,
  1126  			0x54, 0x58, 0xaf, 0xc2, 0xd6, 0x7e, 0x4b, 0x15,
  1127  			0x73, 0xd2, 0x57, 0x47, 0x4a, 0x95, 0x62, 0xbb,
  1128  			0x4c, 0x7c, 0x4f, 0x15, 0x3b, 0x9c, 0xda, 0x94,
  1129  			0xad, 0x72, 0xb5, 0x24, 0x2c, 0x29, 0xac, 0x7e,
  1130  			0x80, 0x51, 0x42, 0xa2, 0xc9, 0x78, 0xe1, 0xf6,
  1131  			0x41, 0x12, 0x93, 0xf9, 0x69, 0x47, 0x65, 0x67,
  1132  			0xb8, 0x9e, 0x81, 0xc5, 0x94, 0x24, 0xeb, 0x35,
  1133  			0xf2, 0x1d, 0xdf, 0xf5, 0x40, 0x38, 0x26, 0xce,
  1134  			0xc0, 0xc3, 0x03, 0xec, 0x0f, 0xb0, 0xbe, 0xf5,
  1135  			0x92, 0xcc, 0x67, 0xba, 0xb1, 0xc0, 0x07, 0xf1,
  1136  			0x82, 0x38, 0xc8, 0x07, 0x93, 0x88, 0x7c, 0xd9,
  1137  			0xcc, 0x92, 0x09, 0x88, 0x43, 0xb2, 0x08, 0xc3,
  1138  			0xcd, 0x72, 0x11, 0x8d, 0xc0, 0x34, 0xd1, 0x84,
  1139  			0x18, 0x21, 0xdb, 0x09, 0xbc, 0xbf, 0x91, 0xf8,
  1140  			0xe6, 0x48, 0xcf, 0xbe, 0x05, 0x32, 0x6e, 0x91,
  1141  			0xd9, 0x85, 0xa6, 0x5c, 0x16, 0xec, 0x1b, 0x88,
  1142  			0xa3, 0xeb, 0xe1, 0xfa, 0xdd, 0x08, 0x62, 0x18,
  1143  			0xf4, 0x8e, 0xb6, 0xc6, 0x84, 0x57, 0x9f, 0xd9,
  1144  			0x26, 0x98, 0x3d, 0x6a, 0x66, 0x97, 0x46, 0x5d,
  1145  			0xcc, 0xee, 0x9f, 0x07, 0x2f, 0xa9, 0x6a, 0xe8,
  1146  			0x5b, 0x16, 0x15, 0xb2, 0x75, 0x1e, 0x7e, 0xf3,
  1147  			0xe2, 0xf8, 0x8d, 0xc6, 0xff, 0xe0, 0xba, 0xc2,
  1148  			0xec, 0x1d, 0x4c, 0x1b, 0x9b, 0xbd, 0xd2, 0xec,
  1149  			0x2a, 0xca, 0xd3, 0x92, 0x0b, 0xf6, 0x8f, 0x88,
  1150  			0xd9, 0x6d, 0xb1, 0x6d, 0xb0, 0x33, 0x9c, 0xac,
  1151  			0x40, 0xf7, 0x51, 0xd6, 0x17, 0xd9, 0x82, 0x85,
  1152  			0x6a, 0xdd, 0xef, 0xd5, 0x07, 0xf3, 0xa3, 0x79,
  1153  			0x8b, 0x89, 0xda, 0xd1, 0xfd, 0x9e, 0xcb, 0x4a,
  1154  			0x4f, 0x96, 0xaa, 0x4f, 0xc7, 0x9c, 0x29, 0x6b,
  1155  			0x14, 0x86, 0xf0, 0x52, 0x29, 0xf8, 0x22, 0xb7,
  1156  			0xe3, 0x42, 0xdb, 0x82, 0x9d, 0xb9, 0x64, 0xe9,
  1157  			0xb6, 0xb2, 0x83, 0x54, 0xb0, 0xb2, 0x19, 0x09,
  1158  			0x5e, 0x49, 0x56, 0xa4, 0x79, 0x2d, 0x04, 0xdd,
  1159  			0x2b, 0xbd, 0x2b, 0xea, 0x53, 0x26, 0x74, 0x06,
  1160  			0x6f, 0x5e, 0x2a, 0xa1, 0xe2, 0x8d, 0x6e, 0xe7,
  1161  			0x9c, 0x97, 0x7a, 0x20, 0x3b, 0x77, 0x86, 0x61,
  1162  			0xbc, 0xd3, 0xeb, 0xc1, 0x78, 0x7e, 0xfa, 0x79,
  1163  			0xff, 0x0b, 0xf6, 0x33, 0x1f, 0x79, 0x76, 0x03,
  1164  			0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
  1165  			0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
  1166  			0x02, 0x00, 0xcf, 0x00, 0x4d, 0xce, 0x31, 0x6a,
  1167  			0xc3, 0x30, 0x18, 0x05, 0x60, 0x41, 0x0f, 0x50,
  1168  			0xd2, 0x66, 0x30, 0x74, 0x88, 0xab, 0x18, 0xeb,
  1169  			0x59, 0xb2, 0xa5, 0xff, 0xb7, 0xa9, 0x93, 0x8c,
  1170  			0x32, 0x82, 0x6a, 0x76, 0xb6, 0xce, 0x3d, 0x40,
  1171  			0x2e, 0x90, 0x41, 0xc1, 0x83, 0x73, 0xc1, 0xdc,
  1172  			0xa4, 0x74, 0xad, 0x4b, 0xa0, 0xf4, 0x5b, 0xde,
  1173  			0xe3, 0x4d, 0xef, 0x26, 0xee, 0xbe, 0xbe, 0xaf,
  1174  			0x0f, 0xcf, 0xe2, 0x94, 0x0b, 0x71, 0x16, 0x9f,
  1175  			0xff, 0xb6, 0xdf, 0x3c, 0x8e, 0x23, 0xf5, 0x6d,
  1176  			0xdf, 0xbd, 0x59, 0x3e, 0xf4, 0xdd, 0x6e, 0xdf,
  1177  			0xb6, 0x62, 0xb8, 0xc8, 0xe8, 0x63, 0x98, 0x57,
  1178  			0x29, 0x44, 0x9f, 0xbc, 0x9c, 0xa6, 0x4c, 0x66,
  1179  			0xc5, 0x94, 0x45, 0xa4, 0x39, 0xad, 0x83, 0x7f,
  1180  			0x8a, 0x31, 0x0c, 0x4b, 0x0d, 0x98, 0xb3, 0x20,
  1181  			0xe1, 0xd7, 0xe9, 0x55, 0xe6, 0x79, 0xfe, 0x52,
  1182  			0xa0, 0xd2, 0xa5, 0xde, 0x42, 0xab, 0x2d, 0x60,
  1183  			0xea, 0x1a, 0xc6, 0x28, 0x65, 0xa1, 0x01, 0xab,
  1184  			0x6c, 0xa9, 0x50, 0x35, 0x0a, 0x1b, 0xc7, 0xda,
  1185  			0xb0, 0x61, 0xaa, 0x1d, 0xa1, 0xd4, 0xa6, 0x65,
  1186  			0x36, 0x64, 0xa0, 0x1c, 0x3b, 0x66, 0x22, 0x76,
  1187  			0x8e, 0xc8, 0x71, 0x45, 0x0b, 0x0b, 0xba, 0xb3,
  1188  			0x4d, 0xa3, 0xf1, 0x38, 0xbe, 0x7f, 0xfc, 0x7d,
  1189  			0x15, 0x3f, 0xf2, 0x15, 0x80, 0x8f, 0xda, 0x00,
  1190  			0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
  1191  			0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
  1192  			0x02, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x00, 0x00,
  1193  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1194  		},
  1195  		expect: sam.GroupReference,
  1196  	},
  1197  }
  1198  
  1199  func (s *S) TestIssue13(c *check.C) {
  1200  	br, err := NewReader(bytes.NewReader(issue13), *conc)
  1201  	c.Assert(err, check.Equals, nil, check.Commentf("Failed to open BAM"))
  1202  
  1203  	r, err := br.Read()
  1204  	c.Assert(err, check.Equals, nil, check.Commentf("Failed to read BAM record"))
  1205  
  1206  	end := r.End()
  1207  	c.Check(end, check.Equals, 4391)
  1208  }
  1209  
  1210  // This is BAM data provided in issue 12 [sic] from SAM file in comment 4.
  1211  // Issue 12 as described is working as intended.
  1212  //
  1213  // @HD	VN:1.0	SO:coordinate
  1214  // @SQ	SN:Zv9_NA129	LN:9079
  1215  // 10	0	Zv9_NA129	4272	50	40M75N5M	*	0	0	TGACGCAGAGGTGCGCAAGACCTCCAAGAAGCAGCTGAAGGACAC	DDDDHGHHHJI<ABGGIHGIGGHIJEEEGGGCBFCEHIIFFHECI	AS:i:-3	XN:i:0	XM:i:1	XO:i:0	XG:i:0	NM:i:1	MD:Z:0C44	YT:Z:UU	XS:A:+	NH:i:1
  1216  //
  1217  var issue13 = []byte{
  1218  	0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
  1219  	0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
  1220  	0x61, 0x00, 0x73, 0x72, 0xf4, 0x65, 0x34, 0x62,
  1221  	0x60, 0x60, 0x70, 0xf0, 0x70, 0xe1, 0x0c, 0xf3,
  1222  	0xb3, 0x32, 0xd4, 0x33, 0xe0, 0x0c, 0xf6, 0xb7,
  1223  	0x4a, 0xce, 0xcf, 0x2f, 0x4a, 0xc9, 0xcc, 0x4b,
  1224  	0x2c, 0x49, 0xe5, 0x72, 0x08, 0x0e, 0xe4, 0x0c,
  1225  	0xf6, 0xb3, 0x8a, 0x2a, 0xb3, 0x8c, 0xf7, 0x73,
  1226  	0x34, 0x34, 0xb2, 0xe4, 0xf4, 0xf1, 0xb3, 0xb2,
  1227  	0x34, 0x30, 0xb7, 0xe4, 0x62, 0x04, 0xea, 0xe2,
  1228  	0x02, 0x62, 0xb8, 0x0c, 0x43, 0xb9, 0x32, 0x03,
  1229  	0x03, 0x00, 0x03, 0x99, 0x97, 0x23, 0x50, 0x00,
  1230  	0x00, 0x00, 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00,
  1231  	0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0x42, 0x43,
  1232  	0x02, 0x00, 0xab, 0x00, 0x2d, 0x89, 0x41, 0x0a,
  1233  	0xc2, 0x30, 0x10, 0x45, 0xa7, 0xd6, 0x03, 0xd8,
  1234  	0x92, 0x9d, 0x9b, 0x26, 0xa6, 0x33, 0x53, 0x44,
  1235  	0xa8, 0xd2, 0x0b, 0x24, 0x11, 0x6c, 0x17, 0xad,
  1236  	0x42, 0x2d, 0xc4, 0x6e, 0xbd, 0x88, 0x88, 0x17,
  1237  	0xf1, 0x04, 0x2e, 0x3c, 0x9f, 0x68, 0x44, 0x1f,
  1238  	0x7c, 0xfe, 0xfb, 0xfc, 0x3b, 0xfc, 0x78, 0xcc,
  1239  	0x00, 0xe2, 0x4d, 0x93, 0xc6, 0xc1, 0x57, 0x21,
  1240  	0xef, 0x3f, 0xdf, 0x6f, 0x5d, 0xc2, 0x65, 0x02,
  1241  	0xf0, 0x9c, 0x02, 0x1c, 0xc2, 0xbc, 0xa5, 0x56,
  1242  	0x88, 0xda, 0xda, 0xc4, 0xa8, 0xab, 0x14, 0x89,
  1243  	0x15, 0x6c, 0x84, 0x91, 0xd9, 0x22, 0x40, 0x48,
  1244  	0x44, 0x05, 0xcf, 0x33, 0x89, 0xc8, 0x84, 0x8c,
  1245  	0x48, 0x5c, 0x68, 0xad, 0x11, 0x51, 0xc9, 0x5c,
  1246  	0x69, 0x62, 0xce, 0x73, 0xd2, 0x8a, 0x4d, 0x7f,
  1247  	0x7e, 0xf9, 0xce, 0x81, 0x6f, 0x5d, 0xe4, 0xf7,
  1248  	0xa1, 0x77, 0x0e, 0xba, 0xe0, 0xed, 0x76, 0x2c,
  1249  	0x5d, 0x55, 0xc1, 0xe9, 0x38, 0x0e, 0x03, 0xf8,
  1250  	0xde, 0x2c, 0xbb, 0xda, 0x45, 0x1f, 0xf4, 0x97,
  1251  	0xb4, 0x05, 0xa5, 0x00, 0x00, 0x00, 0x1f, 0x8b,
  1252  	0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1253  	0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00,
  1254  	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1255  	0x00, 0x00,
  1256  }
  1257  
  1258  func (s *S) TestIssueDate(c *check.C) {
  1259  	br, err := NewReader(bytes.NewReader(issueDate), *conc)
  1260  	c.Assert(err, check.Equals, nil, check.Commentf("Failed to open BAM"))
  1261  
  1262  	rg := br.Header().RGs()
  1263  	c.Assert(len(rg), check.Equals, 1)
  1264  	expect := time.Date(2014, 03, 25, 12, 26, 51, 0, time.FixedZone("", -int(7*time.Hour/time.Second)))
  1265  	c.Check(rg[0].Time(), check.DeepEquals, expect)
  1266  }
  1267  
  1268  // This is BAM data from the following SAM.
  1269  //
  1270  // @HD	VN:1.0
  1271  // @SQ	SN:ref	LN:1
  1272  // @RG	ID:rg	DT:2014-03-25T12:26:51-0700
  1273  // r1	125	ref	-1	0	*	=	-1	0	A	B	RG:Z:rg
  1274  var issueDate = []byte{
  1275  	0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
  1276  	0x00, 0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00,
  1277  	0x6d, 0x00, 0x73, 0x72, 0xf4, 0x65, 0x74, 0x64,
  1278  	0x60, 0x60, 0x70, 0xf0, 0x70, 0xe1, 0x0c, 0xf3,
  1279  	0xb3, 0x32, 0xd4, 0x33, 0xe0, 0x72, 0x08, 0x0e,
  1280  	0xe4, 0x0c, 0xf6, 0xb3, 0x2a, 0x4a, 0x4d, 0xe3,
  1281  	0xf4, 0x01, 0x8a, 0x70, 0x39, 0x04, 0xb9, 0x73,
  1282  	0x7a, 0xba, 0x58, 0x15, 0xa5, 0x73, 0xba, 0x84,
  1283  	0x58, 0x19, 0x19, 0x18, 0x9a, 0xe8, 0x1a, 0x18,
  1284  	0xeb, 0x1a, 0x99, 0x86, 0x18, 0x1a, 0x59, 0x19,
  1285  	0x99, 0x59, 0x99, 0x1a, 0xea, 0x1a, 0x98, 0x1b,
  1286  	0x18, 0x70, 0x31, 0x02, 0x0d, 0x61, 0x01, 0x62,
  1287  	0xa0, 0x36, 0x06, 0x10, 0x1b, 0x00, 0x38, 0x08,
  1288  	0xd9, 0xec, 0x59, 0x00, 0x00, 0x00, 0x1f, 0x8b,
  1289  	0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1290  	0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x38, 0x00,
  1291  	0xd3, 0x66, 0x80, 0x80, 0xff, 0x40, 0xc0, 0xcc,
  1292  	0xe0, 0x21, 0xc4, 0xc0, 0x50, 0xcb, 0xc0, 0x88,
  1293  	0x24, 0x06, 0xa2, 0x8b, 0x0c, 0x19, 0x04, 0x14,
  1294  	0x83, 0xdc, 0xa3, 0x8a, 0xd2, 0x19, 0x00, 0xe6,
  1295  	0x18, 0xef, 0x3c, 0x2f, 0x00, 0x00, 0x00, 0x1f,
  1296  	0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
  1297  	0xff, 0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x1b,
  1298  	0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1299  	0x00, 0x00, 0x00,
  1300  }
  1301  
  1302  var baiTestData = []struct {
  1303  	data   []byte
  1304  	expect *Index
  1305  	err    error
  1306  }{
  1307  	{
  1308  		/*
  1309  		   0x42, 0x41, 0x49, 0x01, // BAI\1
  1310  		   0x01, 0x00, 0x00, 0x00, // n_ref
  1311  
  1312  		   0x02, 0x00, 0x00, 0x00, // n_bin
  1313  
  1314  		   		0x49, 0x12, 0x00, 0x00, // bin
  1315  		   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1316  
  1317  		   			0x00, 0x00, 0x62, 0x00,	0x00, 0x00, 0x00, 0x00, // chunk_beg
  1318  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // chunk_end
  1319  
  1320  		   		0x4a, 0x92, 0x00, 0x00, // bin - always 0x924a
  1321  		   		0x02, 0x00, 0x00, 0x00, // n_chunk - always 2
  1322  
  1323  		   			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // unmapped_beg
  1324  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // unmapped_end
  1325  
  1326  		   			0x08, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, // mapped_count
  1327  		   			0x01, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, // unmapped_count
  1328  
  1329  		   0x01, 0x00, 0x00, 0x00, // n_intv
  1330  
  1331  		   		0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // ioffset
  1332  
  1333  		   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // n_no_coor
  1334  		*/
  1335  		data: []byte{
  1336  			0x42, 0x41, 0x49, 0x01, 0x01, 0x00, 0x00, 0x00,
  1337  			0x02, 0x00, 0x00, 0x00, 0x49, 0x12, 0x00, 0x00,
  1338  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1339  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1340  			0x00, 0x00, 0x00, 0x00, 0x4a, 0x92, 0x00, 0x00,
  1341  			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1342  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1343  			0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  1344  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1345  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1346  			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00,
  1347  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1348  		},
  1349  		expect: &Index{idx: internal.Index{
  1350  			Refs: []internal.RefIndex{
  1351  				{
  1352  					Bins: []internal.Bin{
  1353  						{
  1354  							Bin: 4681, Chunks: []bgzf.Chunk{
  1355  								{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1356  							},
  1357  						},
  1358  					},
  1359  					Stats: &internal.ReferenceStats{
  1360  						Chunk:    bgzf.Chunk{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1361  						Mapped:   8,
  1362  						Unmapped: 1,
  1363  					},
  1364  					Intervals: []bgzf.Offset{{File: 98, Block: 0}},
  1365  				},
  1366  			},
  1367  			Unmapped:   uint64ptr(1),
  1368  			IsSorted:   true,
  1369  			LastRecord: maxInt,
  1370  		}},
  1371  		err: nil,
  1372  	},
  1373  	{
  1374  		/*
  1375  		   0x42, 0x41, 0x49, 0x01, // BAI\1
  1376  		   0x01, 0x00, 0x00, 0x00, // n_ref
  1377  
  1378  		   0x02, 0x00, 0x00, 0x00, // n_bin
  1379  
  1380  		   		0x49, 0x12, 0x00, 0x00, // bin
  1381  		   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1382  
  1383  		   			0x00, 0x00, 0x62, 0x00,	0x00, 0x00, 0x00, 0x00, // chunk_beg
  1384  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // chunk_end
  1385  
  1386  		   		0x4a, 0x92, 0x00, 0x00, // bin - always 0x924a
  1387  		   		0x02, 0x00, 0x00, 0x00, // n_chunk - always 2
  1388  
  1389  		   			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // unmapped_beg
  1390  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // unmapped_end
  1391  
  1392  		   			0x08, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, // mapped_count
  1393  		   			0x01, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, // unmapped_count
  1394  
  1395  		   0x01, 0x00, 0x00, 0x00, // n_intv
  1396  
  1397  		   		0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // ioffset
  1398  		*/
  1399  		data: []byte{
  1400  			0x42, 0x41, 0x49, 0x01, 0x01, 0x00, 0x00, 0x00,
  1401  			0x02, 0x00, 0x00, 0x00, 0x49, 0x12, 0x00, 0x00,
  1402  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1403  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1404  			0x00, 0x00, 0x00, 0x00, 0x4a, 0x92, 0x00, 0x00,
  1405  			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1406  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1407  			0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  1408  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1409  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1410  			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00,
  1411  		},
  1412  		expect: &Index{idx: internal.Index{
  1413  			Refs: []internal.RefIndex{
  1414  				{
  1415  					Bins: []internal.Bin{
  1416  						{
  1417  							Bin: 4681, Chunks: []bgzf.Chunk{
  1418  								{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1419  							},
  1420  						},
  1421  					},
  1422  					Stats: &internal.ReferenceStats{
  1423  						Chunk:    bgzf.Chunk{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1424  						Mapped:   8,
  1425  						Unmapped: 1,
  1426  					},
  1427  					Intervals: []bgzf.Offset{{File: 98, Block: 0}},
  1428  				},
  1429  			},
  1430  			Unmapped:   nil,
  1431  			IsSorted:   true,
  1432  			LastRecord: maxInt,
  1433  		}},
  1434  		err: nil,
  1435  	},
  1436  	{
  1437  		/*
  1438  		   0x42, 0x41, 0x49, 0x01, // BAI\1
  1439  		   0x01, 0x00, 0x00, 0x00, // n_ref
  1440  
  1441  		   0x01, 0x00, 0x00, 0x00, // n_bin
  1442  
  1443  		   		0x49, 0x12, 0x00, 0x00, // bin
  1444  		   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1445  
  1446  		   			0x00, 0x00, 0x62, 0x00,	0x00, 0x00, 0x00, 0x00, // chunk_beg
  1447  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // chunk_end
  1448  
  1449  		   0x01, 0x00, 0x00, 0x00, // n_intv
  1450  
  1451  		   		0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // ioffset
  1452  
  1453  		   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // n_no_coor
  1454  		*/
  1455  		data: []byte{
  1456  			0x42, 0x41, 0x49, 0x01, 0x01, 0x00, 0x00, 0x00,
  1457  			0x01, 0x00, 0x00, 0x00, 0x49, 0x12, 0x00, 0x00,
  1458  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1459  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1460  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1461  			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00,
  1462  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1463  		},
  1464  		expect: &Index{idx: internal.Index{
  1465  			Refs: []internal.RefIndex{
  1466  				{
  1467  					Bins: []internal.Bin{
  1468  						{
  1469  							Bin: 4681, Chunks: []bgzf.Chunk{
  1470  								{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1471  							},
  1472  						},
  1473  					},
  1474  					Stats:     nil,
  1475  					Intervals: []bgzf.Offset{{File: 98, Block: 0}},
  1476  				},
  1477  			},
  1478  			Unmapped:   uint64ptr(1),
  1479  			IsSorted:   true,
  1480  			LastRecord: maxInt,
  1481  		}},
  1482  		err: nil,
  1483  	},
  1484  	{
  1485  		/*
  1486  		   0x42, 0x41, 0x49, 0x01, // BAI\1
  1487  		   0x01, 0x00, 0x00, 0x00, // n_ref
  1488  
  1489  		   0x01, 0x00, 0x00, 0x00, // n_bin
  1490  
  1491  		   		0x49, 0x12, 0x00, 0x00, // bin
  1492  		   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1493  
  1494  		   			0x00, 0x00, 0x62, 0x00,	0x00, 0x00, 0x00, 0x00, // chunk_beg
  1495  		   			0x00, 0x00, 0x91, 0x01,	0x00, 0x00, 0x00, 0x00, // chunk_end
  1496  
  1497  		   0x01, 0x00, 0x00, 0x00, // n_intv
  1498  
  1499  		   		0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // ioffset
  1500  		*/
  1501  		data: []byte{
  1502  			0x42, 0x41, 0x49, 0x01, 0x01, 0x00, 0x00, 0x00,
  1503  			0x01, 0x00, 0x00, 0x00, 0x49, 0x12, 0x00, 0x00,
  1504  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
  1505  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01,
  1506  			0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  1507  			0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00,
  1508  		},
  1509  		expect: &Index{idx: internal.Index{
  1510  			Refs: []internal.RefIndex{
  1511  				{
  1512  					Bins: []internal.Bin{
  1513  						{
  1514  							Bin: 4681, Chunks: []bgzf.Chunk{
  1515  								{Begin: bgzf.Offset{File: 98, Block: 0}, End: bgzf.Offset{File: 401, Block: 0}},
  1516  							},
  1517  						},
  1518  					},
  1519  					Stats:     nil,
  1520  					Intervals: []bgzf.Offset{{File: 98, Block: 0}},
  1521  				},
  1522  			},
  1523  			Unmapped:   nil,
  1524  			IsSorted:   true,
  1525  			LastRecord: maxInt,
  1526  		}},
  1527  		err: nil,
  1528  	},
  1529  	{
  1530  		/*
  1531  			   0x42, 0x41, 0x49, 0x01, // BAI\1
  1532  			   0x56, 0x00, 0x00, 0x00, // n_ref
  1533  
  1534  			   	0x00, 0x00, 0x00, 0x00, // empty bins
  1535  				[ lines removed ]
  1536  			   	0x00, 0x00, 0x00, 0x00, // empty intervals
  1537  
  1538  			   	0x02, 0x00, 0x00, 0x00, // n_bins - ref 23
  1539  			   		0x4a, 0x92, 0x00, 0x00, // bin - always 0x924a
  1540  			   		0x02, 0x00, 0x00, 0x00, // n_chunk - always 2
  1541  			   			0x00, 0x00, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_beg
  1542  			   			0xf9, 0x1c, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_end
  1543  			   			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mapped_count
  1544  			   			0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // unmapped_count
  1545  
  1546  			   		0x70, 0x20, 0x00, 0x00, // bin
  1547  			   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1548  			   			0x00, 0x00, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_beg
  1549  			   			0xf9, 0x1c, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_end
  1550  
  1551  			   	0x00, 0x00, 0x00, 0x00, // n_intv - ref 23
  1552  
  1553  			   	0x02, 0x00, 0x00, 0x00,  // n_bins - ref 24
  1554  			   		0x4a, 0x92, 0x00, 0x00, // bin - always 0x924a
  1555  			   		0x02, 0x00, 0x00, 0x00, // n_chunk - always 2
  1556  			   			0xf9, 0x1c, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_beg
  1557  			   			0x1d, 0x40, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_end
  1558  			   			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mapped_count
  1559  			   			0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // unmapped_count
  1560  
  1561  			   		0x4a, 0x12, 0x00, 0x00, // bin
  1562  			   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1563  			   			0xf9, 0x1c, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_beg
  1564  			   			0x1d, 0x40, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_end
  1565  
  1566  			   	0x00, 0x00, 0x00, 0x00, // n_intv - ref 24
  1567  
  1568  			   	0x00, 0x00, 0x00, 0x00, // empty bins
  1569  				[ lines removed ]
  1570  			   	0x00, 0x00, 0x00, 0x00, // empty intervals
  1571  
  1572  			   	0x02, 0x00, 0x00, 0x00,  // n_bins - ref 72
  1573  			   		0x53, 0x12, 0x00, 0x00, // bin
  1574  			   		0x01, 0x00, 0x00, 0x00, // n_chunk
  1575  			   			0x1d, 0x40, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_beg
  1576  			   			0xf5, 0x41, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // chunk_end
  1577  
  1578  			   		0x4a, 0x92, 0x00, 0x00, // bin - always 0x924a
  1579  			   		0x02, 0x00, 0x00, 0x00, // n_chunk - always 2
  1580  			   			0x1d, 0x40, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_beg
  1581  			   			0xf5, 0x41, 0x46, 0x12, 0x00, 0x00, 0x00, 0x00, // unmapped_end
  1582  			   			0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, // mapped_count
  1583  			   			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // unmapped_count
  1584  
  1585  			   	0x00, 0x00, 0x00, 0x00, // n_intv - ref 72
  1586  
  1587  			   	0x00, 0x00, 0x00, 0x00, // empty bins
  1588  				[ lines removed ]
  1589  			   	0x00, 0x00, 0x00, 0x00, // empty intervals
  1590  
  1591  			   0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // n_no_coor
  1592  		*/
  1593  		data: []byte{
  1594  			0x42, 0x41, 0x49, 0x01, 0x56, 0x00, 0x00, 0x00,
  1595  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1596  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1597  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1598  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1599  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1600  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1601  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1602  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1603  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1604  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1605  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1606  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1607  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1608  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1609  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1610  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1611  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1612  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1613  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1614  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1615  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1616  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1617  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1618  			0x02, 0x00, 0x00, 0x00, 0x4a, 0x92, 0x00, 0x00,
  1619  			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x12,
  1620  			0x00, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x46, 0x12,
  1621  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1622  			0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
  1623  			0x00, 0x00, 0x00, 0x00, 0x70, 0x20, 0x00, 0x00,
  1624  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x12,
  1625  			0x00, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x46, 0x12,
  1626  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1627  			0x02, 0x00, 0x00, 0x00, 0x4a, 0x92, 0x00, 0x00,
  1628  			0x02, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x46, 0x12,
  1629  			0x00, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x46, 0x12,
  1630  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1631  			0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
  1632  			0x00, 0x00, 0x00, 0x00, 0x4a, 0x12, 0x00, 0x00,
  1633  			0x01, 0x00, 0x00, 0x00, 0xf9, 0x1c, 0x46, 0x12,
  1634  			0x00, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x46, 0x12,
  1635  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1636  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1637  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1638  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1639  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1640  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1641  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1642  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1643  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1644  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1645  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1646  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1647  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1648  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1649  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1650  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1651  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1652  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1653  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1654  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1655  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1656  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1657  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1658  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1659  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1660  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1661  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1662  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1663  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1664  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1665  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1666  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1667  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1668  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1669  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1670  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1671  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1672  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1673  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1674  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1675  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1676  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1677  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1678  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1679  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1680  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1681  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1682  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1683  			0x02, 0x00, 0x00, 0x00, 0x53, 0x12, 0x00, 0x00,
  1684  			0x01, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x46, 0x12,
  1685  			0x00, 0x00, 0x00, 0x00, 0xf5, 0x41, 0x46, 0x12,
  1686  			0x00, 0x00, 0x00, 0x00, 0x4a, 0x92, 0x00, 0x00,
  1687  			0x02, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x46, 0x12,
  1688  			0x00, 0x00, 0x00, 0x00, 0xf5, 0x41, 0x46, 0x12,
  1689  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1690  			0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  1691  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1692  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1693  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1694  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1695  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1696  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1697  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1698  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1699  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1700  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1701  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1702  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1703  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1704  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1705  			0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1706  		},
  1707  		expect: &Index{idx: internal.Index{
  1708  			Refs: func() []internal.RefIndex {
  1709  				idx := [86]internal.RefIndex{
  1710  					23: {
  1711  						Bins: []internal.Bin{
  1712  							{
  1713  								Bin: 0x2070,
  1714  								Chunks: []bgzf.Chunk{
  1715  									{
  1716  										Begin: bgzf.Offset{File: 0x1246, Block: 0x0},
  1717  										End:   bgzf.Offset{File: 0x1246, Block: 0x1cf9},
  1718  									},
  1719  								},
  1720  							},
  1721  						},
  1722  						Stats: &internal.ReferenceStats{
  1723  							Chunk: bgzf.Chunk{
  1724  								Begin: bgzf.Offset{File: 0x1246, Block: 0x0},
  1725  								End:   bgzf.Offset{File: 0x1246, Block: 0x1cf9},
  1726  							},
  1727  							Mapped: 0, Unmapped: 0x1d,
  1728  						},
  1729  						Intervals: nil,
  1730  					},
  1731  					24: {
  1732  						Bins: []internal.Bin{
  1733  							{
  1734  								Bin: 0x124a,
  1735  								Chunks: []bgzf.Chunk{
  1736  									{
  1737  										Begin: bgzf.Offset{File: 0x1246, Block: 0x1cf9},
  1738  										End:   bgzf.Offset{File: 0x1246, Block: 0x401d},
  1739  									},
  1740  								},
  1741  							},
  1742  						},
  1743  						Stats: &internal.ReferenceStats{
  1744  							Chunk: bgzf.Chunk{
  1745  								Begin: bgzf.Offset{File: 0x1246, Block: 0x1cf9},
  1746  								End:   bgzf.Offset{File: 0x1246, Block: 0x401d},
  1747  							},
  1748  							Mapped: 0, Unmapped: 0x25,
  1749  						},
  1750  						Intervals: nil,
  1751  					},
  1752  					72: {
  1753  						Bins: []internal.Bin{
  1754  							{
  1755  								Bin: 0x1253,
  1756  								Chunks: []bgzf.Chunk{
  1757  									{
  1758  										Begin: bgzf.Offset{File: 0x1246, Block: 0x401d},
  1759  										End:   bgzf.Offset{File: 0x1246, Block: 0x41f5},
  1760  									},
  1761  								},
  1762  							},
  1763  						},
  1764  						Stats: &internal.ReferenceStats{
  1765  							Chunk: bgzf.Chunk{
  1766  								Begin: bgzf.Offset{File: 0x1246, Block: 0x401d},
  1767  								End:   bgzf.Offset{File: 0x1246, Block: 0x41f5},
  1768  							},
  1769  							Mapped: 0, Unmapped: 0x2,
  1770  						},
  1771  						Intervals: nil,
  1772  					},
  1773  				}
  1774  				return idx[:]
  1775  			}(),
  1776  			Unmapped:   uint64ptr(932),
  1777  			IsSorted:   true,
  1778  			LastRecord: maxInt,
  1779  		}},
  1780  		err: nil,
  1781  	},
  1782  }
  1783  
  1784  func uint64ptr(i uint64) *uint64 {
  1785  	return &i
  1786  }
  1787  
  1788  func (s *S) TestReadBAI(c *check.C) {
  1789  	for _, test := range baiTestData {
  1790  		bai, err := ReadIndex(bytes.NewReader(test.data))
  1791  		c.Assert(err, check.Equals, test.err)
  1792  		c.Check(bai, check.DeepEquals, test.expect)
  1793  	}
  1794  }
  1795  
  1796  // conceptualBAIdata is gzip compressed BAI for the alignments in the BAM
  1797  // corresponding to:
  1798  //
  1799  // @HD	VN:1.0	SO:coordinate
  1800  // @SQ	SN:conceptual	LN:134217728
  1801  // 60m66m:bin0	0	conceptual	62914561	40	6291456M	*	0	0	*	*
  1802  // 70m76m:bin2	0	conceptual	73400321	40	6291456M	*	0	0	*	*
  1803  // 73m75m:bin18	0	conceptual	76546049	40	2097152M	*	0	0	*	*
  1804  //
  1805  // This is a coordinate-translated version of the conceptual example in the
  1806  // SAM spec using binning as actually used by BAM rather than as presented.
  1807  var conceptualBAIdata = []byte{
  1808  	0x1f, 0x8b, 0x08, 0x08, 0xe3, 0xf6, 0x2c, 0x54,
  1809  	0x00, 0x03, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70,
  1810  	0x74, 0x75, 0x61, 0x6c, 0x2e, 0x62, 0x61, 0x6d,
  1811  	0x2e, 0x62, 0x61, 0x69, 0x00, 0xed, 0xcb, 0x41,
  1812  	0x0d, 0x85, 0x30, 0x10, 0x40, 0xc1, 0x2d, 0xa0,
  1813  	0x00, 0x2d, 0x18, 0x80, 0x1b, 0xf8, 0x20, 0x41,
  1814  	0x0f, 0x8a, 0x10, 0xf3, 0x85, 0xfc, 0xa4, 0xb4,
  1815  	0x07, 0x08, 0x0a, 0x60, 0xe6, 0xb0, 0x2f, 0x6d,
  1816  	0xb7, 0xd3, 0x38, 0xa7, 0x14, 0x11, 0x5d, 0x9c,
  1817  	0x52, 0x9e, 0x6b, 0x9e, 0x43, 0x69, 0x53, 0xee,
  1818  	0xeb, 0x79, 0x2b, 0x5d, 0xf6, 0xf3, 0xad, 0xee,
  1819  	0x47, 0xfc, 0xf2, 0x6c, 0xe3, 0xaa, 0x2f, 0xff,
  1820  	0xb7, 0xdb, 0xde, 0xd1, 0x07, 0x00, 0x00, 0x00,
  1821  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1822  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1823  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1824  	0x00, 0x00, 0xf0, 0x68, 0x55, 0x55, 0x55, 0x55,
  1825  	0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x97, 0x76,
  1826  	0x50, 0x55, 0x55, 0x55, 0xd5, 0x4f, 0xb5, 0xfa,
  1827  	0x03, 0x6e, 0x81, 0xb2, 0xab, 0x88, 0x96, 0x00,
  1828  	0x00,
  1829  }
  1830  
  1831  var conceptualBAMdata = []byte{
  1832  	// sam.Header block [{File:0, Block:0}, {File:0, Block:87}).
  1833  	0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1834  	0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x64, 0x00, 0x73, 0x72,
  1835  	0xf4, 0x65, 0xb4, 0x60, 0x60, 0x60, 0x70, 0xf0, 0x70, 0xe1,
  1836  	0x0c, 0xf3, 0xb3, 0x32, 0xd4, 0x33, 0xe0, 0x0c, 0xf6, 0xb7,
  1837  	0x4a, 0xce, 0xcf, 0x2f, 0x4a, 0xc9, 0xcc, 0x4b, 0x2c, 0x49,
  1838  	0xe5, 0x72, 0x08, 0x0e, 0xe4, 0x0c, 0xf6, 0x03, 0x8a, 0xe4,
  1839  	0x25, 0xa7, 0x16, 0x94, 0x94, 0x26, 0xe6, 0x70, 0xfa, 0x00,
  1840  	0x95, 0x19, 0x9b, 0x18, 0x19, 0x9a, 0x9b, 0x1b, 0x59, 0x70,
  1841  	0x31, 0x02, 0xf5, 0x72, 0x03, 0x31, 0x42, 0x1e, 0xc8, 0x61,
  1842  	0xe0, 0x00, 0x00, 0x42, 0x51, 0xcc, 0xea, 0x57, 0x00, 0x00,
  1843  	0x00,
  1844  
  1845  	// Record block [{File:101, Block:0}, {File:101, Block:157}).
  1846  	0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1847  	0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x62, 0x00, 0x33, 0x60,
  1848  	0x80, 0x81, 0x03, 0xcc, 0x3c, 0x1a, 0x0c, 0x0c, 0x8c, 0x50,
  1849  	0xde, 0x7f, 0x28, 0x00, 0xb1, 0xcd, 0x0c, 0x72, 0xcd, 0xcc,
  1850  	0x72, 0xad, 0x92, 0x32, 0xf3, 0x0c, 0x40, 0x5c, 0x36, 0x03,
  1851  	0xb8, 0x9e, 0x04, 0x16, 0x1e, 0x0d, 0x26, 0xac, 0x7a, 0xcc,
  1852  	0x0d, 0x72, 0xcd, 0x21, 0x7a, 0x8c, 0xc0, 0x7a, 0x0c, 0xe1,
  1853  	0x7a, 0x26, 0xb0, 0xf0, 0x6a, 0x08, 0x61, 0xd7, 0x63, 0x9c,
  1854  	0x6b, 0x6e, 0x0a, 0xd6, 0x63, 0x68, 0x01, 0xe2, 0x33, 0x01,
  1855  	0x00, 0x5a, 0x80, 0xfe, 0xec, 0x9d, 0x00, 0x00, 0x00,
  1856  
  1857  	// Magic block [{File:200, Block:0}, {File:200, Block:0}).
  1858  	0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1859  	0x06, 0x00, 0x42, 0x43, 0x02, 0x00, 0x1b, 0x00, 0x03, 0x00,
  1860  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1861  
  1862  	// End {File:228, Block:0}
  1863  }
  1864  
  1865  // conceptualChunks differs from the chunks described in chunkTests
  1866  // since samtools defines the end offset of the last chunk as the
  1867  // end of the file. We define it as the end of the chunk itself.
  1868  var conceptualChunks = []bgzf.Chunk{
  1869  	{Begin: bgzf.Offset{File: 0, Block: 0}, End: bgzf.Offset{File: 0, Block: 87}},        // header
  1870  	{Begin: bgzf.Offset{File: 101, Block: 0}, End: bgzf.Offset{File: 101, Block: 52}},    // 60m66m:bin0
  1871  	{Begin: bgzf.Offset{File: 101, Block: 52}, End: bgzf.Offset{File: 101, Block: 104}},  // 70m76m:bin2
  1872  	{Begin: bgzf.Offset{File: 101, Block: 104}, End: bgzf.Offset{File: 101, Block: 157}}, // 73m75m:bin18
  1873  	{Begin: bgzf.Offset{File: 101, Block: 153}, End: bgzf.Offset{File: 101, Block: 157}}, // EOF - not checked.
  1874  }
  1875  
  1876  func (s *S) TestConceptualBAM(c *check.C) {
  1877  	br, err := NewReader(bytes.NewReader(conceptualBAMdata), *conc)
  1878  	c.Assert(err, check.Equals, nil)
  1879  	c.Check(br.LastChunk(), check.Equals, conceptualChunks[0])
  1880  	for _, chunk := range conceptualChunks[1:] {
  1881  		_, err := br.Read()
  1882  		if err != nil {
  1883  			break
  1884  		}
  1885  		c.Check(br.LastChunk(), check.Equals, chunk)
  1886  	}
  1887  }
  1888  
  1889  var chunkTests = []struct {
  1890  	beg, end int
  1891  	expect   []bgzf.Chunk
  1892  	err      error
  1893  }{
  1894  	{
  1895  		beg: 65000, end: 71000, // Not in covered region.
  1896  		expect: []bgzf.Chunk{
  1897  			{Begin: bgzf.Offset{File: 101, Block: 0}, End: bgzf.Offset{File: 101, Block: 52}},
  1898  		},
  1899  		err: nil,
  1900  	},
  1901  	{
  1902  		beg: 77594624, end: 80740352, // 73m77m:bin2+bin18 - This is the equivalent to the given example.
  1903  		expect: []bgzf.Chunk{
  1904  			{Begin: bgzf.Offset{File: 101, Block: 52}, End: bgzf.Offset{File: 228, Block: 0}},
  1905  		},
  1906  		err: nil,
  1907  	},
  1908  	{
  1909  		beg: 62914561, end: 68157440, // 60m65m:bin0+bin2
  1910  		expect: []bgzf.Chunk{
  1911  			{Begin: bgzf.Offset{File: 101, Block: 0}, End: bgzf.Offset{File: 101, Block: 104}},
  1912  		},
  1913  		err: nil,
  1914  	},
  1915  	{
  1916  		beg: 72351744, end: 80740352, // 69m77m:bin0+bin2+18
  1917  		expect: []bgzf.Chunk{
  1918  			{Begin: bgzf.Offset{File: 101, Block: 0}, End: bgzf.Offset{File: 228, Block: 0}},
  1919  		},
  1920  		err: nil,
  1921  	},
  1922  	{
  1923  		beg: 61865984, end: 80740352, // 59m77m:bin0+bin2+bin18
  1924  		expect: []bgzf.Chunk{
  1925  			{Begin: bgzf.Offset{File: 101, Block: 0}, End: bgzf.Offset{File: 228, Block: 0}},
  1926  		},
  1927  		err: nil,
  1928  	},
  1929  	{
  1930  		beg: 80740352, end: 81788928, // 77m78m - Not in covered region.
  1931  		expect: nil,
  1932  		err:    index.ErrInvalid,
  1933  	},
  1934  }
  1935  
  1936  func (s *S) TestConceptualBAI(c *check.C) {
  1937  	gz, err := gzip.NewReader(bytes.NewReader(conceptualBAIdata))
  1938  	c.Assert(err, check.Equals, nil)
  1939  	bai, err := ReadIndex(gz)
  1940  	c.Assert(err, check.Equals, nil)
  1941  
  1942  	var ref sam.Reference
  1943  	var h sam.Header
  1944  	h.AddReference(&ref)
  1945  
  1946  	for _, test := range chunkTests {
  1947  		chunks, err := bai.Chunks(&ref, test.beg, test.end)
  1948  		c.Check(err, check.Equals, test.err,
  1949  			check.Commentf("Unexpected error for [%d,%d).", test.beg, test.end),
  1950  		)
  1951  		c.Check(chunks, check.DeepEquals, test.expect,
  1952  			check.Commentf("Unexpected result for [%d,%d).", test.beg, test.end),
  1953  		)
  1954  	}
  1955  }
  1956  
  1957  // @HD	VN:1.0	SO:coordinate
  1958  // @SQ	SN:conceptual	LN:134217728
  1959  // 60m66m:bin0	0	conceptual	62914561	40	6291456M	*	0	0	*	*
  1960  // 70m76m:bin2	0	conceptual	73400321	40	6291456M	*	0	0	*	*
  1961  // 73m75m:bin18	0	conceptual	76546049	40	2097152M	*	0	0	*	*
  1962  var (
  1963  	conceptual = func() *sam.Reference {
  1964  		ref, err := sam.NewReference("conceptual", "0", "unicorns", 134217728, nil, nil)
  1965  		if err != nil {
  1966  			panic("Failed to initialise conceptual reference")
  1967  		}
  1968  		// Ensure the reference id is valid.
  1969  		sam.NewHeader(nil, []*sam.Reference{ref})
  1970  		return ref
  1971  	}()
  1972  	bamFile = []struct {
  1973  		rec   *sam.Record
  1974  		chunk bgzf.Chunk
  1975  	}{
  1976  		{
  1977  			rec: &sam.Record{
  1978  				Name: "60m66m:bin0", // [62914560,69206016)
  1979  				Ref:  conceptual,
  1980  				Pos:  62914560,
  1981  				MapQ: 40,
  1982  				Cigar: sam.Cigar{
  1983  					sam.NewCigarOp(sam.CigarMatch, 6291456),
  1984  				},
  1985  			},
  1986  			chunk: bgzf.Chunk{
  1987  				Begin: bgzf.Offset{File: 101, Block: 0},
  1988  				End:   bgzf.Offset{File: 101, Block: 52},
  1989  			},
  1990  		},
  1991  		{
  1992  			rec: &sam.Record{
  1993  				Name: "70m76m:bin2", // [73400320,79691776)
  1994  				Ref:  conceptual,
  1995  				Pos:  73400320,
  1996  				MapQ: 40,
  1997  				Cigar: sam.Cigar{
  1998  					sam.NewCigarOp(sam.CigarMatch, 6291456),
  1999  				},
  2000  			},
  2001  			chunk: bgzf.Chunk{
  2002  				Begin: bgzf.Offset{File: 101, Block: 52},
  2003  				End:   bgzf.Offset{File: 101, Block: 104},
  2004  			},
  2005  		},
  2006  		{
  2007  			rec: &sam.Record{
  2008  				Name: "73m75m:bin18", // [76546048,78643200)
  2009  				Ref:  conceptual,
  2010  				Pos:  76546048,
  2011  				MapQ: 40,
  2012  				Cigar: sam.Cigar{
  2013  					sam.NewCigarOp(sam.CigarMatch, 2097152),
  2014  				},
  2015  			},
  2016  			chunk: bgzf.Chunk{
  2017  				Begin: bgzf.Offset{File: 101, Block: 104},
  2018  				End:   bgzf.Offset{File: 228, Block: 0},
  2019  			},
  2020  		},
  2021  	}
  2022  )
  2023  
  2024  func (s *S) TestAdd(c *check.C) {
  2025  	var bai Index
  2026  	for _, r := range bamFile {
  2027  		c.Assert(bai.Add(r.rec, r.chunk), check.Equals, nil)
  2028  	}
  2029  	gz, err := gzip.NewReader(bytes.NewReader(conceptualBAIdata))
  2030  	c.Assert(err, check.Equals, nil)
  2031  	expect, err := ReadIndex(gz)
  2032  	c.Check(bai.idx.Refs[0].Bins, check.DeepEquals, expect.idx.Refs[0].Bins)
  2033  	c.Check(bai.idx.Refs[0].Stats, check.DeepEquals, expect.idx.Refs[0].Stats)
  2034  	c.Check(bai.idx.Unmapped, check.DeepEquals, expect.idx.Unmapped)
  2035  
  2036  	// We check naively for overlap with tiles since we do not merge chunks in Add.
  2037  	for i := range bai.idx.Refs[0].Intervals {
  2038  		got := bai.idx.Refs[0].Intervals[i]
  2039  		tbeg := i * internal.TileWidth
  2040  		tend := tbeg + internal.TileWidth
  2041  		hasOverlap := false
  2042  		for _, r := range bamFile {
  2043  			if tbeg < r.rec.End() && tend > r.rec.Start() {
  2044  				c.Check(got, check.Equals, r.chunk.Begin,
  2045  					check.Commentf("Unexpected tile offset for [%d,%d) got:%+v expect:%+v", tbeg, tend, got, r.chunk.Begin),
  2046  				)
  2047  				hasOverlap = true
  2048  				break
  2049  			}
  2050  		}
  2051  		if !hasOverlap {
  2052  			c.Check(got, check.Equals, bgzf.Offset{},
  2053  				check.Commentf("Unexpected non-zero offset for [%d,%d) got:%+v", tbeg, tend, got),
  2054  			)
  2055  		}
  2056  	}
  2057  }
  2058  
  2059  var chunkMergeTests = []struct {
  2060  	index func() *Index
  2061  
  2062  	expectAdjacent *Index
  2063  
  2064  	expectSquash *Index
  2065  
  2066  	compStrat      index.MergeStrategy
  2067  	expectCompress *Index
  2068  }{
  2069  	{
  2070  		index: func() *Index {
  2071  			return &Index{idx: internal.Index{
  2072  				Refs: []internal.RefIndex{
  2073  					{
  2074  						Bins: []internal.Bin{
  2075  							{
  2076  								Bin: 0,
  2077  								Chunks: []bgzf.Chunk{
  2078  									{
  2079  										Begin: bgzf.Offset{File: 1, Block: 0},
  2080  										End:   bgzf.Offset{File: 2, Block: 0},
  2081  									},
  2082  									{
  2083  										Begin: bgzf.Offset{File: 2, Block: 0},
  2084  										End:   bgzf.Offset{File: 3, Block: 0},
  2085  									},
  2086  								},
  2087  							},
  2088  							{
  2089  								Bin: 1,
  2090  								Chunks: []bgzf.Chunk{
  2091  									{
  2092  										Begin: bgzf.Offset{File: 1, Block: 0},
  2093  										End:   bgzf.Offset{File: 2, Block: 0},
  2094  									},
  2095  									{
  2096  										Begin: bgzf.Offset{File: 2, Block: 0},
  2097  										End:   bgzf.Offset{File: 3, Block: 0},
  2098  									},
  2099  								},
  2100  							},
  2101  						},
  2102  					},
  2103  				},
  2104  			}}
  2105  		},
  2106  		expectAdjacent: &Index{idx: internal.Index{
  2107  			Refs: []internal.RefIndex{
  2108  				{
  2109  					Bins: []internal.Bin{
  2110  						{
  2111  							Bin: 0,
  2112  							Chunks: []bgzf.Chunk{
  2113  								{
  2114  									Begin: bgzf.Offset{File: 1, Block: 0},
  2115  									End:   bgzf.Offset{File: 3, Block: 0},
  2116  								},
  2117  							},
  2118  						},
  2119  						{
  2120  							Bin: 1,
  2121  							Chunks: []bgzf.Chunk{
  2122  								{
  2123  									Begin: bgzf.Offset{File: 1, Block: 0},
  2124  									End:   bgzf.Offset{File: 3, Block: 0},
  2125  								},
  2126  							},
  2127  						},
  2128  					},
  2129  				},
  2130  			},
  2131  		}},
  2132  		expectSquash: &Index{idx: internal.Index{
  2133  			Refs: []internal.RefIndex{
  2134  				{
  2135  					Bins: []internal.Bin{
  2136  						{
  2137  							Bin: 0,
  2138  							Chunks: []bgzf.Chunk{
  2139  								{
  2140  									Begin: bgzf.Offset{File: 1, Block: 0},
  2141  									End:   bgzf.Offset{File: 3, Block: 0},
  2142  								},
  2143  							},
  2144  						},
  2145  						{
  2146  							Bin: 1,
  2147  							Chunks: []bgzf.Chunk{
  2148  								{
  2149  									Begin: bgzf.Offset{File: 1, Block: 0},
  2150  									End:   bgzf.Offset{File: 3, Block: 0},
  2151  								},
  2152  							},
  2153  						},
  2154  					},
  2155  				},
  2156  			},
  2157  		}},
  2158  	},
  2159  	{
  2160  		index: func() *Index {
  2161  			return &Index{idx: internal.Index{
  2162  				Refs: []internal.RefIndex{
  2163  					{
  2164  						Bins: []internal.Bin{
  2165  							{
  2166  								Bin: 0,
  2167  								Chunks: []bgzf.Chunk{
  2168  									{
  2169  										Begin: bgzf.Offset{File: 1, Block: 0},
  2170  										End:   bgzf.Offset{File: 2, Block: 0},
  2171  									},
  2172  									{
  2173  										Begin: bgzf.Offset{File: 3, Block: 0},
  2174  										End:   bgzf.Offset{File: 4, Block: 0},
  2175  									},
  2176  								},
  2177  							},
  2178  							{
  2179  								Bin: 1,
  2180  								Chunks: []bgzf.Chunk{
  2181  									{
  2182  										Begin: bgzf.Offset{File: 1, Block: 0},
  2183  										End:   bgzf.Offset{File: 2, Block: 0},
  2184  									},
  2185  									{
  2186  										Begin: bgzf.Offset{File: 3, Block: 0},
  2187  										End:   bgzf.Offset{File: 4, Block: 0},
  2188  									},
  2189  								},
  2190  							},
  2191  						},
  2192  					},
  2193  				},
  2194  			}}
  2195  		},
  2196  		expectAdjacent: &Index{idx: internal.Index{
  2197  			Refs: []internal.RefIndex{
  2198  				{
  2199  					Bins: []internal.Bin{
  2200  						{
  2201  							Bin: 0,
  2202  							Chunks: []bgzf.Chunk{
  2203  								{
  2204  									Begin: bgzf.Offset{File: 1, Block: 0},
  2205  									End:   bgzf.Offset{File: 2, Block: 0},
  2206  								},
  2207  								{
  2208  									Begin: bgzf.Offset{File: 3, Block: 0},
  2209  									End:   bgzf.Offset{File: 4, Block: 0},
  2210  								},
  2211  							},
  2212  						},
  2213  						{
  2214  							Bin: 1,
  2215  							Chunks: []bgzf.Chunk{
  2216  								{
  2217  									Begin: bgzf.Offset{File: 1, Block: 0},
  2218  									End:   bgzf.Offset{File: 2, Block: 0},
  2219  								},
  2220  								{
  2221  									Begin: bgzf.Offset{File: 3, Block: 0},
  2222  									End:   bgzf.Offset{File: 4, Block: 0},
  2223  								},
  2224  							},
  2225  						},
  2226  					},
  2227  				},
  2228  			},
  2229  		}},
  2230  		expectSquash: &Index{idx: internal.Index{
  2231  			Refs: []internal.RefIndex{
  2232  				{
  2233  					Bins: []internal.Bin{
  2234  						{
  2235  							Bin: 0,
  2236  							Chunks: []bgzf.Chunk{
  2237  								{
  2238  									Begin: bgzf.Offset{File: 1, Block: 0},
  2239  									End:   bgzf.Offset{File: 4, Block: 0},
  2240  								},
  2241  							},
  2242  						},
  2243  						{
  2244  							Bin: 1,
  2245  							Chunks: []bgzf.Chunk{
  2246  								{
  2247  									Begin: bgzf.Offset{File: 1, Block: 0},
  2248  									End:   bgzf.Offset{File: 4, Block: 0},
  2249  								},
  2250  							},
  2251  						},
  2252  					},
  2253  				},
  2254  			},
  2255  		}},
  2256  	},
  2257  	{
  2258  		index: func() *Index {
  2259  			return &Index{idx: internal.Index{
  2260  				Refs: []internal.RefIndex{
  2261  					{
  2262  						Bins: []internal.Bin{
  2263  							{
  2264  								Bin: 0,
  2265  								Chunks: []bgzf.Chunk{
  2266  									{
  2267  										Begin: bgzf.Offset{File: 1, Block: 0},
  2268  										End:   bgzf.Offset{File: 2, Block: 0},
  2269  									},
  2270  									{
  2271  										Begin: bgzf.Offset{File: 0xffff, Block: 0},
  2272  										End:   bgzf.Offset{File: 0x10000, Block: 0},
  2273  									},
  2274  								},
  2275  							},
  2276  							{
  2277  								Bin: 1,
  2278  								Chunks: []bgzf.Chunk{
  2279  									{
  2280  										Begin: bgzf.Offset{File: 1, Block: 0},
  2281  										End:   bgzf.Offset{File: 2, Block: 0},
  2282  									},
  2283  									{
  2284  										Begin: bgzf.Offset{File: 0x4ffff, Block: 0},
  2285  										End:   bgzf.Offset{File: 0x50000, Block: 0},
  2286  									},
  2287  								},
  2288  							},
  2289  						},
  2290  					},
  2291  				},
  2292  			}}
  2293  		},
  2294  		compStrat: index.CompressorStrategy(0x20000),
  2295  		expectCompress: &Index{idx: internal.Index{
  2296  			Refs: []internal.RefIndex{
  2297  				{
  2298  					Bins: []internal.Bin{
  2299  						{
  2300  							Bin: 0,
  2301  							Chunks: []bgzf.Chunk{
  2302  								{
  2303  									Begin: bgzf.Offset{File: 1, Block: 0},
  2304  									End:   bgzf.Offset{File: 0x10000, Block: 0},
  2305  								},
  2306  							},
  2307  						},
  2308  						{
  2309  							Bin: 1,
  2310  							Chunks: []bgzf.Chunk{
  2311  								{
  2312  									Begin: bgzf.Offset{File: 1, Block: 0},
  2313  									End:   bgzf.Offset{File: 2, Block: 0},
  2314  								},
  2315  								{
  2316  									Begin: bgzf.Offset{File: 0x4ffff, Block: 0},
  2317  									End:   bgzf.Offset{File: 0x50000, Block: 0},
  2318  								},
  2319  							},
  2320  						},
  2321  					},
  2322  				},
  2323  			},
  2324  		}},
  2325  	},
  2326  }
  2327  
  2328  func (s *S) TestMergeChunks(c *check.C) {
  2329  	var bai *Index
  2330  	for _, test := range chunkMergeTests {
  2331  		if test.expectAdjacent != nil {
  2332  			bai = test.index()
  2333  			bai.MergeChunks(index.Adjacent)
  2334  			c.Check(bai, check.DeepEquals, test.expectAdjacent)
  2335  		}
  2336  
  2337  		if test.expectSquash != nil {
  2338  			bai = test.index()
  2339  			bai.MergeChunks(index.Squash)
  2340  			c.Check(bai, check.DeepEquals, test.expectSquash)
  2341  		}
  2342  
  2343  		if test.expectCompress != nil {
  2344  			bai = test.index()
  2345  			bai.MergeChunks(test.compStrat)
  2346  			c.Check(bai, check.DeepEquals, test.expectCompress)
  2347  		}
  2348  	}
  2349  }
  2350  
  2351  func (s *S) TestIndexRoundtrip(c *check.C) {
  2352  	for i, test := range baiTestData {
  2353  		expect := test.expect
  2354  		var buf bytes.Buffer
  2355  		c.Assert(WriteIndex(&buf, expect), check.Equals, nil)
  2356  		got, err := ReadIndex(&buf)
  2357  		c.Assert(err, check.Equals, nil, check.Commentf("Test %d", i))
  2358  		c.Check(got, check.DeepEquals, expect, check.Commentf("Test %d", i))
  2359  	}
  2360  }
  2361  
  2362  // TODO(saito) Enable
  2363  // var fuzzCrashers = []string{
  2364  // 	// lText
  2365  // 	"BAM\x01000\x86",
  2366  // 	"BAM\x01\x00\x00\x00v",
  2367  // 	"BAM\x01000\xef",
  2368  
  2369  // 	// nRef
  2370  // 	"BAM\x01\x00\x00\x00\x00000\xbd",
  2371  // 	"BAM\x01\x00\x00\x00\x000000",
  2372  // 	"BAM\x01\x00\x00\x00\x000000\x00\x00\x00\x000",
  2373  // 	"BAM\x01\x00\x00\x00\x00000\xbf",
  2374  
  2375  // 	// lName
  2376  // 	"BAM\x01\x00\x00\x00\x000000\x00\x00\x00\x000",
  2377  // 	"BAM\x01\x00\x00\x00\x00000\xbf",
  2378  
  2379  // 	//reader.go 412
  2380  // 	"BAM\x01\xbf\xbdC_t\x0efRRUAe\x80t.V",
  2381  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00000\xbf" +
  2382  // 		"e.Ce&Cell",
  2383  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00000\xe9",
  2384  
  2385  // 	// Zero size buffer.
  2386  // 	"BAM\x01\x00\x00\x00\x00\x00\x9f7R",
  2387  // 	// Negative size buffer
  2388  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
  2389  
  2390  // 	// Short reads.
  2391  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x000",
  2392  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x000000" +
  2393  // 		"0000",
  2394  
  2395  // 	// Invalid aux tags.
  2396  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x000000" +
  2397  // 		"000000000000000\xbd0000" +
  2398  // 		"0000",
  2399  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x000000" +
  2400  // 		"0000\x04000\x01\x0000\x00\x00\x00\x000000" +
  2401  // 		"000000000000000000\x000" +
  2402  // 		"0",
  2403  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00 \r\n\xbd" +
  2404  // 		"\xff\xff\xff\xff\aun\x00\x00\x00\u007f\x00\x00\x00\x00\x00\x00\u007f\x00\x00" +
  2405  // 		"\x00 \r\n\xbd\xffxpect\\<invalid" +
  2406  // 		" ",
  2407  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x000000" +
  2408  // 		"0000\x01000\x00\x0000\x00\x00\x00\x000000" +
  2409  // 		"00000000000000000000" +
  2410  // 		"0",
  2411  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x000000" +
  2412  // 		"0000\x06000\x01\x0000\x00\x00\x00\x000000" +
  2413  // 		"00000000000000000000" +
  2414  // 		"n",
  2415  // 	"BAM\x01\x00\x00ewline;�\xbf\xb2\x10e" +
  2416  // 		"�\x16\x00\x00\x00\x00\x00\xbf89rf",
  2417  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x000000" +
  2418  // 		"0000\x01000\x00\x0000\x00\x00\x00\x000000" +
  2419  // 		"00000000000\\00000000" +
  2420  // 		"0",
  2421  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x000000" +
  2422  // 		"0000\a000\x00\x0000\x00\x00\x00\x000000" +
  2423  // 		"00000000000000000\b00" +
  2424  // 		"0",
  2425  // 	"BAM\x01\x00\x00ewline;�\xbf\xb2\x10e" +
  2426  // 		"�\x16\x00\x00\x00\x00\x00\xbf89rf",
  2427  
  2428  // 	// lSeq overflow.
  2429  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x000000" +
  2430  // 		"000000000000\xff\xff\xff\u007f0000" +
  2431  // 		"00000000000000000000" +
  2432  // 		"00000000",
  2433  
  2434  // 	// B-type aux data length overflow.
  2435  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x000000" +
  2436  // 		"0000\x01000\x01\x0000\x00\x00\x00\x000000" +
  2437  // 		"000000000000000BC000" +
  2438  // 		"00000000",
  2439  // 	"BAM\x01\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x000000" +
  2440  // 		"0000\x02000\x01\x0000\x00\x00\x00\x000000" +
  2441  // 		"0000000000000000BB00" +
  2442  // 		"00000000000000000000",
  2443  // }
  2444  
  2445  // func TestFuzzCrashers(t *testing.T) {
  2446  // 	for i, test := range fuzzCrashers {
  2447  // 		func() {
  2448  // 			i := i
  2449  // 			defer func() {
  2450  // 				r := recover()
  2451  // 				if r != nil {
  2452  // 					t.Errorf("unexpected panic for crasher %d: %v", i, r)
  2453  // 				}
  2454  // 			}()
  2455  // 			var buf bytes.Buffer
  2456  // 			w := bgzf.NewWriter(&buf, 1)
  2457  // 			_, err := w.Write([]byte(test))
  2458  // 			if err != nil {
  2459  // 				t.Errorf("unexpected error preparing buffer: %v", err)
  2460  // 			}
  2461  // 			err = w.Close()
  2462  // 			if err != nil {
  2463  // 				t.Errorf("unexpected error closing buffer: %v", err)
  2464  // 			}
  2465  
  2466  // 			r, err := NewReader(&buf, 1)
  2467  // 			if err != nil {
  2468  // 				return
  2469  // 			}
  2470  // 			for {
  2471  // 				_, err := r.Read()
  2472  // 				if err != nil {
  2473  // 					break
  2474  // 				}
  2475  // 			}
  2476  // 		}()
  2477  // 	}
  2478  // }