#!/www/python/bin/python

"""$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/test/test_typed_list.py $
$Id: test_typed_list.py 23443 2004-02-06 15:23:48Z dbinger $

Test for dulcinea.typed_list.
"""

from types import *
from sancho.unittest import TestScenario, parse_args, run_scenarios
from dulcinea.typed_list import TypedList

class Value:

    def __init__ (self, name=None):
        if name is not None:
            self.name = name

    def get_name(self):
        return getattr(self, 'name', 'no')

class OtherValue:

    def __init__ (self, name):
        self.name = name


tested_modules = [ "dulcinea.typed_list" ]

class TestTypedList(TestScenario):

    test_cases = [ 'add', 'format', 'getset_list', 'getset_item',
                   'merge', 'find_index' ]

    def check_add(self):
        lst = TypedList() ; lst.required_class = Value
        v1 = Value("n1")
        v2 = Value("n2")
        self.test_stmt("lst.add(v1)")
        self.test_stmt("lst.add(v2)")
        self.test_val("lst.find('n1')", v1, match_ident=1)
        self.test_val("lst.find('foo')", None)
        self.test_val("len(lst)", 2)

        # adding something already on the list should raise a ValueError:
        self.test_exc("lst.add(v1)", ValueError)
        self.test_seq("lst.get_names()", ["n1", "n2"])

        # turning off type checking, (if you already know the types are ok)
        self.test_stmt("TypedList(lst.get_list(), check_types=0)")

        # check remove method, while we're at it:
        self.test_val("lst.remove('n2')", v2, match_ident=1)
        self.test_val("lst.find('n2')", None)
        self.test_val("lst.remove('foo')", None)

        ov1 = OtherValue("n1")
        ov2 = OtherValue("foo")
        self.test_exc("lst.add(ov1)", TypeError)
        self.test_exc("lst.add(ov2)", TypeError)


    def check_format(self):
        lst = TypedList()
        self.test_val("str(lst)", "no values")
        lst.add(Value("n1"))
        self.test_val("str(lst)", "1 value")
        lst.add(Value("n2"))
        self.test_val("str(lst)", "2 values")


    def check_getset_list(self):
        lst = TypedList()
        v1 = Value("n1")
        v2 = Value("n2")
        self.test_seq("lst.get_list()", [])
        lst.add(v1)
        lst.add(v2)
        self.test_val("lst.get_list()", [v1, v2])
        lst.remove(v1.name)
        self.test_val("lst.get_list()", [v2])
        self.test_stmt("lst.set_list([v1, v2])")
        self.test_val("lst.find('n2')", v2, match_ident=1)
        self.test_val("lst.get_list()", [v1, v2])
        self.test_exc("lst.set_list([v1, v2, v1])", ValueError)

    def check_getset_item(self):
        lst = TypedList() ; lst.required_class = Value
        v1 = Value("n1")
        v2 = Value("n2")
        v3 = Value("n3")
        ov1 = OtherValue("n1")

        lst.add(v1) ; lst.add(v2)
        self.test_val("len(lst)", 2)
        self.test_val("lst[0]", v1, match_ident=1)
        self.test_val("lst[1]", v2, match_ident=1)
        self.test_stmt("lst[1] = v2")
        self.test_val("lst[1]", v2, match_ident=1)
        self.test_exc("lst[1] = v1", ValueError)    # name conflict

        self.test_val("lst.remove('n1')", v1, match_ident=1)
        self.test_val("len(lst)", 1)
        self.test_stmt("lst[0] = v2")
        self.test_val("lst[0]", v2, match_ident=1)
        self.test_stmt("lst[0] = v1")
        self.test_val("lst[0]", v1, match_ident=1)
        self.test_exc("lst[1]", IndexError)

        self.test_exc("lst[0] = ov1", TypeError)
        self.test_val("lst[0]", v1, match_ident=1)

    def check_merge(self):
        lst = TypedList()
        lst2 = TypedList()

        v1 = Value("n1")
        v2 = Value("n2")
        v3 = Value("n3")
        v4 = Value("n4")

        self.test_stmt("lst.add(v1)")
        self.test_stmt("lst.add(v2)")
        self.test_stmt("lst2.add(v3)")
        self.test_stmt("lst2.add(v4)")

        self.test_seq("lst.get_names()", ['n1', 'n2'])
        # presently, lst and lst2 are mutually exclusive.
        # merge them into lst3
        self.test_stmt("lst.merge(lst2)")
        self.test_seq("lst.get_names()", ['n1', 'n2', 'n3', 'n4'])

        # merging a parameter list with itself --setting various merge flags:
        self.test_exc("lst.merge(lst)", ValueError)
        # however, setting the merge flag to ignore should leave the original
        # parameter list unchanged:
        self.test_stmt("lst.merge(lst, 'ignore')")
        self.test_seq("lst.get_names()", ['n1', 'n2', 'n3', 'n4'])

        # verify that 'replace' behavior is correct:
        v1 = Value("n1")
        lst3 = TypedList([v1])
        # first, ensure that the original list contains the param by name:
        self.test_stmt("lst.merge(lst3, 'replace')")
        self.test_seq("lst.get_list()", [v1, v2, v3, v4])
        # next verify that the 'duration' parameter has been replaced:
        self.test_val("lst.find('n1')", v1, match_ident=1)

    def check_find_index(self):
        v1 = Value("n1")
        v2 = Value("n2")
        lst = TypedList([v1, v2])

        self.test_val("lst.find_index('n1')", 0)
        self.test_val("lst.find_index('n2')", 1)
        self.test_val("lst.find_index('foo')", None)


    def check_coverage(self):
        v1 = Value("n1")
        v2 = Value("n2")
        v3 = Value()
        t1 = TypedList([v1])
        self.test_stmt("t2=t1.copy()")
        self.test_stmt("t2.add(v2)")
        self.test_val("t1.get_list()", [v1])
        self.test_val("len(t2)", 2)
        t3 = TypedList([v3])
        self.test_val("len(t1 + t3 + [1])", 3)

if __name__ == "__main__":
    (scenarios, options) = parse_args()
    run_scenarios (scenarios, options)
