# Copyright (c) 2000-2004 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""unit tests for narval.reader and Recipe / Action handlers
"""

__revision__ = '$Id: readers.py,v 1.35 2004/04/02 10:06:46 syt Exp $'

import unittest
from narval.prototype import *
from narval.plan import PlanElement
from narval.tags import tag_element
from narval.public import NO_NS

class DummyElement:
    EID_COUNT = 1
    def __init__(self, prop):
        self.prop = prop
        self.eid = DummyElement.EID_COUNT
        self.outdated = False
        DummyElement.EID_COUNT += 1
        self._ns_attrs = {(NO_NS, 'use'):0}

    def setattr(self, x, y):
        self._ns_attrs[x] = y

    def getattr(self, x):
        try:
            return self._ns_attrs[x]
        except:
            return None


class PrototypeEntryTC(unittest.TestCase):
    klass = PrototypeEntry
    
    def tagger_id(self):
        return 'test'
    
    def setUp(self):
        self.proto = self.klass()
        self.init_proto(self.proto)
        
    def init_proto(self, proto):
        proto.matches = []
        proto.matches.append('elmt.__class__.__name__ == "DummyElement"')
        proto.cmatches.append(compile('elmt.__class__.__name__ == "DummyElement"', 'proto_test.py', 'eval'))
        proto.matches.append('elmt.prop == "toto"')
        proto.cmatches.append(compile('elmt.prop == "toto"', 'proto_test.py', 'eval'))
        elmt1 = DummyElement('toto')
        elmt2 = DummyElement('tutu')
        self.elements = [elmt1, elmt2]
        
    def test_clone(self):
        other = self.proto.clone()
        self.assertNotEquals(id(other), id(self.proto))
        self.assertNotEquals(id(other.matches), id(self.proto.matches), 'matches instances are the same list')
        
    def test_clone_destroy(self):
        # TODO - maybe a more complex PlanElement will give us the deepcopy bug
        self.proto.__dict__.update({'_ns_attrs': {(None, 'owner') : PlanElement(),
                                                  (None, 'optional'): False,
                                                  (None, 'id'): 'statement',
                                                  (None, 'to_context'): 4,
                                                  (None, 'matches'): [u'IRDFStatement(elmt)'],
                                                  (None, 'list'): False,
                                                  (None, 'use'): True,
                                                  (None, 'from_context'): 1,
                                                  (None, 'descriptions'): {}}})
        other = self.proto.clone()
        self.assertNotEquals(id(other), id(self.proto))
        self.assertNotEquals(id(other.matches), id(self.proto.matches), 'matches instances are the same list')
        secondother = other.clone()
        self.assertNotEquals(id(other), id(secondother))
        self.assertNotEquals(id(other.matches), id(secondother.matches), 'matches instances are the same list')


class OutputEntryTC(PrototypeEntryTC):
    klass = OutputEntry
        
    def test_base_match_elements(self):
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [self.elements[0]])
        
    def test_use_match_elements(self):
        self.proto.use = True
        self.proto.owner = self
        tag_element(self.elements[0], self)
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [self.elements[0]])

    def test_outdated_match_elements(self):
        self.elements[0].setattr((AL_NS, 'outdated'), True)
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [self.elements[0]])


class InputEntryTC(PrototypeEntryTC):
    klass = InputEntry
        
    def test_base_match_elements(self):
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [self.elements[0]])
        
    def test_use_match_elements(self):
        self.proto.use = True
        self.proto.owner = self
        tag_element(self.elements[0], self)
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [])

    def test_outdated_match_elements(self):
        self.elements[0].outdated = True
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, [])


class ConditionTC(InputEntryTC):
    klass = Condition
        
    def test_base_match_elements(self):
        match = self.proto.match_elements(self.elements)
        self.assertEquals(match, Set(self.elements))


from unittest_reader import empty_registry, RecipeElement, ActionElement

class MergeIOTC(unittest.TestCase):
    ACTION_STRING = '''<al:action xmlns:al="http://www.logilab.org/namespaces/Narval/1.2" func="non_existent_f" name="naughty_action_2">
<al:output id="output" list="yes">
<al:match>element</al:match>
</al:output>
<al:output id="output-no-match" optional="yes"/>
</al:action>'''
    
    RECIPE_STRING = '''<al:recipe xmlns:al="http://www.logilab.org/namespaces/Narval/1.2" group="bkmonitor" name="update_bmf">
<al:step id="s1" target="whatever" type="action"/>
</al:recipe>
    '''
    def setUp(self):
        self.reader = reader = empty_registry()
        reader.register_class(RecipeElement)
        reader.register_class(ActionElement)
        
    def test_merge_inputs(self):
        raise NotImplementedError()

    def test_merge_outputs(self):
        action = self.reader.from_string(self.ACTION_STRING)[0]
        recipe = self.reader.from_string(self.RECIPE_STRING)[0]
        a_proto = action.prototype
        s_proto = recipe.elements['s1'].prototype
        s_proto.prepare(a_proto)
        self.assertEquals( [s_p.id for s_p in s_proto.output_prototype()],
                           ['output', 'output-no-match'])
        # FIXME: check other thing such as overloading of "optional", "list" and so on
        #raise NotImplementedError()

    
if __name__ == '__main__':
    unittest.main()


