#!/usr/bin/env python
# -*- python -*-
# Copyright (c) 2000-2004, 2007 Tony Garnock-Jones <tonyg@kcbbs.gen.nz>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import ubf
import unittest
import sys

def testFile(name):
    f = open('../tests/encoding-tests/'+name, 'rb')
    text = f.read()
    f.close()
    return text

class CodecTestCase(unittest.TestCase):
    name = None
    def setUp(self):
        if self.name:
            self.text = testFile(self.name)

    def tearDown(self):
        self.text = None

    def testDecoding(self):
        if self.name:
            self.failUnlessEqual(ubf.Decoder(self.text).decode(), self.object)

    def testEncoding(self):
        if self.name and self.doEncode:
            self.failUnlessEqual(ubf.StringEncoder().encode(self.object), self.text)

_a = ubf.Symbol('a')
_b = ubf.Symbol('b')
_c = ubf.Symbol('c')
_d = ubf.Symbol('d')
_hello = ubf.Symbol('hello')

for (caseName, caseObject) in [('ok:bigger-negative-integers', (-123, -234, -345)),
                               ('ok:bizarre-tag-with-backquote', ubf.Tag('a`b', [])),
                               ('ok:bizarre-tag-with-backslash', ubf.Tag('a\\b', [])),
                               ('ok:comment-escaping', (123, 234)),
                               ('ok:double-tag', ubf.Tag('outer', ubf.Tag('inner', []))),
                               ('ok:empty-structure', ()),
                               ('ok:ignore-comments', 123),
                               ('ok:ignore-spaces', ubf.Symbol('hi')),
                               ('ok:large-integer', 123456789123456789L),
                               ('ok:list', [_a, _b]),
                               ('ok:list-of-lists', [[1], [2]]),
                               ('ok:list-with-registers', [_hello, _hello, _hello]),
                               ('ok:negative-integer', -123),
                               ('ok:negative-integers', (-1, -2, -3)),
                               ('ok:register-allocation-sensible', (1,'a',1,'b',1,'c',1,'d',1)),
                               ('ok:small-integer', 123),
                               ('ok:string', 'a"b'),
                               ('ok:struct-of-structs', (_a, (1,), _b, (2,), _c, (3,), _d)),
                               ('ok:struct-of-tagged-values', (ubf.Tag('a', 1),
                                                               ubf.Tag('b', 2),
                                                               ubf.Tag('c', 3))),
                               ('ok:structure-vector', (1, 2, 3)),
                               ('ok:struct-with-comma', (1, 2, 3)),
                               ('ok:structure-with-registers', (_hello, _hello, _hello)),
                               ('ok:symbol', ubf.Symbol("a'b")),
                               ('ok:tagged-structure', ubf.Tag('tag', (1, 2, 3))),
                               ('ok:u8vector', ubf.Binary('abc'))]:
    class Case(CodecTestCase):
        name = caseName
        object = caseObject
        doEncode = True
    Case.__name__ = caseName
    sys.modules[__name__].__dict__[caseName] = Case

for noEncodeName in ['ok:comment-escaping',
                     'ok:struct-with-comma',
                     'ok:ignore-comments',
                     'ok:ignore-spaces']:
    sys.modules[__name__].__dict__[noEncodeName].doEncode = False

for caseName in ['fail:unhandled-ubf-a-opcode',
                 'fail:orphan-tag-outside-struct',
                 'fail:orphan-tag-inside-struct',
                 'fail:orphan-binary-data',
                 'fail:non-integer-binary-data-length',
                 'fail:binary-missing-data',
                 'fail:binary-extra-data',
                 'fail:early-end-of-stream',
                 'fail:early-end-of-string',
                 'fail:empty-stack-at-eom',
                 'fail:extra-close-struct',
                 'fail:non-empty-stack-at-eom']:
    class Case(unittest.TestCase):
        def testFormatException(self):
            def body():
                ubf.Decoder(testFile(caseName)).decode()
            self.failUnlessRaises(ubf.FormatError, body)
    Case.__name__ = caseName
    sys.modules[__name__].__dict__[caseName] = Case

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

