"""
unit tests for Narval core
"""
# Copyright (c) 2000 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
      
# Sylvain Thenault - 16/07/2001
import unittest, cStringIO 
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces
try:
    from Ft.Xml.pDomletteReader import Handler, SaxReader
except:
    from Ft.Lib.pDomletteReader import Handler, SaxReader
from ALAbstraction import Element, RecipeElement, ActionElement, TransformElement
from readers import ALSaxHandler, Reader
from narval.lib import PrettyPrint
    
class ParserKnownValues(unittest.TestCase):
    """
    This class check that source_vector functions give known result
    with known input
    """
    
    def setUp (self):
        """ called before each test from this class """
        self.nl1, self.nl2 = [], []
        self.DATA1 = cStringIO.StringIO("""
<memory>
  <mailbox path="/var/spool/mail/syt"/>
  <email_addr mine="yes">syt@logilab.org</email_addr>
  <server-socket1 port="7776" recipe="pia.PDA"/>
</memory>
""")
        self.DATA2 = cStringIO.StringIO("""
<al:cookbook xmlns:al='http://www.logilab.org/namespaces/Narval/1.2' group='test'>
  <al:recipe name='update_bmf' group='bkmonitor' restart='no'>
    <al:description lang='en'>create or update the xbel bookmark file from
    different formats</al:description>
    <al:step id='Update_bmf.0.Bookmarks.parse_bmf' type='action' target='Bookmarks.parse_bmf'>
      <al:label lang='en'>convert original bookmarks file into an xbel element</al:label>
      <al:output id='output'>
        <al:match>xbel</al:match>
      </al:output>
    </al:step>
    <al:step id='Update_bmf.1.Bookmarks.update_bmf' type='action' target='Bookmarks.update_bmf'>
      <al:label lang='en'>Update the old xbel file</al:label>
      <al:arguments>
        <bookmark-file type='xbel'>$NARVAL_HOME/data/bookmarks.xbel</bookmark-file>
      </al:arguments>
    </al:step>
    <al:transition id='Update_bmf.2'>
      <al:in idref='Update_bmf.0.Bookmarks.parse_bmf'/>
      <al:out idref='Update_bmf.1.Bookmarks.update_bmf'/>
      <al:time seconds="0,30"/>
    </al:transition>
  </al:recipe>        
  <al:recipe name='false' group='false'>
  </al:recipe>

  <xsl:transform xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
  <xsl:strip-space elements='*'/>
  <xsl:output method='xml'/>
  <!-- Narval prototype ====================================================== -->
  <al:prototype>
  <al:description lang="fr">transforme un élément rss en data-unit.</al:description>
  <al:description lang="en">changes rss to data-unit</al:description>
  <al:input id='input' list='yes'><al:match>rss</al:match>
  <al:description lang="en">rss elements to transform</al:description></al:input>
  <al:output id='output' list='yes'><al:match>data-unit[url]</al:match>
  <al:description lang="en">data-unit "ready to download" (you have to download its
  data before the sort)</al:description></al:output>
  </al:prototype>
  <!-- root ================================================================== -->
  <xsl:template match='rss/channel/item'>
    <data-unit>
      <url><xsl:value-of select='link'/></url>
      <channel-title><xsl:value-of select='../title'/></channel-title>
      <title><xsl:value-of select='title'/></title>
      <data><xsl:apply-templates mode='multi' select='description'/>
      </data>
      <description><xsl:apply-templates mode='multi' select='description'/>
      </description>
    </data-unit>
  </xsl:template>
  </xsl:transform>
  
  <al:action name='naughty_action_2' func='non_existent_f'>
          <al:output id='output' list='yes'><al:match>element</al:match></al:output>
  </al:action>
</al:cookbook>
""")

        
    def test_known_values(self):
        """
        should give known result with known input
        """
        dh = ALSaxHandler(level=0)
        p = make_parser(["xml.sax.drivers2.drv_xmlproc"])
        p.setContentHandler(dh)
        p.setFeature(feature_namespaces, 1)
        p.parse(self.DATA1)
        self.assert_(len(dh.elements) == 1, 'Wrong elements number')
        self.assert_(isinstance(dh.elements[0], Element))
        # suite 
        p = make_parser(["xml.sax.drivers2.drv_xmlproc"])
        dh = ALSaxHandler(level=1)
        p.setContentHandler(dh)
        p.parse(self.DATA2)
        self.assert_(len(dh.elements) == 4, 'Wrong elements number')
        correct = (RecipeElement, RecipeElement, TransformElement, ActionElement)
        for i in range(len(dh.elements)):
            element = dh.elements[i]
            #print '-'*80
            #print element.as_xml()
            self.assert_(isinstance(element, correct[i]))
            # FIX ME: test objects+prototype and reader

    def test_dom_known_values(self):
        """
        should give known result with known input
        """
        r = SaxReader()
        d = r.fromStream(self.DATA1).documentElement
        r = Reader()
        elements = r.fromDOM(d, 0)
        self.assert_(len(elements) == 1, 'Wrong elements number')
        self.assert_(isinstance(elements[0], Element))
        # suite 
        r = SaxReader()
        d = r.fromStream(self.DATA2).documentElement
        r = Reader()
        elements = r.fromDOM(d, 1)
        self.assert_(len(elements) == 4, 'Wrong elements number')
        correct = (RecipeElement, RecipeElement, TransformElement, ActionElement)
        for i in range(len(elements)):
            element = elements[i]
            #print '-'*80
            #print element.as_xml()
            self.assert_(isinstance(element, correct[i]))
        
if __name__ == '__main__':
    
    testsuite = unittest.TestSuite()
    testsuite.addTest(ParserKnownValues("test_known_values"))
    testsuite.addTest(ParserKnownValues("test_dom_known_values"))

    test = unittest.TextTestRunner()

    # uncomment next line to write tests results in a file
    #test.__init__(open('unittest.log','w+'))    

    test.run(testsuite)
