"""
$RCSfile: TestExternalFile.py,v $
Unit tests for ExternalFile product

Author: <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
Release: 1.2
"""

__cvstag__  = '$Name:  $'[6:-2]
__date__    = '$Date: 2003/04/21 00:56:27 $'[6:-2]
__version__ = '$Revision: 1.8 $'[10:-2]

from cStringIO import StringIO
import os, sys, tempfile, time, urllib

if __name__ == '__main__':
    execfile(os.path.join(sys.path[0], 'framework.py'))

# Load fixture
from Testing import ZopeTestCase

from Products.ExternalFile import ExternalFile

ZopeTestCase.installProduct('ExternalFile')
ZopeTestCase.installProduct('PageTemplates')

from Testing.ZopeTestCase import _folder_name, _standard_permissions
host, port = ZopeTestCase.utils.startZServer(3)
base = 'http://%s:%d/%s' %(host, port, _folder_name)

class ExternalFileTestCase(ZopeTestCase.ZopeTestCase):
    "Unit tests for ExternalFile product"

    ################################################################
    # Fixture
    ################################################################

    def beforeSetUp(self):
        get_transaction().begin()

    def beforeClose(self):
        # Commit the cleared app
        get_transaction().commit()

    def afterClear(self):
        '''Clean up after myself'''
        pass

    ################################################################
    # Test Cases
    ################################################################

    def test_01(self):
        "Ensure that an ExternalFile cannot be created with a blank ID"
        self.assertRaises(Exception, ExternalFile.addInstance,
                          self.folder, id='')

    def test_02(self):
        "Test ExternalFile pointing to non-existing file"
        ef = ExternalFile.addInstance(self.folder, 'foo',
                                      target_filepath='i/dont/exist')
        self.assertEquals(ef.getFilepath(self.app.REQUEST),
                          os.path.normpath('i/dont/exist'))
        result = ef.getContents(self.app.REQUEST)
        self.assertEquals(result.__class__, IOError)

    def test_03(self):
        "Test ExternalFile pointing to zero-length file"

        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder, 'ascii',
                                      target_filepath=filename)
        self.assertEquals(ef.getFilepath(self.app.REQUEST), filename)
        self.assertEquals(ef.getContents(self.app.REQUEST), "")
        self.assertEquals(ef.getDisplayType(),'ascii')
        self.assertEquals(len(ef), 0)
        os.remove(filename)

    def test_04(self):
        "Test ExernalFile pointing to ASCII text file"

        filename = 'testfiles/test.xml'
        xmlFile  = open(filename,'rb')
        ef = ExternalFile.addInstance(self.folder, 'test.xml',
                                      target_filepath=filename)
        self.assertEquals(ef.getContents(self.app.REQUEST),
                          xmlFile.read())

    def test_05(self):
        "Test ExternalFile pointing to a binary (PDF) file"

        filename = 'testfiles/test.pdf'
        pdfFile  = open(filename,'rb')
        ef = ExternalFile.addInstance(self.folder, 'test.pdf',
                                      target_filepath=filename)
        self.assertEquals(ef.getDisplayType(),'binary')
        self.assertEquals(ef.getContentType(),'application/pdf')

    def test_06(self):
        "Test ExternalFile pointing to an image file"

        filename = 'testfiles/test.gif'
        gifFile  = open(filename,'rb')
        ef = ExternalFile.addInstance(self.folder, 'test.gif',
                                      target_filepath=filename)
        self.assertEquals(ef.getDisplayType(),'image')
        self.assertEquals(ef.getContentType(),'image/gif')

    def test_07(self):
        "Test setContents"
        testcontent  = 'this is some test content'
        testcontent2 = 'but this is totally different content'
        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder,
                                      'ascii', 'Ascii File',
                                      'I am ASCII', filename)
        self.assertEquals(ef.getContents(self.app.REQUEST),
                          testcontent)
        modtime = ef.getModTime(self.app.REQUEST)

        # First sleep for 4 seconds to ensure we get a different
        # number from bobobase_modification_time()
        time.sleep(4)
        # Change the contents

        ef.setContents(testcontent2)
        self.assertEquals(ef.getContents(self.app.REQUEST),
                          testcontent2)
        self.failUnless(ef.getModTime(self.app.REQUEST) !=
                        modtime)
        os.remove(filename)

    def test_08(self):
        "Test behave_like DTMLDocument vs File"
        testcontent  = 'This is the <dtml-var title> Document.'
        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder,
                                      'test','Testing',
                                      target_filepath=filename)
        # default behave_like is DTMLDocument
        self.assertEquals(ef(ef, self.app.REQUEST),
                          'This is the Testing Document.')

        ef.behave_like = 'File'
        #
        # with behave_like == File, 
        # without a REQUEST we just get back the raw content
        # with a REQUEST it streams the output to the RESPONSE
        #
        # 1) Test without a REQUEST
        self.assertEquals(ef(ef), testcontent)

        response = self.app.REQUEST['RESPONSE']
        #
        # 2) Test with a REQUEST
        # replace sys.stdout with our own buffer, so we can capture
        # it, otherwise the streamed output will appear on the
        # console
        #
        response.stdout = StringIO()
        ef(ef, self.app.REQUEST)
        self.failUnless(response.stdout.getvalue().find(
            testcontent) != -1)

    def test_09(self):
        "Test behave_like PageTemplate vs File"
        testcontent  = '<span tal:replace="here/id">nothing</span>'
        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder,
                                      'test','Testing',
                                      target_filepath=filename)
        ef.behave_like  = 'PageTemplate'
        ef.content_type = 'text/html'

        self.assertEquals(ef(ef, self.app.REQUEST).strip(),
                          'test')

        ef.behave_like = 'File'
        
        # with behave_like == File, 
        # without a REQUEST we just get back the raw content
        # with a REQUEST it streams the output to the RESPONSE
        #
        # 1) Test without a REQUEST
        self.assertEquals(ef(ef), testcontent)

        response = self.app.REQUEST['RESPONSE']
        #
        # 2) Test with a REQUEST
        # replace sys.stdout with our own buffer, so we can capture
        # it, otherwise the streamed output will appear on the
        # console
        #
        response.stdout = StringIO()
        ef(ef, self.app.REQUEST)
        self.failUnless(response.stdout.getvalue().find(
            testcontent) != -1)

    def test_10(self):
        "Test adding a property and grabbing it as a page template"

        testcontent  = '<span tal:replace="here/who">nothing</span>'
        # if the file did not end with html, we would have to
        # explicitly set the content_type
        filename  = tempfile.mktemp('.html')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder,
                                      'test','Testing',
                                      target_filepath=filename)
        ef.manage_addProperty('who', 'zippy', 'string')
        ef.behave_like  = 'PageTemplate'

        self.assertEquals(ef(ef, self.app.REQUEST).strip(),
                          'zippy')

    def test_11(self):
        "Test adding a property and grabbing it as a dtml doc or dtml method"

        testcontent  = '<dtml-var who> says hello'
        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()

        ef = ExternalFile.addInstance(self.folder,
                                      'test','Testing',
                                      target_filepath=filename)
        ef.manage_addProperty('who', 'zippy', 'string')
        ef.behave_like  = 'DTMLDocument'
        ef.content_type = 'text/plain'

        self.assertEquals(ef(ef, self.app.REQUEST),
                          'zippy says hello')

        ef.behave_like  = 'DTMLMethod'
        self.assertEquals(ef(ef, self.app.REQUEST),
                          'zippy says hello')

    def test_12(self):
        "Test adding a property and grabbing it by applying a dtml method"

        testcontent  = '<dtml-var who> says hello'
        filename  = tempfile.mktemp('.txt')
        touchfile = open(filename, 'wb') # create zero-length file
        touchfile.write(testcontent)
        touchfile.close()
        dtmlFile = open(filename, 'rb')
        self.folder.manage_addDTMLMethod('whoisit', '', dtmlFile)

        ef = ExternalFile.addInstance(self.folder,
                                      'test','Testing',
                                      target_filepath=filename)
        ef.manage_addProperty('who', 'zippy', 'string')
        ef.content_type = 'text/plain'

        for type in ExternalFile.ExternalFile.behave_like_list:
            ef.behave_like  = type
            #
            # We must commit the transaction so the ZServer (running in a
            # different thread) can see our new Zope objects when it
            # tries to resolve the relative URL defined in self.folder.properties
            #
            get_transaction().commit()
            
            self.assertEquals(self.folder.test.whoisit(ef, self.app.REQUEST),
                              'zippy says hello')
            
            page = urllib.urlopen(base + '/test/whoisit')
            self.assertEquals(page.read(), 'zippy says hello')

    ################################################################
    # Test Runner Setup
    ################################################################

if __name__ == '__main__':
    framework(descriptions=1, verbosity=2) # 0=quiet 1=default 2=verbose
else:
    # While framework.py provides its own test_suite() 
    # method the testrunner utility does not.
    import unittest
    def test_suite():
        suite = unittest.TestSuite()
        suite.addTest(unittest.makeSuite(ExternalFileTestCase))
        return suite

