#
# = test/unit/bio/sequence/test_na.rb - Unit test for Bio::Sequencce::NA
#
# Copyright::   Copyright (C) 2006
#               Mitsuteru C. Nakao <n@bioruby.org>
# License::     The Ruby License
#
# $Id:$
#

# loading helper routine for testing bioruby
require 'pathname'
load Pathname.new(File.join(File.dirname(__FILE__), ['..'] * 3,
                            'bioruby_test_helper.rb')).cleanpath.to_s

# libraries needed for the tests
require 'test/unit'
require 'bio/sequence'
require 'bio/sequence/na'

module Bio
  class TestSequenceNANew < Test::Unit::TestCase
    def test_new
      str = 'atgcatgcatgcatgcaaaa'
      assert(Bio::Sequence::NA.new(str))
    end

    def test_new_t
      str = 'atgcatgcatgcatgcaaaa'
      str_t = "atgcatgcat\tgca\ttgcaaaa"
      assert_equal(str, Bio::Sequence::NA.new(str_t))
    end

    def test_new_n
      str = 'atgcatgcatgcatgcaaaa'
      str_n = "atgcatgcat\ngca\ntgcaaaa"
      assert_equal(str, Bio::Sequence::NA.new(str_n))
    end

    def test_new_r
      str = 'atgcatgcatgcatgcaaaa'
      str_r = "atgcatgcat\n\rgca\n\rtgcaaaa"
      assert_equal(str, Bio::Sequence::NA.new(str_r))
    end
  end

  class TestSequenceNA < Test::Unit::TestCase
    def setup
      @obj = Bio::Sequence::NA.new('atgcatgcatgcatgcaaaa')
    end

    def test_splicing
      #     'atgcatgcatgcatgcaaaa'
      #      12345678901234567890
      str = 'atgca  catgcatg'.gsub(' ', '')
      assert_equal(str, @obj.splicing('join(1..5,8..15)'))
    end

    def test_forward_complement
      str       = 'atgcatgcatgcatgcaaaa'
      str_fcomp = 'tacgtacgtacgtacgtttt'
      fcomp = @obj.forward_complement
      assert_equal(str_fcomp, @obj.forward_complement)
      assert_equal(str, @obj)
      assert_not_equal(fcomp.__id__, @obj.forward_complement.__id__)
      assert_equal(str_fcomp, @obj.forward_complement!)
      assert_equal(str_fcomp, @obj)
    end

    def test_reverse_complement
      str       = 'atgcatgcatgcatgcaaaa'
      str_rcomp = 'tacgtacgtacgtacgtttt'.reverse
      rcomp = @obj.reverse_complement
      assert_equal(str_rcomp, @obj.reverse_complement)
      assert_equal(str, @obj)
      assert_not_equal(rcomp.__id__, @obj.reverse_complement.__id__)
      assert_equal(str_rcomp, @obj.reverse_complement!)
      assert_equal(str_rcomp, @obj)
    end

    def test_complement
      assert(@obj.complement)
      assert(@obj.complement!)
    end

    def test_to_s
      str = 'atgcatgcatgcatgcaaaa'
      assert_equal(str, @obj.to_s)
    end

    def test_codon_usage
      usage = { 'cat' => 1, 'caa' => 1, 'tgc' => 1, 'gca' => 1, 'atg' => 2 }
      assert_equal(usage, @obj.codon_usage)
    end

    def test_gc_percent
      assert_equal(40, @obj.gc_percent)
      @obj[0, 1] = 'g'
      assert_equal(45, @obj.gc_percent)
    end

    def test_gc_content
      assert_in_delta(0.4, @obj.gc_content, Float::EPSILON)
      @obj[0, 1] = 'g'
      assert_in_delta(0.45, @obj.gc_content, Float::EPSILON)
    end

    def test_at_content
      assert_in_delta(0.6, @obj.at_content, Float::EPSILON)
      @obj[0, 1] = 'g'
      assert_in_delta(0.55, @obj.at_content, Float::EPSILON)
    end

    def test_gc_skew
      assert_in_delta(0.0, @obj.gc_skew, Float::EPSILON)
      @obj[0, 1] = 'g'
      assert_in_delta(1.0 / 9.0, @obj.gc_skew, Float::EPSILON)
      @obj.gsub!('a', 'c')
      assert_in_delta(-3.0 / 8.0, @obj.gc_skew, Float::EPSILON)
    end

    def test_at_skew
      assert_in_delta(1.0 / 3.0, @obj.at_skew, Float::EPSILON)
      @obj[0, 1] = 'g'
      assert_in_delta(3.0 / 11.0, @obj.at_skew, Float::EPSILON)
    end

    def test_iliegal_bases
      @obj[0, 1] = 'n'
      @obj[1, 1] = 'y'
      assert_equal(%w[n y], @obj.illegal_bases)
    end

    def test_molecular_weight
      assert_in_delta(6174.3974, @obj.molecular_weight, 1e-4)
    end

    def test_to_re
      assert_equal(/atgcatgcatgcatgcaaaa/, @obj.to_re)
      @obj[1, 1] = 'n'
      @obj[2, 1] = 'r'
      @obj[3, 1] = 's'
      @obj[4, 1] = 'y'
      @obj[5, 1] = 'w'
      assert_equal(/a[atgcyrwskmbdhvn][agr][gcs][tcy][atw]gcatgcatgcaaaa/, @obj.to_re)
    end

    def test_names
      ary = %w[Adenine Thymine Guanine]
      assert_equal(ary, @obj.splice('1..3').names)
    end

    def test_dna
      @obj[0, 1] = 'u'
      assert_equal('utgcatgcatgcatgcaaaa', @obj)
      assert_equal('ttgcatgcatgcatgcaaaa', @obj.dna)
    end

    def test_dna!
      @obj[0, 1] = 'u'
      assert_equal('utgcatgcatgcatgcaaaa', @obj)
      @obj.dna!
      assert_equal('ttgcatgcatgcatgcaaaa', @obj)
    end

    def test_rna
      assert_equal('atgcatgcatgcatgcaaaa', @obj)
      assert_equal('augcaugcaugcaugcaaaa', @obj.rna)
    end

    def test_rna!
      assert_equal('atgcatgcatgcatgcaaaa', @obj)
      @obj.rna!
      assert_equal('augcaugcaugcaugcaaaa', @obj)
    end
  end

  class TestSequenceNACommon < Test::Unit::TestCase
    def setup
      @obj = Bio::Sequence::NA.new('atgcatgcatgcatgcaaaa')
    end

    def test_to_s
      assert_equal('atgcatgcatgcatgcaaaa', @obj.to_s)
    end

    def test_to_str
      assert_equal('atgcatgcatgcatgcaaaa', @obj.to_str)
    end

    def test_seq
      str = 'atgcatgcatgcatgcaaaa'
      assert_equal(str, @obj.seq)
    end

    # <<(*arg)
    def test_push
      str = 'atgcatgcatgcatgcaaaaa'
      assert_equal(str, @obj << 'A')
    end

    # concat(*arg)
    def test_concat
      str = 'atgcatgcatgcatgcaaaaa'
      assert_equal(str, @obj.concat('A'))
    end

    # +(*arg)
    def test_sum
      str = 'atgcatgcatgcatgcaaaaatgcatgcatgcatgcaaaa'
      assert_equal(str, @obj + @obj)
    end

    # window_search(window_size, step_size = 1)
    def test_window_search
      @obj.window_search(4) do |_subseq|
        assert_equal(20, @obj.size)
      end
    end

    # total(hash)
    def test_total
      hash = { 'a' => 1, 'c' => 2, 'g' => 4, 't' => 3 }
      assert_equal(44.0, @obj.total(hash))
    end

    def test_composition
      composition = { 'a' => 8, 'c' => 4, 'g' => 4, 't' => 4 }
      assert_equal(composition, @obj.composition)
    end

    def test_splicing
      # (position)
      assert_equal('atgcatgc', @obj.splicing('join(1..4, 13..16)'))
    end
  end

  class TestSequenceNATranslation < Test::Unit::TestCase
    def setup
      str = 'aaacccgggttttaa'
      #      K>>P>>G>>F>>*>>
      #       N>>P>>G>>F>>
      #        T>>R>>V>>L>>
      #         P>>G>>F>>*>>
      #     "tttgggcccaaaatt"
      #      <<F<<G<<P<<K<<L
      #        <<G<<P<<N<<*
      #       <<V<<R<<T<<K
      @obj = Bio::Sequence::NA.new(str)
    end

    def test_translate
      assert_equal('KPGF*', @obj.translate)
    end

    def test_translate_1
      assert_equal('KPGF*', @obj.translate(1))
    end

    def test_translate_2
      assert_equal('NPGF', @obj.translate(2))
    end

    def test_translate_3
      assert_equal('TRVL', @obj.translate(3))
    end

    def test_translate_4
      assert_equal('LKPGF', @obj.translate(4))
    end

    def test_translate_5
      assert_equal('*NPG', @obj.translate(5))
    end

    def test_translate_6
      assert_equal('KTRV', @obj.translate(6))
    end

    def test_translate_7
      assert_equal('KPGF*', @obj.translate(7))
      assert_equal(@obj.translate, @obj.translate(7))
    end

    def test_translate_n1
      assert_equal('LKPGF', @obj.translate(-1))
      assert_equal(@obj.translate(4), @obj.translate(-1))
    end

    def test_translate_n2
      assert_equal('*NPG', @obj.translate(-2))
      assert_equal(@obj.translate(5), @obj.translate(-2))
    end

    def test_translate_n3
      assert_equal('KTRV', @obj.translate(-3))
      assert_equal(@obj.translate(6), @obj.translate(-3))
    end

    def test_translate_0
      assert_equal('KPGF*', @obj.translate(0))
      assert_equal(@obj.translate, @obj.translate(0))
      assert_equal(@obj.translate(7), @obj.translate(0))
    end

    def test_translate_unknown_x
      @obj[3, 1] = 'N'
      assert_equal('KXGF*', @obj.translate)
    end

    def test_translate_unknown_o
      @obj[3, 1] = 'N'
      assert_equal('KOGF*', @obj.translate(1, 1, 'O'))
    end

    def test_translate_given_codon_table
      @obj[0, 1] = 't'
      @obj[1, 1] = 'g'
      @obj[2, 1] = 'a'
      seleno_ct = Bio::CodonTable.copy(1)
      seleno_ct['tga'] = 'U'
      assert_equal('UPGF*', @obj.translate(1, seleno_ct))
    end
  end
end
