]> git.donarmstrong.com Git - biopieces.git/blob - code_ruby/test/maasha/test_seq.rb
bbb6759277359c0254275cc92101bd00c113abe6
[biopieces.git] / code_ruby / test / maasha / test_seq.rb
1 #!/usr/bin/env ruby
2 $:.unshift File.join(File.dirname(__FILE__), '..', '..')
3
4 # Copyright (C) 2011 Martin A. Hansen.
5
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 # http://www.gnu.org/copyleft/gpl.html
21
22 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
23
24 # This software is part of the Biopieces framework (www.biopieces.org).
25
26 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
27
28 require 'maasha/seq'
29 require 'test/unit'
30 require 'test/helper'
31
32 class TestSeq < Test::Unit::TestCase 
33   def setup
34     @entry = Seq.new
35   end
36
37   test "Seq.new_bp returns correctly" do
38     record = {:SEQ_NAME => "test", :SEQ => "ATCG", :SEQ_TYPE => :dna, :SCORES => "hhhh"}
39     seq    = Seq.new_bp(record)
40     assert_equal("test", seq.seq_name)
41     assert_equal("ATCG", seq.seq)
42     assert_equal(:dna,  seq.type)
43     assert_equal("hhhh", seq.qual)
44   end
45
46   test "#is_dna? with no sequence type returns false" do
47     assert(@entry.is_dna? == false)
48   end
49
50   test "#is_dna? with dna sequence type returns true" do
51     @entry.type = :dna
52     assert(@entry.is_dna? == true)
53   end
54
55   test "#is_rna? with no sequence type returns false" do
56     assert(@entry.is_rna? == false)
57   end
58
59   test "#is_rna? with rna sequence type returns true" do
60     @entry.type = :rna
61     assert(@entry.is_rna? == true)
62   end
63
64   test "#is_protein? with no sequence type returns false" do
65     assert(@entry.is_protein? == false)
66   end
67
68   test "#is_protein? with protein sequence type returns true" do
69     @entry.type = :protein
70     assert_equal(true, @entry.is_protein?)
71   end
72
73   test "#type_guess without sequence raises" do
74     assert_raise(SeqError) { @entry.type_guess }
75   end
76
77   test "#type_guess with protein returns protein" do
78     @entry.seq = 'atcatcrFgatcg'
79     assert_equal(:protein, @entry.type_guess)
80   end
81
82   test "#type_guess with rna returns rna" do
83     @entry.seq = 'atcatcrUgatcg'
84     assert_equal(:rna, @entry.type_guess)
85   end
86
87   test "#type_guess with dna returns dna" do
88     @entry.seq = 'atcatcgatcg'
89     assert_equal(:dna, @entry.type_guess)
90   end
91
92   test "#type_guess! without sequence raises" do
93     assert_raise(SeqError) { @entry.type_guess! }
94   end
95
96   test "#type_guess! with protein returns protein" do
97     @entry.seq = 'atcatcrFgatcg'
98     @entry.type_guess!
99     assert_equal(:protein, @entry.type)
100   end
101
102   test "#type_guess! with rna returns rna" do
103     @entry.seq = 'atcatcrUgatcg'
104     @entry.type_guess!
105     assert_equal(:rna, @entry.type)
106   end
107
108   test "#type_guess! with dna returns dna" do
109     @entry.seq = 'atcatcgatcg'
110     @entry.type_guess!
111     assert_equal(:dna, @entry.type)
112   end
113
114   test "#length returns corretly" do
115     @entry.seq = 'ATCG'
116     assert_equal(4, @entry.length)
117   end
118
119   test "#indels returns correctly" do
120     @entry.seq = 'ATCG.-~_'
121     assert_equal(4, @entry.indels)
122   end
123
124   test "#to_rna with no sequence raises" do
125     @entry.type = :dna
126     assert_raise(SeqError) { @entry.to_rna }
127   end
128
129   test "#to_rna with bad type raises" do
130     @entry.seq  = 'ATCG'
131     @entry.type = :rna
132     assert_raise(SeqError) { @entry.to_rna }
133   end
134
135   test "#to_rna transcribes correctly" do
136     @entry.seq  = 'ATCGatcg'
137     @entry.type = :dna
138     assert_equal("AUCGaucg", @entry.to_rna)
139   end
140
141   test "#to_rna changes entry type to rna" do
142     @entry.seq  = 'ATCGatcg'
143     @entry.type = :dna
144     @entry.to_rna
145     assert_equal(:rna, @entry.type)
146   end
147
148   test "#to_dna with no sequence raises" do
149     @entry.type = :rna
150     assert_raise(SeqError) { @entry.to_dna }
151   end
152
153   test "#to_dna with bad type raises" do
154     @entry.seq  = 'AUCG'
155     @entry.type = :dna
156     assert_raise(SeqError) { @entry.to_dna }
157   end
158
159   test "#to_dna transcribes correctly" do
160     @entry.seq  = 'AUCGaucg'
161     @entry.type = :rna
162     assert_equal("ATCGatcg", @entry.to_dna)
163   end
164
165   test "#to_dna changes entry type to dna" do
166     @entry.seq  = 'AUCGaucg'
167     @entry.type = :rna
168     @entry.to_dna
169     assert_equal(:dna, @entry.type)
170   end
171
172   test "#to_bp returns correct record" do
173     @entry.seq_name = 'test'
174     @entry.seq      = 'ATCG'
175     assert_equal({:SEQ_NAME=>"test", :SEQ=>"ATCG", :SEQ_LEN=>4}, @entry.to_bp)
176   end
177
178   test "#to_bp with missing seq_name raises" do
179     @entry.seq = 'ATCG'
180     assert_raise(SeqError) { @entry.to_bp }
181   end
182
183   test "#to_bp with missing sequence raises" do
184     @entry.seq_name = 'test'
185     assert_raise(SeqError) { @entry.to_bp }
186   end
187
188   test "#to_fasta with missing seq_name raises" do
189     @entry.seq = 'ATCG'
190     assert_raise(SeqError) { @entry.to_fasta }
191   end
192
193   test "#to_fasta with empty seq_name raises" do
194     @entry.seq_name = ''
195     @entry.seq      = 'ATCG'
196     assert_raise(SeqError) { @entry.to_fasta }
197   end
198
199   test "#to_fasta with missing seq raises" do
200     @entry.seq_name = 'test'
201     assert_raise(SeqError) { @entry.to_fasta }
202   end
203
204   test "#to_fasta with empty seq raises" do
205     @entry.seq_name = 'test'
206     @entry.seq      = ''
207     assert_raise(SeqError) { @entry.to_fasta }
208   end
209
210   test "#to_fasta returns correct entry" do
211     @entry.seq_name = 'test'
212     @entry.seq      = 'ATCG'
213     assert_equal(">test\nATCG\n", @entry.to_fasta)
214   end
215
216   test "#to_fasta wraps correctly" do
217     entry = Seq.new("test", "ATCG")
218     assert_equal(">test\nAT\nCG\n", entry.to_fasta(2))
219   end
220
221   test "#to_fastq returns correct entry" do
222     @entry.seq_name = 'test'
223     @entry.seq      = 'ATCG'
224     @entry.qual     = 'hhhh'
225     assert_equal("@test\nATCG\n+\nhhhh\n", @entry.to_fastq)
226   end
227
228   test "#to_key with bad residue raises" do
229     entry = Seq.new("test", "AUCG")
230     assert_raise(SeqError) { entry.to_key }
231   end
232
233   test "#to_key returns correctly" do
234     entry = Seq.new("test", "ATCG")
235     assert_equal(54, entry.to_key)
236   end
237
238   test "#reverse returns correctly" do
239     @entry.seq = "ATCG"
240     new_entry  = @entry.reverse
241     assert_equal("GCTA", new_entry.seq)
242     assert_equal("ATCG", @entry.seq)
243   end
244
245   test "#reverse! returns correctly" do
246     @entry.seq = "ATCG"
247     @entry.reverse!
248     assert_equal("GCTA", @entry.seq)
249   end
250
251   test "#complement with no sequence raises" do
252     @entry.type = :dna
253     assert_raise(SeqError) { @entry.complement }
254   end
255
256   test "#complement with bad type raises" do
257     @entry.seq  = 'ATCG'
258     @entry.type = :protein
259     assert_raise(SeqError) { @entry.complement }
260   end
261
262   test "#complement for DNA is correct" do
263     @entry.seq  = 'ATCGatcg'
264     @entry.type = :dna
265     comp        = @entry.complement
266     assert_equal("TAGCtagc", comp.seq)
267     assert_equal("ATCGatcg", @entry.seq)
268   end
269
270   test "#complement for RNA is correct" do
271     @entry.seq  = 'AUCGaucg'
272     @entry.type = :rna
273     comp        = @entry.complement
274     assert_equal("UAGCuagc", comp.seq)
275     assert_equal("AUCGaucg", @entry.seq)
276   end
277
278   test "#complement! with no sequence raises" do
279     @entry.type = :dna
280     assert_raise(SeqError) { @entry.complement! }
281   end
282
283   test "#complement! with bad type raises" do
284     @entry.seq  = 'ATCG'
285     @entry.type = :protein
286     assert_raise(SeqError) { @entry.complement! }
287   end
288
289   test "#complement! for DNA is correct" do
290     @entry.seq  = 'ATCGatcg'
291     @entry.type = :dna
292     assert_equal("TAGCtagc", @entry.complement!.seq)
293   end
294
295   test "#complement! for RNA is correct" do
296     @entry.seq  = 'AUCGaucg'
297     @entry.type = :rna
298     assert_equal("UAGCuagc", @entry.complement!.seq)
299   end
300
301   test "#hamming_distance returns correctly" do
302     seq1 = Seq.new("test1", "ATCG")
303     seq2 = Seq.new("test2", "atgg")
304     assert_equal(1, seq1.hamming_distance(seq2))
305   end
306
307   test "#hamming_distance with ambiguity codes return correctly" do
308     seq1 = Seq.new("test1", "ATCG")
309     seq2 = Seq.new("test2", "atng")
310
311     assert_equal(1, seq1.hamming_distance(seq2))
312     assert_equal(0, seq1.hamming_distance(seq2, ambiguity: true))
313   end
314
315   test "#edit_distance returns correctly" do
316     seq1 = Seq.new("test1", "ATCG")
317     seq2 = Seq.new("test2", "tgncg")
318     assert_equal(2, seq1.edit_distance(seq2))
319   end
320
321   test "#generate with length < 1 raises" do
322     assert_raise(SeqError) { @entry.generate(-10, :dna) }
323     assert_raise(SeqError) { @entry.generate(0, :dna) }
324   end
325
326   test "#generate with bad type raises" do
327     assert_raise(SeqError) { @entry.generate(10, "foo") }
328   end
329
330   test "#generate with ok type dont raise" do
331     %w[dna rna protein].each do |type|
332       assert_nothing_raised { @entry.generate(10, type.to_sym) }
333     end
334   end
335
336   test "#shuffle returns correctly" do
337     orig       = "actgactgactgatcgatcgatcgatcgtactg" 
338     @entry.seq = "actgactgactgatcgatcgatcgatcgtactg"
339     entry_shuf = @entry.shuffle
340     assert_equal(orig, @entry.seq)
341     assert_not_equal(@entry.seq, entry_shuf.seq)
342   end
343
344   test "#shuffle! returns correctly" do
345     @entry.seq = "actgactgactgatcgatcgatcgatcgtactg"
346     assert_not_equal(@entry.seq, @entry.shuffle!.seq)
347   end
348
349   test "#+ without qual returns correctly" do
350     entry = Seq.new("test1", "at") + Seq.new("test2", "cg")
351     assert_nil(entry.seq_name)
352     assert_equal("atcg", entry.seq)
353     assert_nil(entry.type)
354     assert_nil(entry.qual)
355   end
356
357   test "#+ with qual returns correctly" do
358     entry = Seq.new("test1", "at", :dna, "II") + Seq.new("test2", "cg", :dna, "JJ")
359     assert_nil(entry.seq_name)
360     assert_equal("atcg", entry.seq)
361     assert_equal(:dna,   entry.type)
362     assert_equal("IIJJ", entry.qual)
363   end
364
365   test "#<< with different types raises" do
366     @entry.seq = "atcg"
367     assert_raise(SeqError) { @entry << Seq.new("test", "atcg", :dna) }
368   end
369
370   test "#<< with missing qual in one entry raises" do
371     @entry.seq  = "atcg"
372     @entry.type = :dna
373     assert_raise(SeqError) { @entry << Seq.new("test", "atcg", :dna, "IIII") }
374     @entry.qual = "IIII"
375     assert_raise(SeqError) { @entry << Seq.new("test", "atcg", :dna) }
376   end
377
378   test "#<< with nil qual in both entries dont raise" do
379     @entry.seq = "atcg"
380     assert_nothing_raised { @entry << Seq.new("test", "atcg") }
381   end
382
383   test "#<< with qual in both entries dont raise" do
384     @entry.seq  = "atcg"
385     @entry.type = :dna
386     @entry.qual = "IIII"
387     assert_nothing_raised { @entry << Seq.new("test", "atcg", :dna, "IIII") }
388   end
389
390   test "#<< without qual returns correctly" do
391     @entry.seq  = "atcg"
392     @entry <<  Seq.new("test", "ATCG")
393     assert_equal("atcgATCG", @entry.seq)
394   end
395
396   test "#<< with qual returns correctly" do
397     @entry.seq  = "atcg"
398     @entry.type = :dna
399     @entry.qual = "HHHH"
400     @entry <<  Seq.new("test", "ATCG", :dna, "IIII")
401     assert_equal("atcgATCG", @entry.seq)
402     assert_equal("HHHHIIII", @entry.qual)
403   end
404
405   test "#[] with qual returns correctly" do
406     entry = Seq.new("test", "atcg", :dna, "FGHI")
407
408     e = entry[2]
409
410     assert_equal("test", e.seq_name)
411     assert_equal("c",    e.seq)
412     assert_equal(:dna,   e.type)
413     assert_equal("H",    e.qual)
414     assert_equal("atcg", entry.seq)
415     assert_equal("FGHI", entry.qual)
416   end
417
418   test "#[] without qual returns correctly" do
419     entry = Seq.new("test", "atcg")
420
421     e = entry[2]
422
423     assert_equal("test", e.seq_name)
424     assert_equal("c",    e.seq)
425     assert_nil(e.qual)
426     assert_equal("atcg", entry.seq)
427   end
428
429   test "[]= with qual returns correctly" do
430     entry = Seq.new("test", "atcg", :dna, "FGHI")
431
432     entry[0] = Seq.new("foo", "T", :dna, "I")
433
434     assert_equal("test", entry.seq_name)
435     assert_equal("Ttcg", entry.seq)
436     assert_equal(:dna,   entry.type)
437     assert_equal("IGHI", entry.qual)
438   end
439
440   test "[]= without qual returns correctly" do
441     entry = Seq.new("test", "atcg")
442
443     entry[0] = Seq.new("foo", "T")
444
445     assert_equal("test", entry.seq_name)
446     assert_equal("Ttcg", entry.seq)
447   end
448
449   test "#subseq with start < 0 raises" do
450     @entry.seq = "ATCG"
451     assert_raise(SeqError) { @entry.subseq(-1, 1) }
452   end
453
454   test "#subseq with start plus length gt seq raises" do
455     @entry.seq = "ATCG"
456     assert_raise(SeqError) { @entry.subseq(0, 5) }
457   end
458
459   test "#subseq returns correct sequence" do
460     @entry.seq  = "ATCG"
461     assert_equal("AT", @entry.subseq(0, 2).seq)
462     assert_equal("CG", @entry.subseq(2, 2).seq)
463   end
464
465   test "#subseq without length returns correct sequence" do
466     @entry.seq  = "ATCG"
467     assert_equal("ATCG", @entry.subseq(0).seq)
468     assert_equal("CG",   @entry.subseq(2).seq)
469   end
470
471   test "#subseq returns correct qual" do
472     @entry.seq  = "ATCG"
473     @entry.qual = "abcd"
474     assert_equal("ab", @entry.subseq(0, 2).qual)
475     assert_equal("cd", @entry.subseq(2, 2).qual)
476   end
477
478   test "#subseq without length returns correct qual" do
479     @entry.seq  = "ATCG"
480     @entry.qual = "abcd"
481     assert_equal("abcd", @entry.subseq(0).qual)
482     assert_equal("cd",   @entry.subseq(2).qual)
483   end
484
485   test "#subseq! with start < 0 raises" do
486     @entry.seq = "ATCG"
487     assert_raise(SeqError) { @entry.subseq!(-1, 1) }
488   end
489
490   test "#subseq! with start plus length > seq.length raises" do
491     @entry.seq = "ATCG"
492     assert_raise(SeqError) { @entry.subseq!(0, 5) }
493   end
494
495   test "#subseq! returns correct sequence" do
496     @entry.seq  = "ATCG"
497     @entry.subseq!(0, 2)
498     assert_equal("AT", @entry.seq)
499     @entry.seq  = "ATCG"
500     @entry.subseq!(2, 2)
501     assert_equal("CG", @entry.seq)
502   end
503
504   test "#subseq! without length returns correct sequence" do
505     @entry.seq  = "ATCG"
506     @entry.subseq!(0)
507     assert_equal("ATCG", @entry.seq)
508     @entry.seq  = "ATCG"
509     @entry.subseq!(2)
510     assert_equal("CG", @entry.seq)
511   end
512
513   test "#subseq! with pos and length returns correct qual" do
514     @entry.seq  = "ATCG"
515     @entry.qual = "abcd"
516     @entry.subseq!(0, 2)
517     assert_equal("ab", @entry.qual)
518     @entry.seq  = "ATCG"
519     @entry.qual = "abcd"
520     @entry.subseq!(2, 2)
521     assert_equal("cd", @entry.qual)
522   end
523
524   test "#subseq! with pos returns correct qual" do
525     @entry.seq  = "ATCG"
526     @entry.qual = "abcd"
527     @entry.subseq!(0)
528     assert_equal("abcd", @entry.qual)
529     @entry.seq  = "ATCG"
530     @entry.qual = "abcd"
531     @entry.subseq!(2)
532     assert_equal("cd", @entry.qual)
533   end
534
535   test "#subseq_rand returns correct sequence" do
536     @entry.seq  = "ATCG"
537     assert_equal("ATCG", @entry.subseq_rand(4).seq)
538   end
539
540   test "#indels_remove without qual returns correctly" do
541     @entry.seq  = "A-T.CG~CG"
542     @entry.qual = nil
543     assert_equal("ATCGCG", @entry.indels_remove.seq)
544   end
545
546   test "#indels_remove with qual returns correctly" do
547     @entry.seq  = "A-T.CG~CG"
548     @entry.qual = "a@b@cd@fg"
549     assert_equal("ATCGCG", @entry.indels_remove.seq)
550     assert_equal("abcdfg", @entry.indels_remove.qual)
551   end
552
553   test "#composition returns correctly" do
554     @entry.seq = "AAAATTTCCG"
555     assert_equal(4, @entry.composition["A"])
556     assert_equal(3, @entry.composition["T"])
557     assert_equal(2, @entry.composition["C"])
558     assert_equal(1, @entry.composition["G"])
559     assert_equal(0, @entry.composition["X"])
560   end
561
562   test "#hard_mask returns correctly" do
563     @entry.seq = "--AAAANn"
564     assert_equal(33.33, @entry.hard_mask)
565   end
566
567   test "#soft_mask returns correctly" do
568     @entry.seq = "--AAAa"
569     assert_equal(25.00, @entry.soft_mask)
570   end
571
572   test "#mask_seq_hard! with nil seq raises" do
573     @entry.seq  = nil
574     @entry.qual = ""
575
576     assert_raise(SeqError) { @entry.mask_seq_hard!(20) }
577   end
578
579   test "#mask_seq_hard! with nil qual raises" do
580     @entry.seq  = ""
581     @entry.qual = nil
582
583     assert_raise(SeqError) { @entry.mask_seq_hard!(20) }
584   end
585
586   test "#mask_seq_hard! with bad cutoff raises" do
587     assert_raise(SeqError) { @entry.mask_seq_hard!(-1) }
588     assert_raise(SeqError) { @entry.mask_seq_hard!(41) }
589   end
590
591   test "#mask_seq_hard! with OK cutoff dont raise" do
592     @entry.seq  = "ATCG"
593     @entry.qual = "RSTU"
594
595     assert_nothing_raised { @entry.mask_seq_hard!(0) }
596     assert_nothing_raised { @entry.mask_seq_hard!(40) }
597   end
598
599   test "#mask_seq_hard! returns correctly" do
600     @entry.seq  = "-ATCG"
601     @entry.qual = "33456"
602
603     assert_equal("-NNCG", @entry.mask_seq_hard!(20).seq)
604   end
605
606   test "#mask_seq_soft! with nil seq raises" do
607     @entry.seq  = nil
608     @entry.qual = ""
609
610     assert_raise(SeqError) { @entry.mask_seq_soft!(20) }
611   end
612
613   test "#mask_seq_soft! with nil qual raises" do
614     @entry.seq  = ""
615     @entry.qual = nil
616
617     assert_raise(SeqError) { @entry.mask_seq_soft!(20) }
618   end
619
620   test "#mask_seq_soft! with bad cutoff raises" do
621     assert_raise(SeqError) { @entry.mask_seq_soft!(-1) }
622     assert_raise(SeqError) { @entry.mask_seq_soft!(41) }
623   end
624
625   test "#mask_seq_soft! with OK cutoff dont raise" do
626     @entry.seq  = "ATCG"
627     @entry.qual = "RSTU"
628
629     assert_nothing_raised { @entry.mask_seq_soft!(0) }
630     assert_nothing_raised { @entry.mask_seq_soft!(40) }
631   end
632
633   test "#mask_seq_soft! returns correctly" do
634     @entry.seq  = "-ATCG"
635     @entry.qual = "33456"
636
637     assert_equal("-atCG", @entry.mask_seq_soft!(20).seq)
638   end
639
640   # qual score detection
641
642   test "#qual_base33? returns correctly" do
643     # self.qual.match(/[!-:]/)
644     @entry.qual = '!"#$%&\'()*+,-./0123456789:'
645     assert_equal(true,  @entry.qual_base33? )
646     @entry.qual = 32.chr
647     assert_equal(false, @entry.qual_base33? )
648     @entry.qual = 59.chr
649     assert_equal(false, @entry.qual_base33? )
650   end
651
652   test "#qual_base64? returns correctly" do
653     # self.qual.match(/[K-h]/)
654     @entry.qual = 'KLMNOPQRSTUVWXYZ[\]^_`abcdefgh'
655     assert_equal(true,  @entry.qual_base64? )
656     @entry.qual = 74.chr
657     assert_equal(false, @entry.qual_base64? )
658     @entry.qual = 105.chr
659     assert_equal(false, @entry.qual_base64? )
660   end
661
662   test "#qual_valid? with nil qual raises" do
663     assert_raise(SeqError) { @entry.qual_valid?(:base_33) }
664     assert_raise(SeqError) { @entry.qual_valid?(:base_64) }
665   end
666
667   test "#qual_valid? with bad encoding raises" do
668     @entry.qual = "abc"
669     assert_raise(SeqError) { @entry.qual_valid?("foobar") }
670   end
671
672   test "#qual_valid? with OK range returns correctly" do
673     @entry.qual = ((Seq::SCORE_MIN + 33).chr .. (Seq::SCORE_MAX + 33).chr).to_a.join
674     assert_equal(true,  @entry.qual_valid?(:base_33))
675     @entry.qual = ((Seq::SCORE_MIN + 64).chr .. (Seq::SCORE_MAX + 64).chr).to_a.join
676     assert_equal(true,  @entry.qual_valid?(:base_64))
677   end
678
679   test "#qual_valid? with bad range returns correctly" do
680     @entry.qual = ((Seq::SCORE_MIN + 33 - 1).chr .. (Seq::SCORE_MAX + 33).chr).to_a.join
681     assert_equal(false,  @entry.qual_valid?(:base_33))
682     @entry.qual = ((Seq::SCORE_MIN + 33).chr .. (Seq::SCORE_MAX + 33 + 1).chr).to_a.join
683     assert_equal(false,  @entry.qual_valid?(:base_33))
684
685     @entry.qual = ((Seq::SCORE_MIN + 64 - 1).chr .. (Seq::SCORE_MAX + 64).chr).to_a.join
686     assert_equal(false,  @entry.qual_valid?(:base_64))
687     @entry.qual = ((Seq::SCORE_MIN + 64).chr .. (Seq::SCORE_MAX + 64 + 1).chr).to_a.join
688     assert_equal(false,  @entry.qual_valid?(:base_64))
689   end
690
691   # convert sanger to ...
692
693   test "#qual_convert! from base33 to base33 returns OK" do
694     @entry.qual = 'BCDEFGHI'
695     assert_equal('BCDEFGHI', @entry.qual_convert!(:base_33, :base_33).qual)
696   end
697
698   test "#qual_convert! from base33 to base64 returns OK" do
699     @entry.qual = 'BCDEFGHI'
700     assert_equal('abcdefgh', @entry.qual_convert!(:base_33, :base_64).qual)
701   end
702
703   test "#qual_convert! from base64 to base64 returns OK" do
704     @entry.qual = 'BCDEFGHI'
705     assert_equal('BCDEFGHI', @entry.qual_convert!(:base_64, :base_64).qual)
706   end
707
708   test "#qual_convert! from base64 to base33 returns OK" do
709     @entry.qual = 'abcdefgh'
710     assert_equal('BCDEFGHI', @entry.qual_convert!(:base_64, :base_33).qual)
711   end
712
713   test "#qual_coerce! returns correctly" do
714     @entry.qual = ('!' .. '~').to_a.join
715     assert_equal("!\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII", @entry.qual_coerce!(:base_33).qual)
716     @entry.qual = ('!' .. '~').to_a.join
717     assert_equal("!\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZh\\h^_`abcdefghhhhhhhhhhhhhhhhhhhhhhh", @entry.qual_coerce!(:base_64).qual)
718   end
719
720   test "#scores_mean without qual raises" do
721     @entry.qual = nil
722     assert_raise(SeqError) { @entry.scores_mean }
723   end
724
725   test "#scores_mean returns correctly" do
726     @entry.qual = '!!II'
727     assert_equal(20.0, @entry.scores_mean)
728   end
729 end