import unittest
import exceptions
from LLazyModel.TreeDataBase import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, TreeDBMethods, LlazyDBError
from LLazyModel.TDBBackends.LDAP import LDAPLlazyDBError
from LLazyModel.TDBBackends.AbstractTDB import AbstractTDBConnection
from LLazyModel.DACData import *

# LDAP setup
ldapdb = 'ldap://kamka.org'
fakeldapdb = 'ldap://nara'
testnode1 = 'dc=org,dc=kamka'
testnode2 = 'dc=org,dc=kamka,ou=Users,uid=usertest'
testdicnod = {'nodename':'dc=org,dc=kamka,ou=test','objectClass':['organizationalUnit'], 'ou':['test']}
testdicnod2 = {'nodename':'dc=org,dc=kamka,ou=test','objectClass':['organizationalUnit'], 'ou':['test']}
fakenode2 = {'nodename':'dc=org,dc=kamka,ou=zzz,ou=fake','objectClass':['organizationalUnit'], 'ou':['fake']}
fakenode = 'dc=kamka,dc=kamka,ou=fake'
baddicnode = {'ou=test,dc=kamka,dc=orgggg':{'objectClass':['organizationalUnit'], 'ou':['test']}}
login = 'cn=admin,dc=kamka,dc=org'
passwd = 'secret'

proto = 3
total_child_of_ouPeopledckamkadcorg = 112
child_of_ouPeopledckamkadcorg = 8

# XML setup
xmldb = 'xml:///home/ced/Eclipse/workspace/llazy/tests/test.xml'

class NodeTestCase(unittest.TestCase):
    """Unit test for Node class"""
    def setUp(self):
        """ Set up initial values"""
        self.dict1 = {"nodename":"noeud0","key0":"val0","key1":"val1","key2":"val2"}
                
        self.nodeslist =    [
            {"nodename":"root,sub","key0":"val0"},
            {"nodename":"root,sub,nod0","key0":"val0"},
            {"nodename":"root,sub,nod0,n","key0":"val0"},
            {"nodename":"root,sub,nod1","key1":"val1","k1":"v", "m1":"n"},
            {"nodename":"root,sub,nod1,n","key1":"val1","k1":"v", "m1":"n"},
            {"nodename":"root,sub,nod2","key2":"val2","k":"v", "m":"n"},
            {"nodename":"root,sub,nod2,n","key2":"val2"},
            {"nodename":"root,sub,nod2,n,o","key2":"val2"},
            {"nodename":"root,sub,nod2,n,o,m","keym":"valm"},
            {"nodename":"root,sub,nod2,w,o,x","keyo":"valo"}
            ]


        pass
    
    def test_01_Node_init_without_param(self):
        """ Test Node __init__ function"""
        n = Node()
        
        self.failIf(n is None and not isinstance(n, Node), "Instanciation error" )
        
    def test_02_Node_init_with_dic_param(self):
        """Test Node __init__ function"""
        dic = self.dict1.copy()     
        n = Node(dic)
        
        t1 = isinstance(n, Node)
        t2 = n.nodename == self.dict1["nodename"]
        t3 = len(n) == len(self.dict1)
        t4 = n.nbChild() == 0

        #print t1 , t2 , t3 , t4
        
        self.failIf(not(t1 and t2 and t3 and t4), "Classe Node: instanciation error")
        pass
    
    def test_03_Node_init_with_list_param(self):
        """Test Node __init__ function"""
        dic = self.nodeslist[0:-1]
        n = Node(dic)
        t1 = isinstance(n, Node)
        t2 ,t3 = True, True
        
        for d in self.nodeslist[0:-1]:
            if not isinstance(find_node(n, d["nodename"]), Node):
                t2 = False
            if len(d) != len(find_node(n, d["nodename"])):
                t3 = False            
        
        t4 = n.nbChild() == len(self.nodeslist[0:-1]) -1
        
        #print t1 , t2 , t3, t4
        
        self.failIf(not(t1 and t2 and t3 and t4), "Classe Node: instanciation error")
        pass
    
    def test_04_Node_init_with_list_param2(self):
        """Test Node __init__ function"""
        dic = self.nodeslist[1:-1]
        n = Node(dic)
        t1 = isinstance(n, Node)
        t2 ,t3 = True, True
        
        for d in self.nodeslist[1:-1]:
            if not isinstance(find_node(n, d["nodename"]), Node):
                t2 = False
            if len(d) != len(find_node(n, d["nodename"])):
                t3 = False            
        
        t4 = n.nbChild() == len(self.nodeslist[1:-1])
        
        #print t1 , t2 , t3, t4
        
        self.failIf(not(t1 and t2 and t3 and t4), "Classe Node: instanciation error")
        pass
    
    def test_05_Node_init_with_node_param(self):
        """Test Node __init__ function"""
        dic = self.nodeslist[0:-1]
        m = Node(dic)
        n= Node(m)
        
        t1 = isinstance(n, Node)
        t2 = True
        for d in self.nodeslist[0:-1]:
            if not isinstance(find_node(n, d["nodename"]), Node):
                t2 = False
        t3 = True
        t4 = n.nbChild() == len(self.nodeslist[0:-1]) -1
        t5 = m.nbChild() == len(self.nodeslist[0:-1]) -1
        
        #print t1 , t2 , t3, t4
        
        self.failIf(not(t1 and t2 and t3 and t4), "Classe Node: instanciation error")
        pass
    
    def test_06_Node_addNode(self):
        """Test Node addNode method"""
        rootdic = self.nodeslist[0]
        subdic = self.nodeslist[5:9]
        
        root = Node(rootdic)
        sub = Node(subdic)
        
        root.addNode(sub)
        
        t1 = isinstance(root, Node)
        t2 = root.nbChild() == len(self.nodeslist[5:9])
        
        t3  = True
        for d in self.nodeslist[5:9]:
            if not isinstance(find_node(root, d["nodename"]), Node):
                t3 = False           
        
        #print t1, t2, t3
        
        self.failIf(not(t1 and t2 and t3), "Classe Node: addNode method error")
        
    def test_07_Node_delNode(self):
        """Test Node delNode method"""
        n = Node(self.nodeslist[0:-1])
        
        t1 = n.nbChild() == len(self.nodeslist[0:-1]) -1
        
        n.delNode(find_node(n, self.nodeslist[8]["nodename"]))
        
        t2 = n.nbChild() == len(self.nodeslist[0:-1]) -2
        
        n.delNode(find_node(n, self.nodeslist[1]["nodename"]))
        
        t3 = n.nbChild () == len(self.nodeslist[0:-1]) -4
        
        #print t1, t2, t3       
        
        self.failIf(not(t1 and t2 and t3), "Classe Node: delNode method error")
        
    def test_08_Node_add_Node_2_Node(self):    
        A = Node(self.nodeslist[0])
        B = Node(self.nodeslist[1])
        
        add(A, B)
        
        t1 = isinstance(A, Node)
        t2 = A.nbChild() == 1
        find_node(A, B.nodename)
        
        self.failIf(not(t1 and t2), "Module DACData: add method, cant't add node to node")
        
    def test_09_Node_add_Node_2_Node_err(self):
        A = self.nodeslist[0]
        B = self.nodeslist[1]
        
        try:
            add(A, B)
        except LlazyNodeError:
            return
        self.fail("Module DACData: add method, operation non permited")
        
    def test_10_Node_add_Node_2_Node_err(self):
        root = Node(self.nodeslist[0])
        nonchildren = Node(self.nodeslist[-1])
        
        try:
            add(root, nonchildren)
        except :
            return
        self.fail("Module DACData: add method, operation non permited")
        
    def test_11_Node_substract_Node_2_Node(self):
        A = Node(self.nodeslist[0:-1])
        B = Node(self.nodeslist[5:9])
        
        subst(A, B)
        
        t1 = A.nbChild() == 4
        
        self.failIf(not(t1), "Module DACData: add method, cant't substract node to node" )
        
    def test_12_Node_substract_Node_2_Node_err(self):
        A = self.nodeslist[0:-1]
        B = self.nodeslist[5:9]
        
        try:
            subst(A, B)
        except :
            return
        self.fail("Module DACData: add method, operation non permited")
        
    def test_13_Node_substract_Node_2_Node_err(self):
        root = Node(self.nodeslist[0:-1])
        nonchildren = Node(self.nodeslist[-1])
        
        try:
            subst(root, nonchildren)
        except :
            return
        self.fail("Module DACData: add method, operation non permited")
        
    def test_14_Node_change_root(self):
        node = Node(self.nodeslist[0:-1])
        change_root(node, "anotherroot")
        
        t1 = find_node(node, "anotherroot")
        
        self.failIf(not(t1), "Module DACData: change_root method: error")

    def test_15_Node_search(self):
        node = Node(self.nodeslist[0:-1])

        resp = search(node, {"key2":"val2"})        
        t1 = len(resp) == 3
        
        resp = search(node, {"key1":"val1"})
        t2 = len(resp) == 2
        
        resp = search(node, {"m":"n"})
        t3 = len(resp) == 1
        
    def test_16_Node_search_with_scope(self):
        node = Node(self.nodeslist[0:-1])
        
        resp = search(node, {"key0":"val0"},0)        
        t1 = len(resp) == 1
        resp = search(node, {"key1":"val1"},0)        
        t2 = len(resp) == 0
        
        resp = search(node, {"key0":"val0"},1)
        t3 = len(resp) == 2
        
        resp = search(node, {"key2":"val2"},1)
        t4 = len(resp) == 1
        resp = search(node, {"key2":"val2"},2)
        t5 = len(resp) == 2       
        
        resp = search(node, {"key2":"val2"},3)
        t6 = len(resp) == 3
        
        self.failIf(not(t1 and t2 and t3 and t4 and t5 and t6), "Module DACData: search method: error")
        
class TreeDBFactoryTestCase(unittest.TestCase):
    """Unit test for TreeDataBase class"""
    def test_01_TreeDBFactory_LDAPTreeDB_getFactory(self):
        """Get a ldap TreeDB"""
        db = TreeDBMethods.getTDB(ldapdb)
        self.failIf(not(issubclass(db.__class__, AbstractTDBConnection)), "Instanciation error")
        
    def test_02_TreeDBFactory_XMLTreeDB_getFactory(self):
        """Get a xml TreeDB"""
        db = TreeDBMethods.getTDB(xmldb)
        self.failIf(not(issubclass(db.__class__, AbstractTDBConnection)), "Instanciation error")
    
    def test_03_TreeDBFactory_TreeDB_getFactory_error(self):
        """Test error if dbname is not valid"""
        try:
            db = TreeDBMethods.getTDB('anydb')
        except LlazyDBError:
            pass
        else:
            self.fail("Expected a LlazyUnknownScheme")

class TDB_LDAPTreeDBTestCase(unittest.TestCase):
    """Unit test for LDAPDataBase class"""
    def setUp(self):
        """Creating fixtures for ldap TreeDB"""
        self.db = TreeDBMethods.getTDB(ldapdb)   
        self.failIf(self.db.fti['module'] != 'LDAP', "Instanciation error")     
        
    def test_01_LDAPTreeDB_open_close(self):
        """Test open / close conection"""
        self.db.setParam(ldapdb, testnode1, login, passwd, proto)
        
        try:
            self.db.open()
            self.db.close()
        except LlazyDBError:
            self.fail("Can't open connection Node")
    
    def test_02_LDAPTreeDB_open_close_fakedb(self):
        """Test open / close conection"""
        self.db.setParam(fakeldapdb, testnode1, login, passwd, proto)
        
        try:
            self.db.opendb()
            self.db.closedb()
        except Exception:
            return
        
        self.fail("Can open connection with a fake node ???")

class TDB_XMLTreeDBTestCase(unittest.TestCase):
    """Unit test for XMLDataBase class"""
    def setUp(self):
        """Creating fixtures for xml TreeDB"""
        
        self.db = TreeDBMethods.getTDB(xmldb)   
        self.failIf(self.db.fti['module'] != 'XML', "Instanciation error")

    def test_01_XMLTreeDB_open_close(self):
        """Test open / close conection"""
        try:
            self.db.open()
            self.db.close()
        except LlazyDBError:
            self.fail("Can't open connection Node")
        
class TDBM_LDAPMethods(unittest.TestCase):
    """Unit test for LDAP TDBMethods"""
    def setUp(self):
        """Creating fixtures for ldap TreeDB"""
        
        self.db = TreeDBMethods.getTDB(ldapdb)
        self.db.setParam(ldapdb,testnode1,login,passwd,proto)
           
    def test_01_LdapTDBM_getNode_SCOPE_BASE(self):
        node = TreeDBMethods.getNode(testnode1, SCOPE_BASE, self.db)
        
        t1 = node.nodename == testnode1
        t2 = node.nbChild() == 0
        t3 = len(node) == 4

        self.failIf(not(t1 and t2 and t3), "LdapTDBMethods error")
        
    def test_02_LdapTDBM_getNode_SCOPE_ONELEVEL(self):
        node = TreeDBMethods.getNode(testnode1, SCOPE_ONELEVEL, self.db)
        
        t1 = node.nodename == testnode1
        t2 = node.nbChild() == child_of_ouPeopledckamkadcorg

        self.failIf(not(t1 and t2), "LdapTDBMethods error")
        
    def test_03_LdapTDBM_getNode_SCOPE_SUBTREE(self):
        node = TreeDBMethods.getNode(testnode1, SCOPE_SUBTREE, self.db)
        
        t1 = node.nodename == testnode1
        t2 = node.nbChild() == total_child_of_ouPeopledckamkadcorg

        self.failIf(not(t1 and t2), "LdapTDBMethods error")
        
    def test_04_LdapTDBM_getNode_fakeNode(self):
        result = TreeDBMethods.getNode(fakenode, SCOPE_SUBTREE, self.db)
        t1 = result.nodename = "not found"
        
        self.failIf(not(t1), "Module LdapTDBMethod: delNode, can't delete a node")
      
    def test_05_LdapTDBM_searchNode(self):
        node = TreeDBMethods.searchNode(testnode1, self.db)
        
        t1 = node.nodename == testnode1
        t2 = node.nbChild() == 0     
        self.failIf(not(t1 and t2), "LdapTDBMethods error")
        
    def test_06_LdapTDBM_searchNode_fakeNode(self):
        result = TreeDBMethods.searchNode(fakenode, self.db)
        
        t1 = result.nodename = "not found"
        
        self.failIf(not(t1), "Module LdapTDBMethod: delNode, can't delete a node")
           
    def test_07_LdapTDBM_addNode(self):
        node = Node(testdicnod.copy())
        
        TreeDBMethods.addNode(node, self.db)
        
        result = TreeDBMethods.searchNode(node.nodename, self.db)
        
        t1 = node.nodename == result.nodename
        t2 = node.items() == result.items()
        
        self.failIf(not(t1 and t2), "LdapTDBMethods error")
     
    def test_08_LdapTDBM_delNode(self):
        node = Node(testdicnod.copy())
        TreeDBMethods.delNode(node, self.db)
        
        result = TreeDBMethods.searchNode(testdicnod["nodename"], self.db)
                
        t1 = result.nodename == "ldap response"
        
        self.failIf(not(t1), "Module LdapTDBMethod: delNode, can't delete a node")

    def test_09_LdapTDBM_addNode_err(self):
        node = Node(fakenode2.copy())
        
        addresult = TreeDBMethods.addNode(node, self.db)
        
        result = TreeDBMethods.searchNode(node.nodename, self.db)
        
        t1 = result.nodename == "ldap response"
        
        self.failIf(not(t1), "LdapTDBMethods error")
        pass
    
    def test_10_LdapTDBM_delNode_err(self):
        node = Node(fakenode2.copy())
        
        addresult = TreeDBMethods.delNode(node, self.db)
        
        result = TreeDBMethods.searchNode(node.nodename, self.db)

        t1 = result.nodename == "ldap response"
        
        self.failIf(not(t1), "LdapTDBMethods error")
    
    def test_11_LdapTDBM_updateNode(self):
        node = TreeDBMethods.searchNode(testnode2, self.db)
        node["mail"] = "mail@mail"
        #print_node(node)
        
        TreeDBMethods.updateNode(node, self.db)
        
    def test_12_LdapTDBM_copy(self):
        node = TreeDBMethods.getNode("dc=org,dc=kamka,ou=Users", SCOPE_SUBTREE, self.db)
        
        node["ou"] = 'test'
        
        change_root(node, "dc=org,dc=kamka,ou=test")
        
        addresult = TreeDBMethods.addNode(node, self.db)
        delresult = TreeDBMethods.delNode(node, self.db)
        
        self.failIf(addresult is not None, "error")
        
    
        
        
#class TDBM_XMLMethods(unittest.TestCase):
#    """Unit test for XML TDBMethods"""
#    def setUp(self):
#        """Creating fixtures for ldap TreeDB"""
#        self.backend = 'xml://foo'
#        
#        self.db = TreeDataBase(self.backend)
#
#    def test_XmlTDBM_addNode(self):
#        node = TreeDBMethods.addNode(None, self.db)        
#        self.failIf(node.__class__ != Node, "XmlTDBMethods error")
#        
#    def test_XmlTDBM_getNode(self):
#        node = TreeDBMethods.getNode(None, None, self.db)        
#        self.failIf(node.__class__ != Node, "XmlTDBMethods error")
#        
#    def test_XmlTDBM_searchNode(self):
#        node = TreeDBMethods.searchNode(None, self.db)        
#        self.failIf(node.__class__ != Node, "XmlTDBMethods error")
#        
#    def test_XmlTDBM_delNode(self):
#        node = TreeDBMethods.delNode(None, self.db)        
#        self.failIf(node.__class__ != Node, "XmlTDBMethods error")
#    
#    pass
