package dna import "testing" func (h Histogram) Equal(o Histogram) bool { return h.sameLength(o) && h.sameMappings(o) } func (h Histogram) sameLength(o Histogram) bool { return len(h) == len(o) } func (h Histogram) sameMappings(o Histogram) (res bool) { res = true for k := range h { if h[k] != o[k] { res = false } } return } var tallyTests = []struct { strand string nucleotide byte expected int }{ {"", 'A', 0}, {"ACT", 'G', 0}, {"CCCCC", 'C', 5}, {"GGGGGTAACCCGG", 'T', 1}, } func TestNucleotideCounts(t *testing.T) { for _, tt := range tallyTests { dna := DNA(tt.strand) count, _ := dna.Count(tt.nucleotide) if count != tt.expected { t.Fatalf("Got \"%v\", expected \"%v\"", count, tt.expected) } } } func TestHasErrorForInvalidNucleotides(t *testing.T) { dna := DNA("GATTACA") count, err := dna.Count('X') if count != 0 { t.Fatalf("Got \"%v\", expected \"%v\"", count, 0) } if err == nil { t.Fatalf("X is an invalid nucleotide, but no error was raised") } } // In most cases, this test is pointless. // Very occasionally it matters. // Just roll with it. func TestCountingDoesntChangeCount(t *testing.T) { dna := DNA("CGATTGGG") dna.Count('T') count, _ := dna.Count('T') if count != 2 { t.Fatalf("Got \"%v\", expected \"%v\"", count, 2) } } type histogramTest struct { strand string expected Histogram } var histogramTests = []histogramTest{ { "", Histogram{'A': 0, 'C': 0, 'T': 0, 'G': 0}, }, { "GGGGGGGG", Histogram{'A': 0, 'C': 0, 'T': 0, 'G': 8}, }, { "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC", Histogram{'A': 20, 'C': 12, 'T': 21, 'G': 17}, }, } func TestSequenceHistograms(t *testing.T) { for _, tt := range histogramTests { dna := DNA(tt.strand) if !dna.Counts().Equal(tt.expected) { t.Fatalf("DNA{ \"%v\" }: Got \"%v\", expected \"%v\"", tt.strand, dna.Counts(), tt.expected) } } } func BenchmarkSequenceHistograms(b *testing.B) { b.StopTimer() for _, tt := range histogramTests { for i := 0; i < b.N; i++ { dna := DNA(tt.strand) b.StartTimer() dna.Counts() b.StopTimer() } } }