github.com/biogo/biogo@v1.0.4/io/featio/bed/bed_test.go (about)

     1  // Copyright ©2011-2012 The bíogo Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package bed
     6  
     7  import (
     8  	"github.com/biogo/biogo/feat"
     9  	"github.com/biogo/biogo/seq"
    10  
    11  	"bytes"
    12  	"fmt"
    13  	"image/color"
    14  	"strings"
    15  	"testing"
    16  
    17  	"gopkg.in/check.v1"
    18  )
    19  
    20  var (
    21  	validBeds = []int{3, 4, 5, 6, 12}
    22  	bedTests  = []struct {
    23  		fields    int
    24  		line      string
    25  		skipWrite bool // We do not trail with commas on lists, but we do handle them on read.
    26  		beds      []Bed
    27  	}{
    28  		{
    29  			3, "chr1	11873	14409\n", false,
    30  			[]Bed{
    31  				&Bed3{"chr1", 11873, 14409},
    32  			},
    33  		},
    34  		{
    35  			4, "chr1	11873	14409	uc001aaa.3\n", false,
    36  			[]Bed{
    37  				&Bed3{"chr1", 11873, 14409},
    38  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    39  			},
    40  		},
    41  		{
    42  			5, "chr1	11873	14409	uc001aaa.3	3\n", false,
    43  			[]Bed{
    44  				&Bed3{"chr1", 11873, 14409},
    45  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    46  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    47  			},
    48  		},
    49  		{
    50  			6, "chr1	11873	14409	uc001aaa.3	3	+\n", false,
    51  			[]Bed{
    52  				&Bed3{"chr1", 11873, 14409},
    53  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    54  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    55  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus},
    56  			},
    57  		},
    58  		{
    59  			6, "chr1	11873	14409	uc001aaa.3	3	-\n", false,
    60  			[]Bed{
    61  				&Bed3{"chr1", 11873, 14409},
    62  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    63  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    64  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Minus},
    65  			},
    66  		},
    67  		{
    68  			6, "chr1	11873	14409	uc001aaa.3	3	.\n", false,
    69  			[]Bed{
    70  				&Bed3{"chr1", 11873, 14409},
    71  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    72  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    73  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.None},
    74  			},
    75  		},
    76  		{
    77  			12, "chr1	11873	14409	uc001aaa.3	3	+	11873	11873	0	3	354,109,1189,	0,739,1347,\n", true,
    78  			[]Bed{
    79  				&Bed3{"chr1", 11873, 14409},
    80  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    81  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    82  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus},
    83  				&Bed12{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus, 11873, 11873, color.RGBA{}, 3, []int{354, 109, 1189}, []int{0, 739, 1347}},
    84  			},
    85  		},
    86  		{
    87  			12, "chr1	11873	14409	uc001aaa.3	3	+	11873	11873	255,128,0	3	354,109,1189,	0,739,1347,\n", true,
    88  			[]Bed{
    89  				&Bed3{"chr1", 11873, 14409},
    90  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
    91  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
    92  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus},
    93  				&Bed12{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus, 11873, 11873, color.RGBA{255, 128, 0, 255}, 3, []int{354, 109, 1189}, []int{0, 739, 1347}},
    94  			},
    95  		},
    96  		{
    97  			12, "chr1	11873	14409	uc001aaa.3	3	+	11873	11873	0	3	354,109,1189	0,739,1347\n", false,
    98  			[]Bed{
    99  				&Bed3{"chr1", 11873, 14409},
   100  				&Bed4{"chr1", 11873, 14409, "uc001aaa.3"},
   101  				&Bed5{"chr1", 11873, 14409, "uc001aaa.3", 3},
   102  				&Bed6{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus},
   103  				&Bed12{"chr1", 11873, 14409, "uc001aaa.3", 3, seq.Plus, 11873, 11873, color.RGBA{}, 3, []int{354, 109, 1189}, []int{0, 739, 1347}},
   104  			},
   105  		},
   106  	}
   107  )
   108  
   109  // Tests
   110  func Test(t *testing.T) { check.TestingT(t) }
   111  
   112  type S struct{}
   113  
   114  var _ = check.Suite(&S{})
   115  
   116  func (s *S) TestUnsafeString(c *check.C) {
   117  	for _, t := range []string{
   118  		"I",
   119  		"Lorem",
   120  		"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
   121  	} {
   122  		b := []byte(t)
   123  		c.Check(unsafeString(b), check.Equals, t)
   124  	}
   125  }
   126  
   127  func (s *S) TestReadBed(c *check.C) {
   128  	for i, b := range bedTests {
   129  		for j, typ := range validBeds {
   130  			buf := strings.NewReader(b.line)
   131  			r, err := NewReader(buf, typ)
   132  			c.Assert(err, check.Equals, nil)
   133  			f, err := r.Read()
   134  			if typ <= b.fields {
   135  				c.Check(f, check.DeepEquals, b.beds[j], check.Commentf("Test: %d type: Bed%d", i, typ))
   136  				c.Check(err, check.Equals, nil)
   137  			} else {
   138  				c.Check(f, check.Equals, nil)
   139  				c.Check(err, check.ErrorMatches, fmt.Sprintf("%s.*", ErrBadBedType), check.Commentf("Test: %d type: Bed%d", i, typ))
   140  			}
   141  		}
   142  	}
   143  }
   144  
   145  func (s *S) TestWriteBed(c *check.C) {
   146  	for i, b := range bedTests {
   147  		for _, typ := range validBeds {
   148  			buf := &bytes.Buffer{}
   149  			w, err := NewWriter(buf, typ)
   150  			c.Assert(err, check.Equals, nil)
   151  			n, err := w.Write(b.beds[len(b.beds)-1])
   152  			c.Check(n, check.Equals, buf.Len())
   153  			if typ <= b.fields {
   154  				trunc := strings.Join(strings.Split(b.line, "\t")[:typ], "\t")
   155  				if trunc[len(trunc)-1] != '\n' {
   156  					trunc += "\n"
   157  				}
   158  				c.Check(err, check.Equals, nil)
   159  				if !b.skipWrite {
   160  					c.Check(buf.String(), check.Equals, trunc, check.Commentf("Test: %d type: Bed%d", i, typ))
   161  				}
   162  			} else {
   163  				c.Check(buf.String(), check.Equals, "")
   164  				c.Check(err, check.ErrorMatches, fmt.Sprintf("%s.*", ErrBadBedType), check.Commentf("Test: %d type: Bed%d", i, typ))
   165  			}
   166  		}
   167  	}
   168  }
   169  
   170  type tf struct {
   171  	chrom      feat.Feature
   172  	start, end int
   173  	name       string
   174  }
   175  
   176  func (f *tf) Start() int { return f.start }
   177  func (f *tf) End() int   { return f.end }
   178  func (f *tf) Len() int   { return f.end - f.start }
   179  func (f *tf) Name() string {
   180  	if f.name == "" {
   181  		return fmt.Sprintf("%s", f.chrom)
   182  	}
   183  	return f.name
   184  }
   185  func (f *tf) Description() string    { return "test feat" }
   186  func (f *tf) Location() feat.Feature { return f.chrom }
   187  
   188  type sctf struct {
   189  	tf
   190  	score int
   191  }
   192  
   193  func (f *sctf) Score() int { return f.score }
   194  
   195  type sttf struct {
   196  	tf
   197  	strand seq.Strand
   198  }
   199  
   200  func (f *sttf) Orientation() feat.Orientation { return feat.Orientation(f.strand) }
   201  
   202  type ctf struct {
   203  	tf
   204  	score  int
   205  	strand seq.Strand
   206  }
   207  
   208  func (f *ctf) Score() int                    { return f.score }
   209  func (f *ctf) Orientation() feat.Orientation { return feat.Orientation(f.strand) }
   210  
   211  func (s *S) TestWriteFeature(c *check.C) {
   212  	for i, f := range []struct {
   213  		feat feat.Feature
   214  		typ  int
   215  		line string
   216  		err  error
   217  	}{
   218  		// Vanilla feature.
   219  		{
   220  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99}, 3,
   221  			"test chrom\t1\t99\n", nil,
   222  		},
   223  		{
   224  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, 3,
   225  			"test chrom\t1\t99\n", nil,
   226  		},
   227  		{
   228  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, 4,
   229  			"test chrom\t1\t99\ttest feat\n", nil,
   230  		},
   231  		{
   232  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, 5,
   233  			"test chrom\t1\t99\ttest feat\t0\n", nil,
   234  		},
   235  		{
   236  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, 6,
   237  			"test chrom\t1\t99\ttest feat\t0\t.\n", nil,
   238  		},
   239  		{
   240  			&tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, 12,
   241  			"test chrom\t1\t99\ttest feat\t0\t.\n", ErrBadBedType,
   242  		},
   243  
   244  		// Scorer.
   245  		{
   246  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99}, score: 100}, 3,
   247  			"test chrom\t1\t99\n", nil,
   248  		},
   249  		{
   250  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100}, 3,
   251  			"test chrom\t1\t99\n", nil,
   252  		},
   253  		{
   254  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100}, 4,
   255  			"test chrom\t1\t99\ttest feat\n", nil,
   256  		},
   257  		{
   258  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100}, 5,
   259  			"test chrom\t1\t99\ttest feat\t100\n", nil,
   260  		},
   261  		{
   262  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100}, 6,
   263  			"test chrom\t1\t99\ttest feat\t100\t.\n", nil,
   264  		},
   265  		{
   266  			&sctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100}, 12,
   267  			"test chrom\t1\t99\ttest feat\t100\t.\n", ErrBadBedType,
   268  		},
   269  
   270  		// feat.Orientater.
   271  		{
   272  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99}, strand: +1}, 3,
   273  			"test chrom\t1\t99\n", nil,
   274  		},
   275  		{
   276  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, strand: +1}, 3,
   277  			"test chrom\t1\t99\n", nil,
   278  		},
   279  		{
   280  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, strand: +1}, 4,
   281  			"test chrom\t1\t99\ttest feat\n", nil,
   282  		},
   283  		{
   284  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, strand: +1}, 5,
   285  			"test chrom\t1\t99\ttest feat\t0\n", nil,
   286  		},
   287  		{
   288  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, strand: +1}, 6,
   289  			"test chrom\t1\t99\ttest feat\t0\t+\n", nil,
   290  		},
   291  		{
   292  			&sttf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, strand: +1}, 12,
   293  			"test chrom\t1\t99\ttest feat\t0\t+\n", ErrBadBedType,
   294  		},
   295  
   296  		// Complete.
   297  		{
   298  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99}, score: 100, strand: +1}, 3,
   299  			"test chrom\t1\t99\n", nil,
   300  		},
   301  		{
   302  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100, strand: +1}, 3,
   303  			"test chrom\t1\t99\n", nil,
   304  		},
   305  		{
   306  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100, strand: +1}, 4,
   307  			"test chrom\t1\t99\ttest feat\n", nil,
   308  		},
   309  		{
   310  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100, strand: +1}, 5,
   311  			"test chrom\t1\t99\ttest feat\t100\n", nil,
   312  		},
   313  		{
   314  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100, strand: +1}, 6,
   315  			"test chrom\t1\t99\ttest feat\t100\t+\n", nil,
   316  		},
   317  		{
   318  			&ctf{tf: tf{chrom: Chrom("test chrom"), start: 1, end: 99, name: "test feat"}, score: 100, strand: +1}, 12,
   319  			"test chrom\t1\t99\ttest feat\t100\t+\n", ErrBadBedType,
   320  		},
   321  	} {
   322  		buf := &bytes.Buffer{}
   323  		w, err := NewWriter(buf, f.typ)
   324  		c.Assert(err, check.Equals, nil)
   325  		n, err := w.Write(f.feat)
   326  		c.Check(n, check.Equals, buf.Len())
   327  		c.Check(err, check.Equals, f.err)
   328  		c.Check(buf.String(), check.Equals, f.line, check.Commentf("Test: %d type: Bed%d", i, f.typ))
   329  	}
   330  }