#
# Copyright 2001 by Object Craft P/L, Melbourne, Australia.
#
# LICENCE - see LICENCE file distributed with this software for details.
#
#
# Test NameRecorderMixin functionality
#
# Unfortunately, we need to have intimate knowledge of the encoding scheme used
# by the NameRecorderMixin - changes there will need to be reflected here.
#
# $Id: recorder.py,v 1.6 2003/09/21 04:40:31 djc Exp $

import re, os, sys

import unittest
import base64, zlib, cPickle

import albatross

"""
Test field recording action

Set up all the appropriate infrastructure, then run a template that
contains an <al-form>. Check that the resulting html contains a __albform__
hidden field with an appropriate value.
"""
albform_re = re.compile(r'<input type="hidden" name="__albform__" value="([^"]*)" />', re.I|re.M|re.S)

class RecorderTestApp(albatross.Application):
    def __init__(self):
        albatross.Application.__init__(self, 'here')

    def pickle_sign(self, text):
        # albatross.Application discards text, we need a pass-thru
        return text

    def pickle_unsign(self, text):
        return text

class RecorderTestContext(albatross.TemplateLoaderMixin,
                  albatross.AppContext, albatross.NameRecorderMixin,
                  albatross.StubSessionMixin):
    def __init__(self, template_path):
        albatross.TemplateLoaderMixin.__init__(self, template_path)
        albatross.AppContext.__init__(self, RecorderTestApp())
        albatross.NameRecorderMixin.__init__(self)

    def current_url(self):
        return 'here'

class RecorderTestCase(unittest.TestCase):
    template_dir = "recorder"

    def runTest(self):
        base_dir = os.path.dirname(sys.modules[__name__].__file__)
        template_dir = os.path.join(base_dir, self.template_dir)
        self.ctx = RecorderTestContext(template_dir)

        self.ctx.push_content_trap()
        tmpl = self.ctx.load_template("recorder.html")
        tmpl.to_html(self.ctx)
        text = self.ctx.pop_content_trap()

        expect = {'this': 0, 'that': 1}
        result = None
        match = albform_re.search(text)
        self.failUnless(match, 
                        "__albform__ regular expression didn't find anything")
        text = base64.decodestring(match.group(1))
        text = zlib.decompress(text)
        result = cPickle.loads(text)
        self.assertEqual(result, expect)

"""
Test request merging action
"""
merge_data = [
    # var        list?  input           expect
    ('this',     0,     'one',          'one'),
    ('that',     1,     'two',          ['two']),
    ('another',  1,     ['three'],      ['three']),
    ('whatever', 1,     None,           []),
]

class MergeTestRequest:
    def __init__(self):
        self.expect = {}
        self.fields = {}
        self.islist = {}
        for var, islist, input, output in merge_data:
            self.islist[var] = islist
            self.fields[var] = input
            self.expect[var] = output

        text = cPickle.dumps(self.islist, 1)
        text = zlib.compress(text)
        text = base64.encodestring(text)
        self.fields['__albform__'] = text
        self.expect['__page__'] = None
        self.expect['__pages__'] = []

    def has_field(self, field):
        return self.fields.has_key(field)

    def field_value(self, field):
        return self.fields[field]

class MergeTestCase(unittest.TestCase):
    def runTest(self):
        ctx = RecorderTestContext('.')
        ctx.set_request(MergeTestRequest())
        ctx.merge_request()
        got = ctx.locals.__dict__
        self.assertEqual(got, ctx.request.expect)

"""
Test namespace "protection"
"""
class UnderscoreRequest:
    def __init__(self):
        self.__field = '_protected'

    def has_field(self, name):
        return name == self.__field

    def field_value(self, name):
        if name == self.__field:
            return self.__field
        else:
            raise KeyError

    def field_names(self):
        return [self.__field]

class UnderscoreTestCase(unittest.TestCase):
    def runTest(self):
        ctx = RecorderTestContext('.')
        ctx.set_request(UnderscoreRequest())
        self.failUnlessRaises(albatross.SecurityError, ctx.merge_request)

"""
Driver for the above tests
"""

class RecorderSuite(unittest.TestSuite):
    def __init__(self):
        unittest.TestSuite.__init__(self)
        self.addTest(RecorderTestCase())
        self.addTest(MergeTestCase())
        self.addTest(UnderscoreTestCase())

def suite():
    return RecorderSuite()

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