[Zope3-checkins] CVS: Zope3/src/zope/tal/tests - __init__.py:1.1.2.1 markbench.py:1.1.2.1 run.py:1.1.2.1 test_files.py:1.1.2.1 test_htmltalparser.py:1.1.2.1 test_sourcepos.py:1.1.2.1 test_talinterpreter.py:1.1.2.1 test_xmlparser.py:1.1.2.1 utils.py:1.1.2.1

Jim Fulton jim@zope.com
Mon, 23 Dec 2002 14:33:31 -0500


Update of /cvs-repository/Zope3/src/zope/tal/tests
In directory cvs.zope.org:/tmp/cvs-serv19908/zope/tal/tests

Added Files:
      Tag: NameGeddon-branch
	__init__.py markbench.py run.py test_files.py 
	test_htmltalparser.py test_sourcepos.py test_talinterpreter.py 
	test_xmlparser.py utils.py 
Log Message:
Initial renaming before debugging

=== Added File Zope3/src/zope/tal/tests/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/tal/tests/markbench.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
'''Run benchmarks of TAL vs. DTML'''

try:
    import warnings
except ImportError:
    pass
else:
    warnings.filterwarnings("ignore", category=DeprecationWarning)

import os
os.environ['NO_SECURITY'] = 'true'

import sys
import time

from cStringIO import StringIO

#from DocumentTemplate.DT_HTML import HTMLFile

from zope.tal.htmltalparser import HTMLTALParser
from zope.tal.talinterpreter import TALInterpreter
from zope.tal.dummyengine import DummyEngine


def time_apply(f, args, kwargs, count):
    r = [None] * count
    for i in range(4):
        f(*args, **kwargs)
    t0 = time.clock()
    for i in r:
        pass
    t1 = time.clock()
    for i in r:
        f(*args, **kwargs)
    t = time.clock() - t1 - (t1 - t0)
    return t / count

def time_zpt(fn, count):
    from zope.pagetemplate.pagetemplate import PageTemplate
    pt = PageTemplate()
    pt.write(open(fn).read())
    return time_apply(pt.pt_render, (data,), {}, count)

def time_tal(fn, count):
    p = HTMLTALParser()
    p.parseFile(fn)
    program, macros = p.getCode()
    engine = DummyEngine(macros)
    engine.globals = data
    tal = TALInterpreter(program, macros, engine, StringIO(), wrap=0,
                         tal=1, strictinsert=0)
    return time_apply(tal, (), {}, count)

def time_dtml(fn, count):
    html = HTMLFile(fn)
    return time_apply(html, (), data, count)

def profile_zpt(fn, count, profiler):
    from Products.PageTemplates.PageTemplate import PageTemplate
    pt = PageTemplate()
    pt.write(open(fn).read())
    for i in range(4):
        pt.pt_render(extra_context=data)
    r = [None] * count
    for i in r:
        profiler.runcall(pt.pt_render, 0, data)

def profile_tal(fn, count, profiler):
    p = HTMLTALParser()
    p.parseFile(fn)
    program, macros = p.getCode()
    engine = DummyEngine(macros)
    engine.globals = data
    tal = TALInterpreter(program, macros, engine, StringIO(), wrap=0,
                         tal=1, strictinsert=0)
    for i in range(4):
        tal()
    r = [None] * count
    for i in r:
        profiler.runcall(tal)

tal_fn = 'benchmark/tal%.2d.html'
dtml_fn = 'benchmark/dtml%.2d.html'

def compare(n, count, profiler=None):
    t1 = int(time_zpt(tal_fn % n, count) * 1000 + 0.5)
    t2 = int(time_tal(tal_fn % n, count) * 1000 + 0.5)
    t3 = 'n/a' # int(time_dtml(dtml_fn % n, count) * 1000 + 0.5)
    print '%.2d: %10s %10s %10s' % (n, t1, t2, t3)
    if profiler:
        profile_tal(tal_fn % n, count, profiler)

def main(count, profiler=None):
    n = 1
    print '##: %10s %10s %10s' % ('ZPT', 'TAL', 'DTML')
    while os.path.isfile(tal_fn % n) and os.path.isfile(dtml_fn % n):
        compare(n, count, profiler)
        n = n + 1

data = {'x':'X', 'r2': range(2), 'r8': range(8), 'r64': range(64)}
for i in range(10):
    data['x%s' % i] = 'X%s' % i

if __name__ == "__main__":
    filename = "markbench.prof"
    profiler = None
    if len(sys.argv) > 1 and sys.argv[1] == "-p":
        import profile
        profiler = profile.Profile()
        del sys.argv[1]

    if len(sys.argv) > 1:
        for arg in sys.argv[1:]:
            compare(int(arg), 25, profiler)
    else:
        main(25, profiler)

    if profiler is not None:
        profiler.dump_stats(filename)
        import pstats
        p = pstats.Stats(filename)
        p.strip_dirs()
        p.sort_stats('time', 'calls')
        try:
            p.print_stats(20)
        except IOError, e:
            if e.errno != errno.EPIPE:
                raise


=== Added File Zope3/src/zope/tal/tests/run.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Run all tests."""

import sys
import zope.tal.tests.utils
import unittest
import zope.tal.tests.test_htmltalparser
import zope.tal.tests.test_talinterpreter
import zope.tal.tests.test_files
import zope.tal.tests.test_sourcepos

def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(test_htmltalparser.test_suite())
    if not utils.skipxml:
        import test_xmlparser
        suite.addTest(test_xmlparser.test_suite())
    suite.addTest(test_talinterpreter.test_suite())
    suite.addTest(test_files.test_suite())
    suite.addTest(test_sourcepos.test_suite())
    return suite

def main():
    return utils.run_suite(test_suite())

if __name__ == "__main__":
    errs = main()
    sys.exit(errs and 1 or 0)


=== Added File Zope3/src/zope/tal/tests/test_files.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Tests that run driver.py over input files comparing to output files."""

import os
import sys
import glob

from Zope.TAL.tests import utils
import unittest

from Zope.TAL import runtest

class FileTestCase(unittest.TestCase):

    def __init__(self, file, dir):
        self.__file = file
        self.__dir = dir
        unittest.TestCase.__init__(self)

    # For unittest.
    def shortDescription(self):
        path = os.path.basename(self.__file)
        return '%s (%s)' % (path, self.__class__)

    def runTest(self):
        basename = os.path.basename(self.__file)
        #sys.stdout.write(basename + " ")
        sys.stdout.flush()
        if basename.startswith('test_metal'):
            sys.argv = ["", "-Q", "-m", self.__file]
        else:
            sys.argv = ["", "-Q", self.__file]
        pwd = os.getcwd()
        try:
            try:
                os.chdir(self.__dir)
                runtest.main()
            finally:
                os.chdir(pwd)
        except SystemExit, what:
            if what.code:
                self.fail("output for %s didn't match" % self.__file)

try:
    script = __file__
except NameError:
    script = sys.argv[0]

def test_suite():
    suite = unittest.TestSuite()
    dir = os.path.dirname(script)
    dir = os.path.abspath(dir)
    parentdir = os.path.dirname(dir)
    prefix = os.path.join(dir, "input", "test*.")
    if utils.skipxml:
        xmlargs = []
    else:
        xmlargs = glob.glob(prefix + "xml")
        xmlargs.sort()
    htmlargs = glob.glob(prefix + "html")
    htmlargs.sort()
    args = xmlargs + htmlargs
    if not args:
        sys.stderr.write("Warning: no test input files found!!!\n")
    for arg in args:
        case = FileTestCase(arg, parentdir)
        suite.addTest(case)
    return suite

if __name__ == "__main__":
    errs = utils.run_suite(test_suite())
    sys.exit(errs and 1 or 0)


=== Added File Zope3/src/zope/tal/tests/test_htmltalparser.py === (760/860 lines abridged)
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Tests for the HTMLTALParser code generator."""

import pprint
import sys

from Zope.TAL.tests import utils
import unittest


from Zope.TAL import HTMLTALParser
from zope.tal.taldefs import TAL_VERSION, TALError, METALError


class TestCaseBase(unittest.TestCase):

    prologue = ""
    epilogue = ""
    initial_program = [('version', TAL_VERSION), ('mode', 'html')]
    final_program = []

    def _merge(self, p1, p2):
        if p1 and p2:
            op1, args1 = p1[-1]
            op2, args2 = p2[0]
            if op1.startswith('rawtext') and op2.startswith('rawtext'):
                return (p1[:-1]
                        + [rawtext(args1[0] + args2[0])]
                        + p2[1:])
        return p1+p2

    def _run_check(self, source, program, macros={}):
        parser = HTMLTALParser.HTMLTALParser()
        parser.parseString(self.prologue + source + self.epilogue)
        got_program, got_macros = parser.getCode()
        program = self._merge(self.initial_program, program)
        program = self._merge(program, self.final_program)

[-=- -=- -=- 760 lines omitted -=- -=- -=-]

        self._run_check('''\
<p i18n:translate="verify">Your contact email address is recorded as
    <a href="mailto:user@example.com"
       tal:content="request/submitter"
       i18n:name="email">user@host.com</a>
</p>
''', [
  ('setPosition', (1, 0)),
  ('beginScope', {'i18n:translate': 'verify'}),
  ('startTag', ('p', [('i18n:translate', 'verify', 'i18n')])),
  ('insertTranslation',
   ('verify',
    [('rawtextBeginScope',
      ('Your contact email address is recorded as\n    ',
       4,
       (2, 4),
       0,
       {'href': 'mailto:user@example.com',
        'i18n:name': 'email',
        'tal:content': 'request/submitter'})),
     ('i18nVariable',
      ('email',
       [('startTag',
         ('a',
          [('href', 'href="mailto:user@example.com"'),
           ('tal:content', 'request/submitter', 'tal'),
           ('i18n:name', 'email', 'i18n')])),
        ('insertText',
         ('$request/submitter$',
          [('rawtextOffset', ('user@host.com', 13))])),
        ('rawtextOffset', ('</a>', 4))],
       None)),
     ('endScope', ()),
     ('rawtextColumn', ('\n', 0))])),
  ('endScope', ()),
  ('rawtextColumn', ('</p>\n', 0))
  ])


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(HTMLTALParserTestCases, "check_"))
    suite.addTest(unittest.makeSuite(METALGeneratorTestCases, "check_"))
    suite.addTest(unittest.makeSuite(TALGeneratorTestCases, "check_"))
    return suite


if __name__ == "__main__":
    errs = utils.run_suite(test_suite())
    sys.exit(errs and 1 or 0)


=== Added File Zope3/src/zope/tal/tests/test_sourcepos.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Tests for TALInterpreter."""

import sys
import unittest

from StringIO import StringIO

from zope.tal.htmltalparser import HTMLTALParser
from zope.tal.talinterpreter import TALInterpreter
from zope.tal.talgenerator import TALGenerator
from zope.tal.dummyengine import DummyEngine


page1 = '''<html metal:use-macro="main"><body>
<div metal:fill-slot="body">
page1=<span tal:replace="position:" />
</div>
</body></html>'''

main_template = '''<html metal:define-macro="main"><body>
main_template=<span tal:replace="position:" />
<div metal:define-slot="body" />
main_template=<span tal:replace="position:" />
<div metal:use-macro="foot" />
main_template=<span tal:replace="position:" />
</body></html>'''

footer = '''<div metal:define-macro="foot">
footer=<span tal:replace="position:" />
</div>'''

expected = '''<html><body>
main_template=main_template (2,14)
<div>
page1=page1 (3,6)
</div>
main_template=main_template (4,14)
<div>
footer=footer (2,7)
</div>
main_template=main_template (6,14)
</body></html>'''



class Tests(unittest.TestCase):

    def parse(self, eng, s, fn):
        gen = TALGenerator(expressionCompiler=eng, xml=0, source_file=fn)
        parser = HTMLTALParser(gen)
        parser.parseString(s)
        program, macros = parser.getCode()
        return program, macros

    def testSourcePositions(self):
        # Ensure source file and position are set correctly by TAL
        macros = {}
        eng = DummyEngine(macros)
        page1_program, page1_macros = self.parse(eng, page1, 'page1')
        main_template_program, main_template_macros = self.parse(
            eng, main_template, 'main_template')
        footer_program, footer_macros = self.parse(eng, footer, 'footer')

        macros['main'] = main_template_macros['main']
        macros['foot'] = footer_macros['foot']

        stream = StringIO()
        interp = TALInterpreter(page1_program, macros, eng, stream)
        interp()
        self.assertEqual(stream.getvalue().strip(), expected.strip(),
                         "Got result:\n%s\nExpected:\n%s"
                         % (stream.getvalue(), expected))


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Tests))
    return suite


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


=== Added File Zope3/src/zope/tal/tests/test_talinterpreter.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Tests for TALInterpreter."""

import sys

from Zope.TAL.tests import utils
import unittest

from StringIO import StringIO

from zope.tal.taldefs import METALError, I18NError
from zope.tal.htmltalparser import HTMLTALParser
from zope.tal.talinterpreter import TALInterpreter
from zope.tal.dummyengine import DummyEngine


class TestCaseBase(unittest.TestCase):

    def _compile(self, source):
        parser = HTMLTALParser()
        parser.parseString(source)
        program, macros = parser.getCode()
        return program, macros


class MacroErrorsTestCase(TestCaseBase):

    def setUp(self):
        dummy, macros = self._compile('<p metal:define-macro="M">Booh</p>')
        self.macro = macros['M']
        self.engine = DummyEngine(macros)
        program, dummy = self._compile('<p metal:use-macro="M">Bah</p>')
        self.interpreter = TALInterpreter(program, {}, self.engine)

    def tearDown(self):
        try:
            self.interpreter()
        except METALError:
            pass
        else:
            self.fail("Expected METALError")

    def check_mode_error(self):
        self.macro[1] = ("mode", "duh")

    def check_version_error(self):
        self.macro[0] = ("version", "duh")


class I18NErrorsTestCase(TestCaseBase):

    def _check(self, src, msg):
        try:
            self._compile(src)
        except I18NError:
            pass
        else:
            self.fail(msg)

    def check_id_with_replace(self):
        self._check('<p i18n:id="foo" tal:replace="string:splat"></p>',
                    "expected i18n:id with tal:replace to be denied")

    def check_missing_values(self):
        self._check('<p i18n:attributes=""></p>',
                    "missing i18n:attributes value not caught")
        self._check('<p i18n:data=""></p>',
                    "missing i18n:data value not caught")
        self._check('<p i18n:id=""></p>',
                    "missing i18n:id value not caught")


class OutputPresentationTestCase(TestCaseBase):

    def check_attribute_wrapping(self):
        # To make sure the attribute-wrapping code is invoked, we have to
        # include at least one TAL/METAL attribute to avoid having the start
        # tag optimized into a rawtext instruction.
        INPUT = r"""
        <html this='element' has='a' lot='of' attributes=', so' the='output'
              needs='to' be='line' wrapped='.' tal:define='foo nothing'>
        </html>"""
        EXPECTED = r'''
        <html this="element" has="a" lot="of"
              attributes=", so" the="output" needs="to"
              be="line" wrapped=".">
        </html>''' "\n"
        self.compare(INPUT, EXPECTED)

    def check_entities(self):
        INPUT = ('<img tal:define="foo nothing" '
                 'alt="&a; &#1; &#x0a; &a &#45 &; &#0a; <>" />')
        EXPECTED = ('<img alt="&a; &#1; &#x0a; '
                    '&amp;a &amp;#45 &amp;; &amp;#0a; &lt;&gt;" />\n')
        self.compare(INPUT, EXPECTED)
                     
    def compare(self, INPUT, EXPECTED):
        program, macros = self._compile(INPUT)
        sio = StringIO()
        interp = TALInterpreter(program, {}, DummyEngine(), sio, wrap=60)
        interp()
        self.assertEqual(sio.getvalue(), EXPECTED)

def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(I18NErrorsTestCase, "check_"))
    suite.addTest(unittest.makeSuite(MacroErrorsTestCase, "check_"))
    suite.addTest(unittest.makeSuite(OutputPresentationTestCase, "check_"))
    return suite


if __name__ == "__main__":
    errs = utils.run_suite(test_suite())
    sys.exit(errs and 1 or 0)


=== Added File Zope3/src/zope/tal/tests/test_xmlparser.py ===
#! /usr/bin/env python
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Tests for XMLParser.py."""

import sys
from types import ListType

from Zope.TAL.tests import utils
import unittest

from Zope.TAL import XMLParser


class EventCollector(XMLParser.XMLParser):

    def __init__(self):
        self.events = []
        self.append = self.events.append
        XMLParser.XMLParser.__init__(self)
        self.parser.ordered_attributes = 1

    def get_events(self):
        # Normalize the list of events so that buffer artefacts don't
        # separate runs of contiguous characters.
        L = []
        prevtype = None
        for event in self.events:
            type = event[0]
            if type == prevtype == "data":
                L[-1] = ("data", L[-1][1] + event[1])
            else:
                L.append(event)
            prevtype = type
        self.events = L
        return L

    # structure markup

    def StartElementHandler(self, tag, attrs):
        self.append(("starttag", tag, attrs))

    def EndElementHandler(self, tag):
        self.append(("endtag", tag))

    # all other markup

    def CommentHandler(self, data):
        self.append(("comment", data))

    def handle_charref(self, data):
        self.append(("charref", data))

    def CharacterDataHandler(self, data):
        self.append(("data", data))

    def StartDoctypeDeclHandler(self, rootelem, publicId, systemId, subset):
        self.append(("doctype", rootelem, systemId, publicId, subset))

    def XmlDeclHandler(self, version, encoding, standalone):
        self.append(("decl", version, encoding, standalone))

    def ExternalEntityRefHandler(self, data):
        self.append(("entityref", data))

    def ProcessingInstructionHandler(self, target, data):
        self.append(("pi", target, data))


class EventCollectorExtra(EventCollector):

    def handle_starttag(self, tag, attrs):
        EventCollector.handle_starttag(self, tag, attrs)
        self.append(("starttag_text", self.get_starttag_text()))


class SegmentedFile:
    def __init__(self, parts):
        self.parts = list(parts)

    def read(self, bytes):
        if self.parts:
            s = self.parts.pop(0)
        else:
            s = ''
        return s


class XMLParserTestCase(unittest.TestCase):

    def _run_check(self, source, events, collector=EventCollector):
        parser = collector()
        if isinstance(source, ListType):
            parser.parseStream(SegmentedFile(source))
        else:
            parser.parseString(source)
        self.assertEquals(parser.get_events(),events)

    def _run_check_extra(self, source, events):
        self._run_check(source, events, EventCollectorExtra)

    def _parse_error(self, source):
        def parse(source=source):
            parser = XMLParser.XMLParser()
            parser.parseString(source)
        self.assertRaises(XMLParser.XMLParseError, parse)

    def check_processing_instruction_plus(self):
        self._run_check("<?processing instruction?><a/>", [
            ("pi", "processing", "instruction"),
            ("starttag", "a", []),
            ("endtag", "a"),
            ])

    def _check_simple_html(self):
        self._run_check("""\
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE html PUBLIC 'foo' 'bar'>
<html>&entity;&#32;
<!--comment1a
-></foo><bar>&lt;<?pi?></foo<bar
comment1b-->
<img src='Bar' ismap=''/>sample
text
<!--comment2a- -comment2b-->
</html>
""", [
    ("decl", "1.0", "iso-8859-1", -1),
    ("doctype", "html", "foo", "bar", 0),
    ("starttag", "html", []),
#    ("entityref", "entity"),
    ("data", " \n"),
    ("comment", "comment1a\n-></foo><bar>&lt;<?pi?></foo<bar\ncomment1b"),
    ("data", "\n"),
    ("starttag", "img", ["src", "Bar", "ismap", ""]),
    ("endtag", "img"),
    ("data", "sample\ntext\n"),
    ("comment", "comment2a- -comment2b"),
    ("data", "\n"),
    ("endtag", "html"),
    ])

    def check_bad_nesting(self):
        try:
            self._run_check("<a><b></a></b>", [
                ("starttag", "a", []),
                ("starttag", "b", []),
                ("endtag", "a"),
                ("endtag", "b"),
                ])
        except:
            e = sys.exc_info()[1]
            self.assert_(e.lineno == 1,
                         "did not receive correct position information")
        else:
            self.fail("expected parse error: bad nesting")

    def check_attr_syntax(self):
        output = [
          ("starttag", "a", ["b", "v", "c", "v"]),
          ("endtag", "a"),
          ]
        self._run_check("""<a b='v' c="v"/>""", output)
        self._run_check("""<a  b = 'v' c = "v"/>""", output)
        self._run_check("""<a\nb\n=\n'v'\nc\n=\n"v"\n/>""", output)
        self._run_check("""<a\tb\t=\t'v'\tc\t=\t"v"\t/>""", output)

    def check_attr_values(self):
        self._run_check("""<a b='xxx\n\txxx' c="yyy\t\nyyy" d='\txyz\n'/>""",
                        [("starttag", "a", ["b", "xxx  xxx",
                                            "c", "yyy  yyy",
                                            "d", " xyz "]),
                         ("endtag", "a"),
                         ])
        self._run_check("""<a b='' c="" d=''/>""", [
            ("starttag", "a", ["b", "", "c", "", "d", ""]),
            ("endtag", "a"),
            ])

    def check_attr_entity_replacement(self):
        self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'/>""", [
            ("starttag", "a", ["b", "&><\"'"]),
            ("endtag", "a"),
            ])

    def check_attr_funky_names(self):
        self._run_check("""<a a.b='v' c:d='v' e-f='v'/>""", [
            ("starttag", "a", ["a.b", "v", "c:d", "v", "e-f", "v"]),
            ("endtag", "a"),
            ])

    def check_starttag_end_boundary(self):
        self._run_check("""<a b='&lt;'/>""", [
            ("starttag", "a", ["b", "<"]),
            ("endtag", "a"),
            ])
        self._run_check("""<a b='&gt;'/>""", [
            ("starttag", "a", ["b", ">"]),
            ("endtag", "a"),
            ])

    def check_buffer_artefacts(self):
        output = [("starttag", "a", ["b", "<"]), ("endtag", "a")]
        self._run_check(["<a b='&lt;'/>"], output)
        self._run_check(["<a ", "b='&lt;'/>"], output)
        self._run_check(["<a b", "='&lt;'/>"], output)
        self._run_check(["<a b=", "'&lt;'/>"], output)
        self._run_check(["<a b='&lt;", "'/>"], output)
        self._run_check(["<a b='&lt;'", "/>"], output)

        output = [("starttag", "a", ["b", ">"]), ("endtag", "a")]
        self._run_check(["<a b='&gt;'/>"], output)
        self._run_check(["<a ", "b='&gt;'/>"], output)
        self._run_check(["<a b", "='&gt;'/>"], output)
        self._run_check(["<a b=", "'&gt;'/>"], output)
        self._run_check(["<a b='&gt;", "'/>"], output)
        self._run_check(["<a b='&gt;'", "/>"], output)

    def check_starttag_junk_chars(self):
        self._parse_error("<")
        self._parse_error("<>")
        self._parse_error("</>")
        self._parse_error("</$>")
        self._parse_error("</")
        self._parse_error("</a")
        self._parse_error("</a")
        self._parse_error("<a<a>")
        self._parse_error("</a<a>")
        self._parse_error("<$")
        self._parse_error("<$>")
        self._parse_error("<!")
        self._parse_error("<a $>")
        self._parse_error("<a")
        self._parse_error("<a foo='bar'")
        self._parse_error("<a foo='bar")
        self._parse_error("<a foo='>'")
        self._parse_error("<a foo='>")

    def check_declaration_junk_chars(self):
        self._parse_error("<!DOCTYPE foo $ >")


# Support for the Zope regression test framework:
def test_suite(skipxml=utils.skipxml):
    suite = unittest.TestSuite()
    if not skipxml:
        suite.addTest(unittest.makeSuite(XMLParserTestCase, "check_"))
    return suite


if __name__ == "__main__":
    errs = utils.run_suite(test_suite(skipxml=0))
    sys.exit(errs and 1 or 0)


=== Added File Zope3/src/zope/tal/tests/utils.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Helper functions for the test suite."""

import os
import sys

mydir = os.path.abspath(os.path.dirname(__file__))
codedir = os.path.dirname(os.path.dirname(os.path.dirname(mydir)))

if codedir not in sys.path:
    sys.path.append(codedir)

import unittest


# Set skipxml to true if an XML parser could not be found.
skipxml = 0
try:
    import xml.parsers.expat
except ImportError:
    skipxml = 1


def run_suite(suite, outf=None, errf=None):
    if outf is None:
        outf = sys.stdout
    runner = unittest.TextTestRunner(outf)
    result = runner.run(suite)

##     print "\n\n"
##     if result.errors:
##         print "Errors (unexpected exceptions):"
##         map(print_error, result.errors)
##         print
##     if result.failures:
##         print "Failures (assertion failures):"
##         map(print_error, result.failures)
##         print
    newerrs = len(result.errors) + len(result.failures)
    if newerrs:
        print "'Errors' indicate exceptions other than AssertionError."
        print "'Failures' indicate AssertionError"
        if errf is None:
            errf = sys.stderr
        errf.write("%d errors, %d failures\n"
                   % (len(result.errors), len(result.failures)))
    return newerrs


def print_error(info):
    testcase, (type, e, tb) = info