github.com/biogo/biogo@v1.0.4/seq/sequtils/utils_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 sequtils 6 7 import ( 8 "fmt" 9 "reflect" 10 "testing" 11 12 "github.com/biogo/biogo/alphabet" 13 "github.com/biogo/biogo/feat" 14 "github.com/biogo/biogo/seq" 15 "gopkg.in/check.v1" 16 ) 17 18 // Tests 19 func Test(t *testing.T) { check.TestingT(t) } 20 21 type S struct{} 22 23 var _ = check.Suite(&S{}) 24 25 var ( 26 lorem = stringToSlice("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") 27 ) 28 29 type slice []byte 30 31 func stringToSlice(s string) slice { 32 return []byte(s) 33 } 34 func (s slice) Make(len, cap int) alphabet.Slice { return make(slice, len, cap) } 35 func (s slice) Len() int { return len(s) } 36 func (s slice) Cap() int { return cap(s) } 37 func (s slice) Slice(start, end int) alphabet.Slice { return s[start:end] } 38 func (s slice) Append(a alphabet.Slice) alphabet.Slice { return append(s, a.(slice)...) } 39 func (s slice) Copy(a alphabet.Slice) int { return copy(s, a.(slice)) } 40 41 type offSlice struct { 42 slice 43 offset int 44 conf feat.Conformation 45 } 46 47 func stringToOffSlice(s string) *offSlice { 48 return &offSlice{slice: stringToSlice(s)} 49 } 50 func (os *offSlice) Conformation() feat.Conformation { return os.conf } 51 func (os *offSlice) SetOffset(o int) error { os.offset = o; return nil } 52 func (os *offSlice) Slice() alphabet.Slice { return os.slice } 53 func (os *offSlice) SetSlice(sl alphabet.Slice) { os.slice = sl.(slice) } 54 func (os *offSlice) String() string { return fmt.Sprintf("%s %d", os.slice, os.offset) } 55 56 type conformRangeOffSlice struct { 57 slice 58 offset int 59 conf feat.Conformation 60 } 61 62 func stringToConformRangeOffSlice(s string) *conformRangeOffSlice { 63 return &conformRangeOffSlice{slice: stringToSlice(s)} 64 } 65 func (os *conformRangeOffSlice) Conformation() feat.Conformation { return os.conf } 66 func (os *conformRangeOffSlice) SetConformation(c feat.Conformation) { os.conf = c } 67 func (os *conformRangeOffSlice) SetOffset(o int) error { os.offset = o; return nil } 68 func (os *conformRangeOffSlice) Start() int { return os.offset } 69 func (os *conformRangeOffSlice) End() int { return os.offset + len(os.slice) } 70 func (os *conformRangeOffSlice) Slice() alphabet.Slice { return os.slice } 71 func (os *conformRangeOffSlice) SetSlice(sl alphabet.Slice) { os.slice = sl.(slice) } 72 func (os *conformRangeOffSlice) String() string { return fmt.Sprintf("%s", os.slice) } 73 74 func (s *S) TestTruncate(c *check.C) { 75 type test struct { 76 in *conformRangeOffSlice 77 start, end int 78 expect interface{} 79 } 80 81 var T []test = []test{ 82 { 83 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear}, 84 start: 28, 85 end: 39, 86 expect: stringToSlice("consectetur"), 87 }, 88 { 89 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 1}, 90 start: 29, 91 end: 40, 92 expect: stringToSlice("consectetur"), 93 }, 94 { 95 in: &conformRangeOffSlice{slice: lorem, conf: feat.Circular}, 96 start: 28, 97 end: 39, 98 expect: stringToSlice("consectetur"), 99 }, 100 { 101 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear}, 102 start: 117, 103 end: 5, 104 expect: "sequtils: start position greater than end position for linear sequence", 105 }, 106 { 107 in: &conformRangeOffSlice{slice: lorem, conf: feat.Circular}, 108 start: 117, 109 end: 5, 110 expect: stringToSlice("aliqua.Lorem"), 111 }, 112 { 113 in: &conformRangeOffSlice{slice: lorem, conf: feat.Circular, offset: 1}, 114 start: 118, 115 end: 6, 116 expect: stringToSlice("aliqua.Lorem"), 117 }, 118 { 119 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear}, 120 start: 5, 121 end: 1170, 122 expect: "sequtils: index out of range", 123 }, 124 { 125 in: &conformRangeOffSlice{slice: lorem, conf: feat.Circular}, 126 start: 1170, 127 end: 5, 128 expect: "sequtils: index out of range", 129 }, 130 } 131 132 for _, t := range T { 133 r := &conformRangeOffSlice{} 134 if err := Truncate(r, t.in, t.start, t.end); err != nil { 135 c.Check(err, check.ErrorMatches, t.expect) 136 } else { 137 c.Check(r.slice, check.DeepEquals, t.expect) 138 c.Check(r.conf, check.Equals, feat.Linear) 139 if t.in.conf != feat.Circular || (t.in.conf == feat.Circular && t.end >= t.start) { 140 c.Check(t.end-t.start, check.Equals, reflect.ValueOf(t.expect).Len()) 141 } else { 142 c.Check(t.end+reflect.ValueOf(t.in.slice).Len()-t.start, check.Equals, reflect.ValueOf(t.expect).Len()) 143 } 144 } 145 } 146 } 147 148 func (s *S) TestJoin(c *check.C) { 149 type test struct { 150 a, b *offSlice 151 where int 152 expect *offSlice 153 } 154 155 var T []test = []test{ 156 { 157 a: &offSlice{lorem[28:40], 0, feat.Linear}, 158 b: &offSlice{lorem[117:], 0, feat.Linear}, 159 where: seq.Start, 160 expect: &offSlice{stringToSlice("aliqua.consectetur "), -7, feat.Linear}, 161 }, 162 { 163 a: &offSlice{lorem[28:40], 0, feat.Linear}, 164 b: &offSlice{lorem[117:], 0, feat.Linear}, 165 where: seq.End, 166 expect: &offSlice{stringToSlice("consectetur aliqua."), 0, feat.Linear}, 167 }, 168 } 169 170 for _, t := range T { 171 Join(t.a, t.b, t.where) 172 c.Check(t.a, check.DeepEquals, t.expect) 173 } 174 } 175 176 type fe struct { 177 s, e int 178 orient feat.Orientation 179 feat.Feature 180 } 181 182 func (f fe) Start() int { return f.s } 183 func (f fe) End() int { return f.e } 184 func (f fe) Len() int { return f.e - f.s } 185 func (f fe) Orientation() feat.Orientation { return f.orient } 186 187 type fs []feat.Feature 188 189 func (f fs) Features() []feat.Feature { return []feat.Feature(f) } 190 191 func (s *S) TestStitch(c *check.C) { 192 type test struct { 193 in *conformRangeOffSlice 194 f feat.Set 195 expect interface{} 196 } 197 198 var T []test = []test{ 199 { 200 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 201 f: fs{fe{s: 12, e: 18}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 202 expect: stringToSlice("dolor et dolore"), 203 }, 204 { 205 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: -1}, 206 f: fs{fe{s: 12, e: 18}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 207 expect: stringToSlice("olor st,dolore "), 208 }, 209 { 210 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 211 f: fs{fe{s: 12, e: 18}, fe{s: 13, e: 17}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 212 expect: stringToSlice("dolor et dolore"), 213 }, 214 { 215 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: -1}, 216 f: fs{fe{s: 12, e: 18}, fe{s: 13, e: 17}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 217 expect: stringToSlice("olor st,dolore "), 218 }, 219 { 220 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 221 f: fs{fe{s: 19, e: 18}}, 222 expect: "sequtils: feature end < feature start", 223 }, 224 } 225 226 for _, t := range T { 227 r := &conformRangeOffSlice{} 228 if err := Stitch(r, t.in, t.f); err != nil { 229 c.Check(err, check.ErrorMatches, t.expect) 230 } else { 231 c.Check(r.slice, check.DeepEquals, t.expect) 232 } 233 } 234 } 235 236 func (s *S) TestCompose(c *check.C) { 237 type test struct { 238 in *conformRangeOffSlice 239 f feat.Set 240 expect interface{} 241 } 242 243 var T []test = []test{ 244 { 245 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 246 f: fs{fe{s: 12, e: 18}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 247 expect: stringToSlice("dolor et dolore"), 248 }, 249 { 250 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: -1}, 251 f: fs{fe{s: 12, e: 18}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 252 expect: stringToSlice("olor st,dolore "), 253 }, 254 { 255 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 256 f: fs{fe{s: 12, e: 18}, fe{s: 13, e: 17}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 257 expect: stringToSlice("dolor oloret dolore"), 258 }, 259 { 260 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: -1}, 261 f: fs{fe{s: 12, e: 18}, fe{s: 13, e: 17}, fe{s: 24, e: 26}, fe{s: 103, e: 110}}, 262 expect: stringToSlice("olor slor t,dolore "), 263 }, 264 { 265 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: -1}, 266 f: fs{fe{s: 12, e: 18}, fe{s: 13, e: 17}, fe{s: 24, e: 26, orient: feat.Reverse}, fe{s: 103, e: 110}}, 267 expect: "sequtils: unable to reverse segment during compose", 268 }, 269 { 270 in: &conformRangeOffSlice{slice: lorem, conf: feat.Linear, offset: 0}, 271 f: fs{fe{s: 19, e: 18}}, 272 expect: "sequtils: feature end < feature start", 273 }, 274 } 275 276 for _, t := range T { 277 r := &conformRangeOffSlice{} 278 if err := Compose(r, t.in, t.f); err == nil { 279 c.Check(r.slice, check.DeepEquals, t.expect) 280 } else { 281 c.Check(err, check.ErrorMatches, t.expect) 282 } 283 } 284 }