#
# = test/bio/db/newick.rb - Unit test for Bio::Newick
#
# Copyright::   Copyright (C) 2004-2006
#               Daniel Amelang <dan@amelang.net>
#               Naohisa Goto <ng@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/tree'
require 'bio/db/newick'

module Bio
  class TestNewick < Test::Unit::TestCase

    TREE_STRING = <<-END_OF_TREE_STRING
    (
      (
        HexLEZ35:0.00263,
        HexMCZ42:0.00788
      ):0.00854,
      (
        HexFLZ48:0.00457,
        (
          HexFLZ83:0.00217,
          HexFLZ13:0.00574
        ):0.00100
      ):0.04692,
      HexLEZ73:0.00268
    )[0.1250];
    END_OF_TREE_STRING

    def setup
      @newick = Bio::Newick.new(TREE_STRING)
    end

    def test_string_tree
      tree = @newick.tree
      assert_equal(3, tree.children(tree.root).size)
      assert_equal(9, tree.descendents(tree.root).size)
      assert_equal(6, tree.leaves.size)
      leaf = tree.get_node_by_name('HexFLZ83')
      assert_equal(3, tree.ancestors(leaf).size)
      assert_equal(tree.path(tree.root, leaf)[1], tree.ancestors(leaf)[1])
      assert_equal(0.00217, tree.get_edge(leaf, tree.parent(leaf)).distance)
      assert_equal("HexFLZ83", leaf.name)
    end

    def test_reparse
      tree = @newick.tree
      tree_text = tree.output(:newick)
      assert_equal(@newick, @newick.reparse)
      assert_equal(tree_text, @newick.tree.output(:newick))
    end

    def test_reparse_before_lazy_parsing
      # not to use @newick to guarantee that the Newick object
      # is before lazy parsing.
      newick = Bio::Newick.new(TREE_STRING)
      assert_equal(newick, newick.reparse)
    end

  end #class TestNewick

  class TestNewick2 < Test::Unit::TestCase

    TREE_STRING = <<-END_OF_TREE_STRING
    (
      (
        'this is test':0.0625,
        'test2 (abc, def)':0.125
      ) 'internal node''s name' : 0.25,
      (
        '''':0.03125,
        (
          'ABCAC_HUMAN [ABC superfamily]':0.015625,
          hypothetical_protein:0.5
        ) ABC : 0.25 [99]
      ) test3 :0.5
    )root;
    END_OF_TREE_STRING

    def setup
      @newick = Bio::Newick.new(TREE_STRING)
    end

    def test_string_tree
      tree = @newick.tree
      assert_equal('root', tree.root.name)
      assert_equal([ 
                    "this is test",
                    "test2 (abc, def)",
                    "internal node\'s name",
                    "\'",
                    "ABCAC_HUMAN [ABC superfamily]",
                    "hypothetical protein",
                    "ABC",
                    "test3",
                    "root"
                   ].sort,
                   tree.nodes.collect { |x| x.name }.sort)

      assert_equal(tree.children(tree.root).collect { |x| x.name }.sort,
                   [ "internal node\'s name", "test3" ])

      node = tree.get_node_by_name('ABC')
      assert_equal(99, node.bootstrap)

      assert_equal(1.5625,
                   tree.distance(tree.get_node_by_name('hypothetical protein'),
                                 tree.get_node_by_name('this is test')))
    end

  end #class TestNewick2

  class TestNewickPrivate < Test::Unit::TestCase
    def setup
      @newick = Bio::Newick.new('') # dummy data
    end

    def test_parse_newick_leaf
      leaf_tokens = [ "A:B _C(D,E)F\'s G[H]", :":", '0.5', :"[",
                      "&&NHX", :":", "S=human", :":", "E=1.1.1.1", :"]" ]
      node = Bio::Tree::Node.new
      edge = Bio::Tree::Edge.new
      options = {}

      assert_equal(true,
                   @newick.instance_eval do
                     __parse_newick_leaf(leaf_tokens, node, edge, options)
                   end)

      assert_equal(:nhx, @newick.options[:original_format])
      assert_equal("A:B _C(D,E)F\'s G[H]", node.name)
      assert_equal("human", node.scientific_name)
      assert_equal("1.1.1.1", node.ec_number)
      assert_equal(0.5, edge.distance)
    end

    def test_parse_newick_get_tokens_for_leaf
      input = [ "A:B _C(D,E)F\'s G[H]", :":", '0.5', :"[",
                "&&NHX", :":", "S=human", :":", "E=1.1.1.1", :"]",
                :",", :"(", "bbb", :":", "0.2", :")" ]
      leaf_should_be = [ "A:B _C(D,E)F\'s G[H]", :":", '0.5', :"[",
                "&&NHX", :":", "S=human", :":", "E=1.1.1.1", :"]" ]
      rest_should_be = [ :",", :"(", "bbb", :":", "0.2", :")" ]

      assert_equal(leaf_should_be, 
                   @newick.instance_eval do
                     __parse_newick_get_tokens_for_leaf(input)
                   end)

      assert_equal(rest_should_be, input)
    end

    def test_parse_newick_tokenize
      examples =
        [
         [ 
          '(a,b);', # input
          [ :"(", 'a', :",", 'b', :")" ], # normal parser result
          [ :"(", 'a', :",", 'b', :")" ], # naive parser result
         ],
         [
          # input
          "(\'A:B _C(D,E)F\'\'s G[H]\':0.5[&&NHX:S=human:E=1.1.1.1], \n(bbb:0.2, c_d_e[&&NHX:B=100]);",
            # normal parser result
            [ :"(", "A:B _C(D,E)F\'s G[H]", :":", '0.5', :"[",
            "&&NHX", :":", "S=human", :":", "E=1.1.1.1", :"]",
            :",", :"(", "bbb", :":", "0.2", :",", 
            "c d e", :"[", "&&NHX", :":", "B=100", :"]", :")" ],
            # naive parser result
            [ :"(", "\'A", :":", "B _C", :"(", "D", :",", "E",
            :")", "F\'\'s G", :"[", "H", :"]", "\'", :":", '0.5', :"[",
            "&&NHX", :":", "S=human", :":", "E=1.1.1.1", :"]",
            :",", :"(", "bbb", :":", "0.2", :",", 
            "c_d_e", :"[", "&&NHX", :":", "B=100", :"]", :")" ]
          ]
        ]

      examples.each do |a|
        # normal parser
        assert_equal(a[1],
                     @newick.instance_eval do
                       __parse_newick_tokenize(a[0], {})
                     end)

        # naive parser
        assert_equal(a[2],
                     @newick.instance_eval do
                       __parse_newick_tokenize(a[0], { :parser => :naive })
                     end)
      end
    end
  end #class TestNewickPrivate

  class TestBioTreeOutputPrivate < Test::Unit::TestCase

    def setup
      @tree = Bio::Tree.new
    end

    def test_to_newick_format_label
      # unquoted_label
      assert_equal('ABC', @tree.instance_eval do
                     __to_newick_format_label('ABC', {})
                   end)

      # unquoted_label, replaces blank to underscore
      assert_equal('A_B_C', @tree.instance_eval do
                     __to_newick_format_label('A B C', {})
                   end)

      # quoted_label example 1
      assert_equal("\'A B_C\'", @tree.instance_eval do
                     __to_newick_format_label('A B_C', {})
                   end)

      # quoted_label example 2
      assert_equal("\'A(B),C\'", @tree.instance_eval do
                     __to_newick_format_label('A(B),C', {})
                   end)

      # normal formatter
      assert_equal("\'A_B_C\'", @tree.instance_eval do
                     __to_newick_format_label('A_B_C', {})
                   end)
      # naive formatter
      assert_equal("A_B_C", @tree.instance_eval do
                     __to_newick_format_label('A_B_C',
                                              { :parser => :naive })
                   end)
    end


    def test_to_newick_format_leaf
      node = Bio::Tree::Node.new('ABC')
      edge = Bio::Tree::Edge.new(0.5)

      assert_equal('ABC:0.5', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge, {})
                   end)

      # disable branch length
      assert_equal('ABC', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge,
                                             { :branch_length_style =>
                                               :disabled })
                   end)

      node.bootstrap = 98
      # default: molphy style bootstrap
      assert_equal('ABC:0.5[98]', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge, {})
                   end)
      # force molphy style bootstrap
      assert_equal('ABC:0.5[98]', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge,
                                             { :bootstrap_style => :molphy })
                   end)
      # disable bootstrap output
      assert_equal('ABC:0.5', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge,
                                             { :bootstrap_style =>
                                               :disabled })
                   end)

      # force traditional bootstrap style
      assert_equal('ABC98:0.5', @tree.instance_eval do
                     __to_newick_format_leaf(node, edge,
                                             { :bootstrap_style =>
                                               :traditional })
                   end)
      # normally, when traditional style, no node name allowed for the node
      node2 = Bio::Tree::Node.new
      node2.bootstrap = 98
      assert_equal('98:0.5', @tree.instance_eval do
                     __to_newick_format_leaf(node2, edge,
                                             { :bootstrap_style =>
                                               :traditional })
                   end)
      
    end

    def test_to_newick_format_leaf_NHX
      node = Bio::Tree::Node.new('ADH')
      edge = Bio::Tree::Edge.new(0.5)
      node.bootstrap = 98
      node.ec_number = '1.1.1.1'
      node.scientific_name = 'human'
      node.taxonomy_id = '9606'
      node.events.push :gene_duplication
      edge.log_likelihood = 1.5
      edge.width = 3

      str = 'ADH:0.5[&&NHX:B=98:D=Y:E=1.1.1.1:L=1.5:S=human:T=9606:W=3]'
      assert_equal(str, @tree.instance_eval do
                     __to_newick_format_leaf_NHX(node, edge, {})
                   end)
    end

  end #class TestBioTreeOutputPrivate

end #module Bio
