home *** CD-ROM | disk | FTP | other *** search
/ Freelog 33 / Freelog033.iso / Progr / Python-2.2.1.exe / TEST_SAX.PY < prev    next >
Encoding:
Python Source  |  2001-10-24  |  17.8 KB  |  644 lines

  1. # regression test for SAX 2.0
  2. # $Id: test_sax.py,v 1.19 2001/10/24 20:32:02 gvanrossum Exp $
  3.  
  4. from xml.sax import make_parser, ContentHandler, \
  5.                     SAXException, SAXReaderNotAvailable, SAXParseException
  6. try:
  7.     make_parser()
  8. except SAXReaderNotAvailable:
  9.     # don't try to test this module if we cannot create a parser
  10.     raise ImportError("no XML parsers available")
  11. from xml.sax.saxutils import XMLGenerator, escape, quoteattr, XMLFilterBase
  12. from xml.sax.expatreader import create_parser
  13. from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
  14. from cStringIO import StringIO
  15. from test_support import verify, verbose, TestFailed, findfile
  16. import os
  17.  
  18. # ===== Utilities
  19.  
  20. tests = 0
  21. fails = 0
  22.  
  23. def confirm(outcome, name):
  24.     global tests, fails
  25.  
  26.     tests = tests + 1
  27.     if outcome:
  28.         print "Passed", name
  29.     else:
  30.         print "Failed", name
  31.         fails = fails + 1
  32.  
  33. def test_make_parser2():
  34.     try:
  35.         # Creating parsers several times in a row should succeed.
  36.         # Testing this because there have been failures of this kind
  37.         # before.
  38.         from xml.sax import make_parser
  39.         p = make_parser()
  40.         from xml.sax import make_parser
  41.         p = make_parser()
  42.         from xml.sax import make_parser
  43.         p = make_parser()
  44.         from xml.sax import make_parser
  45.         p = make_parser()
  46.         from xml.sax import make_parser
  47.         p = make_parser()
  48.         from xml.sax import make_parser
  49.         p = make_parser()
  50.     except:
  51.         return 0
  52.     else:
  53.         return p
  54.  
  55.  
  56. # ===========================================================================
  57. #
  58. #   saxutils tests
  59. #
  60. # ===========================================================================
  61.  
  62. # ===== escape
  63.  
  64. def test_escape_basic():
  65.     return escape("Donald Duck & Co") == "Donald Duck & Co"
  66.  
  67. def test_escape_all():
  68.     return escape("<Donald Duck & Co>") == "<Donald Duck & Co>"
  69.  
  70. def test_escape_extra():
  71.     return escape("Hei pσ deg", {"σ" : "å"}) == "Hei på deg"
  72.  
  73. # ===== quoteattr
  74.  
  75. def test_quoteattr_basic():
  76.     return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"'
  77.  
  78. def test_single_quoteattr():
  79.     return (quoteattr('Includes "double" quotes')
  80.             == '\'Includes "double" quotes\'')
  81.  
  82. def test_double_quoteattr():
  83.     return (quoteattr("Includes 'single' quotes")
  84.             == "\"Includes 'single' quotes\"")
  85.  
  86. def test_single_double_quoteattr():
  87.     return (quoteattr("Includes 'single' and \"double\" quotes")
  88.             == "\"Includes 'single' and "double" quotes\"")
  89.  
  90. # ===== make_parser
  91.  
  92. def test_make_parser():
  93.     try:
  94.         # Creating a parser should succeed - it should fall back
  95.         # to the expatreader
  96.         p = make_parser(['xml.parsers.no_such_parser'])
  97.     except:
  98.         return 0
  99.     else:
  100.         return p
  101.  
  102.  
  103. # ===== XMLGenerator
  104.  
  105. start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
  106.  
  107. def test_xmlgen_basic():
  108.     result = StringIO()
  109.     gen = XMLGenerator(result)
  110.     gen.startDocument()
  111.     gen.startElement("doc", {})
  112.     gen.endElement("doc")
  113.     gen.endDocument()
  114.  
  115.     return result.getvalue() == start + "<doc></doc>"
  116.  
  117. def test_xmlgen_content():
  118.     result = StringIO()
  119.     gen = XMLGenerator(result)
  120.  
  121.     gen.startDocument()
  122.     gen.startElement("doc", {})
  123.     gen.characters("huhei")
  124.     gen.endElement("doc")
  125.     gen.endDocument()
  126.  
  127.     return result.getvalue() == start + "<doc>huhei</doc>"
  128.  
  129. def test_xmlgen_pi():
  130.     result = StringIO()
  131.     gen = XMLGenerator(result)
  132.  
  133.     gen.startDocument()
  134.     gen.processingInstruction("test", "data")
  135.     gen.startElement("doc", {})
  136.     gen.endElement("doc")
  137.     gen.endDocument()
  138.  
  139.     return result.getvalue() == start + "<?test data?><doc></doc>"
  140.  
  141. def test_xmlgen_content_escape():
  142.     result = StringIO()
  143.     gen = XMLGenerator(result)
  144.  
  145.     gen.startDocument()
  146.     gen.startElement("doc", {})
  147.     gen.characters("<huhei&")
  148.     gen.endElement("doc")
  149.     gen.endDocument()
  150.  
  151.     return result.getvalue() == start + "<doc><huhei&</doc>"
  152.  
  153. def test_xmlgen_attr_escape():
  154.     result = StringIO()
  155.     gen = XMLGenerator(result)
  156.  
  157.     gen.startDocument()
  158.     gen.startElement("doc", {"a": '"'})
  159.     gen.startElement("e", {"a": "'"})
  160.     gen.endElement("e")
  161.     gen.startElement("e", {"a": "'\""})
  162.     gen.endElement("e")
  163.     gen.endElement("doc")
  164.     gen.endDocument()
  165.  
  166.     return result.getvalue() == start \
  167.            + "<doc a='\"'><e a=\"'\"></e><e a=\"'"\"></e></doc>"
  168.  
  169. def test_xmlgen_ignorable():
  170.     result = StringIO()
  171.     gen = XMLGenerator(result)
  172.  
  173.     gen.startDocument()
  174.     gen.startElement("doc", {})
  175.     gen.ignorableWhitespace(" ")
  176.     gen.endElement("doc")
  177.     gen.endDocument()
  178.  
  179.     return result.getvalue() == start + "<doc> </doc>"
  180.  
  181. ns_uri = "http://www.python.org/xml-ns/saxtest/"
  182.  
  183. def test_xmlgen_ns():
  184.     result = StringIO()
  185.     gen = XMLGenerator(result)
  186.  
  187.     gen.startDocument()
  188.     gen.startPrefixMapping("ns1", ns_uri)
  189.     gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
  190.     # add an unqualified name
  191.     gen.startElementNS((None, "udoc"), None, {})
  192.     gen.endElementNS((None, "udoc"), None)
  193.     gen.endElementNS((ns_uri, "doc"), "ns1:doc")
  194.     gen.endPrefixMapping("ns1")
  195.     gen.endDocument()
  196.  
  197.     return result.getvalue() == start + \
  198.            ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
  199.                                          ns_uri)
  200.  
  201. # ===== XMLFilterBase
  202.  
  203. def test_filter_basic():
  204.     result = StringIO()
  205.     gen = XMLGenerator(result)
  206.     filter = XMLFilterBase()
  207.     filter.setContentHandler(gen)
  208.  
  209.     filter.startDocument()
  210.     filter.startElement("doc", {})
  211.     filter.characters("content")
  212.     filter.ignorableWhitespace(" ")
  213.     filter.endElement("doc")
  214.     filter.endDocument()
  215.  
  216.     return result.getvalue() == start + "<doc>content </doc>"
  217.  
  218. # ===========================================================================
  219. #
  220. #   expatreader tests
  221. #
  222. # ===========================================================================
  223.  
  224. # ===== XMLReader support
  225.  
  226. def test_expat_file():
  227.     parser = create_parser()
  228.     result = StringIO()
  229.     xmlgen = XMLGenerator(result)
  230.  
  231.     parser.setContentHandler(xmlgen)
  232.     parser.parse(open(findfile("test"+os.extsep+"xml")))
  233.  
  234.     return result.getvalue() == xml_test_out
  235.  
  236. # ===== DTDHandler support
  237.  
  238. class TestDTDHandler:
  239.  
  240.     def __init__(self):
  241.         self._notations = []
  242.         self._entities  = []
  243.  
  244.     def notationDecl(self, name, publicId, systemId):
  245.         self._notations.append((name, publicId, systemId))
  246.  
  247.     def unparsedEntityDecl(self, name, publicId, systemId, ndata):
  248.         self._entities.append((name, publicId, systemId, ndata))
  249.  
  250. def test_expat_dtdhandler():
  251.     parser = create_parser()
  252.     handler = TestDTDHandler()
  253.     parser.setDTDHandler(handler)
  254.  
  255.     parser.feed('<!DOCTYPE doc [\n')
  256.     parser.feed('  <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
  257.     parser.feed('  <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
  258.     parser.feed(']>\n')
  259.     parser.feed('<doc></doc>')
  260.     parser.close()
  261.  
  262.     return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
  263.            handler._entities == [("img", None, "expat.gif", "GIF")]
  264.  
  265. # ===== EntityResolver support
  266.  
  267. class TestEntityResolver:
  268.  
  269.     def resolveEntity(self, publicId, systemId):
  270.         inpsrc = InputSource()
  271.         inpsrc.setByteStream(StringIO("<entity/>"))
  272.         return inpsrc
  273.  
  274. def test_expat_entityresolver():
  275.     parser = create_parser()
  276.     parser.setEntityResolver(TestEntityResolver())
  277.     result = StringIO()
  278.     parser.setContentHandler(XMLGenerator(result))
  279.  
  280.     parser.feed('<!DOCTYPE doc [\n')
  281.     parser.feed('  <!ENTITY test SYSTEM "whatever">\n')
  282.     parser.feed(']>\n')
  283.     parser.feed('<doc>&test;</doc>')
  284.     parser.close()
  285.  
  286.     return result.getvalue() == start + "<doc><entity></entity></doc>"
  287.  
  288. # ===== Attributes support
  289.  
  290. class AttrGatherer(ContentHandler):
  291.  
  292.     def startElement(self, name, attrs):
  293.         self._attrs = attrs
  294.  
  295.     def startElementNS(self, name, qname, attrs):
  296.         self._attrs = attrs
  297.  
  298. def test_expat_attrs_empty():
  299.     parser = create_parser()
  300.     gather = AttrGatherer()
  301.     parser.setContentHandler(gather)
  302.  
  303.     parser.feed("<doc/>")
  304.     parser.close()
  305.  
  306.     return verify_empty_attrs(gather._attrs)
  307.  
  308. def test_expat_attrs_wattr():
  309.     parser = create_parser()
  310.     gather = AttrGatherer()
  311.     parser.setContentHandler(gather)
  312.  
  313.     parser.feed("<doc attr='val'/>")
  314.     parser.close()
  315.  
  316.     return verify_attrs_wattr(gather._attrs)
  317.  
  318. def test_expat_nsattrs_empty():
  319.     parser = create_parser(1)
  320.     gather = AttrGatherer()
  321.     parser.setContentHandler(gather)
  322.  
  323.     parser.feed("<doc/>")
  324.     parser.close()
  325.  
  326.     return verify_empty_nsattrs(gather._attrs)
  327.  
  328. def test_expat_nsattrs_wattr():
  329.     parser = create_parser(1)
  330.     gather = AttrGatherer()
  331.     parser.setContentHandler(gather)
  332.  
  333.     parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
  334.     parser.close()
  335.  
  336.     attrs = gather._attrs
  337.  
  338.     return attrs.getLength() == 1 and \
  339.            attrs.getNames() == [(ns_uri, "attr")] and \
  340.            attrs.getQNames() == [] and \
  341.            len(attrs) == 1 and \
  342.            attrs.has_key((ns_uri, "attr")) and \
  343.            attrs.keys() == [(ns_uri, "attr")] and \
  344.            attrs.get((ns_uri, "attr")) == "val" and \
  345.            attrs.get((ns_uri, "attr"), 25) == "val" and \
  346.            attrs.items() == [((ns_uri, "attr"), "val")] and \
  347.            attrs.values() == ["val"] and \
  348.            attrs.getValue((ns_uri, "attr")) == "val" and \
  349.            attrs[(ns_uri, "attr")] == "val"
  350.  
  351. # ===== InputSource support
  352.  
  353. xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
  354.  
  355. def test_expat_inpsource_filename():
  356.     parser = create_parser()
  357.     result = StringIO()
  358.     xmlgen = XMLGenerator(result)
  359.  
  360.     parser.setContentHandler(xmlgen)
  361.     parser.parse(findfile("test"+os.extsep+"xml"))
  362.  
  363.     return result.getvalue() == xml_test_out
  364.  
  365. def test_expat_inpsource_sysid():
  366.     parser = create_parser()
  367.     result = StringIO()
  368.     xmlgen = XMLGenerator(result)
  369.  
  370.     parser.setContentHandler(xmlgen)
  371.     parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
  372.  
  373.     return result.getvalue() == xml_test_out
  374.  
  375. def test_expat_inpsource_stream():
  376.     parser = create_parser()
  377.     result = StringIO()
  378.     xmlgen = XMLGenerator(result)
  379.  
  380.     parser.setContentHandler(xmlgen)
  381.     inpsrc = InputSource()
  382.     inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
  383.     parser.parse(inpsrc)
  384.  
  385.     return result.getvalue() == xml_test_out
  386.  
  387. # ===== IncrementalParser support
  388.  
  389. def test_expat_incremental():
  390.     result = StringIO()
  391.     xmlgen = XMLGenerator(result)
  392.     parser = create_parser()
  393.     parser.setContentHandler(xmlgen)
  394.  
  395.     parser.feed("<doc>")
  396.     parser.feed("</doc>")
  397.     parser.close()
  398.  
  399.     return result.getvalue() == start + "<doc></doc>"
  400.  
  401. def test_expat_incremental_reset():
  402.     result = StringIO()
  403.     xmlgen = XMLGenerator(result)
  404.     parser = create_parser()
  405.     parser.setContentHandler(xmlgen)
  406.  
  407.     parser.feed("<doc>")
  408.     parser.feed("text")
  409.  
  410.     result = StringIO()
  411.     xmlgen = XMLGenerator(result)
  412.     parser.setContentHandler(xmlgen)
  413.     parser.reset()
  414.  
  415.     parser.feed("<doc>")
  416.     parser.feed("text")
  417.     parser.feed("</doc>")
  418.     parser.close()
  419.  
  420.     return result.getvalue() == start + "<doc>text</doc>"
  421.  
  422. # ===== Locator support
  423.  
  424. def test_expat_locator_noinfo():
  425.     result = StringIO()
  426.     xmlgen = XMLGenerator(result)
  427.     parser = create_parser()
  428.     parser.setContentHandler(xmlgen)
  429.  
  430.     parser.feed("<doc>")
  431.     parser.feed("</doc>")
  432.     parser.close()
  433.  
  434.     return parser.getSystemId() is None and \
  435.            parser.getPublicId() is None and \
  436.            parser.getLineNumber() == 1
  437.  
  438. def test_expat_locator_withinfo():
  439.     result = StringIO()
  440.     xmlgen = XMLGenerator(result)
  441.     parser = create_parser()
  442.     parser.setContentHandler(xmlgen)
  443.     parser.parse(findfile("test.xml"))
  444.  
  445.     return parser.getSystemId() == findfile("test.xml") and \
  446.            parser.getPublicId() is None
  447.  
  448.  
  449. # ===========================================================================
  450. #
  451. #   error reporting
  452. #
  453. # ===========================================================================
  454.  
  455. def test_expat_inpsource_location():
  456.     parser = create_parser()
  457.     parser.setContentHandler(ContentHandler()) # do nothing
  458.     source = InputSource()
  459.     source.setByteStream(StringIO("<foo bar foobar>"))   #ill-formed
  460.     name = "a file name"
  461.     source.setSystemId(name)
  462.     try:
  463.         parser.parse(source)
  464.     except SAXException, e:
  465.         return e.getSystemId() == name
  466.  
  467. def test_expat_incomplete():
  468.     parser = create_parser()
  469.     parser.setContentHandler(ContentHandler()) # do nothing
  470.     try:
  471.         parser.parse(StringIO("<foo>"))
  472.     except SAXParseException:
  473.         return 1 # ok, error found
  474.     else:
  475.         return 0
  476.  
  477.  
  478. # ===========================================================================
  479. #
  480. #   xmlreader tests
  481. #
  482. # ===========================================================================
  483.  
  484. # ===== AttributesImpl
  485.  
  486. def verify_empty_attrs(attrs):
  487.     try:
  488.         attrs.getValue("attr")
  489.         gvk = 0
  490.     except KeyError:
  491.         gvk = 1
  492.  
  493.     try:
  494.         attrs.getValueByQName("attr")
  495.         gvqk = 0
  496.     except KeyError:
  497.         gvqk = 1
  498.  
  499.     try:
  500.         attrs.getNameByQName("attr")
  501.         gnqk = 0
  502.     except KeyError:
  503.         gnqk = 1
  504.  
  505.     try:
  506.         attrs.getQNameByName("attr")
  507.         gqnk = 0
  508.     except KeyError:
  509.         gqnk = 1
  510.  
  511.     try:
  512.         attrs["attr"]
  513.         gik = 0
  514.     except KeyError:
  515.         gik = 1
  516.  
  517.     return attrs.getLength() == 0 and \
  518.            attrs.getNames() == [] and \
  519.            attrs.getQNames() == [] and \
  520.            len(attrs) == 0 and \
  521.            not attrs.has_key("attr") and \
  522.            attrs.keys() == [] and \
  523.            attrs.get("attrs") is None and \
  524.            attrs.get("attrs", 25) == 25 and \
  525.            attrs.items() == [] and \
  526.            attrs.values() == [] and \
  527.            gvk and gvqk and gnqk and gik and gqnk
  528.  
  529. def verify_attrs_wattr(attrs):
  530.     return attrs.getLength() == 1 and \
  531.            attrs.getNames() == ["attr"] and \
  532.            attrs.getQNames() == ["attr"] and \
  533.            len(attrs) == 1 and \
  534.            attrs.has_key("attr") and \
  535.            attrs.keys() == ["attr"] and \
  536.            attrs.get("attr") == "val" and \
  537.            attrs.get("attr", 25) == "val" and \
  538.            attrs.items() == [("attr", "val")] and \
  539.            attrs.values() == ["val"] and \
  540.            attrs.getValue("attr") == "val" and \
  541.            attrs.getValueByQName("attr") == "val" and \
  542.            attrs.getNameByQName("attr") == "attr" and \
  543.            attrs["attr"] == "val" and \
  544.            attrs.getQNameByName("attr") == "attr"
  545.  
  546. def test_attrs_empty():
  547.     return verify_empty_attrs(AttributesImpl({}))
  548.  
  549. def test_attrs_wattr():
  550.     return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
  551.  
  552. # ===== AttributesImpl
  553.  
  554. def verify_empty_nsattrs(attrs):
  555.     try:
  556.         attrs.getValue((ns_uri, "attr"))
  557.         gvk = 0
  558.     except KeyError:
  559.         gvk = 1
  560.  
  561.     try:
  562.         attrs.getValueByQName("ns:attr")
  563.         gvqk = 0
  564.     except KeyError:
  565.         gvqk = 1
  566.  
  567.     try:
  568.         attrs.getNameByQName("ns:attr")
  569.         gnqk = 0
  570.     except KeyError:
  571.         gnqk = 1
  572.  
  573.     try:
  574.         attrs.getQNameByName((ns_uri, "attr"))
  575.         gqnk = 0
  576.     except KeyError:
  577.         gqnk = 1
  578.  
  579.     try:
  580.         attrs[(ns_uri, "attr")]
  581.         gik = 0
  582.     except KeyError:
  583.         gik = 1
  584.  
  585.     return attrs.getLength() == 0 and \
  586.            attrs.getNames() == [] and \
  587.            attrs.getQNames() == [] and \
  588.            len(attrs) == 0 and \
  589.            not attrs.has_key((ns_uri, "attr")) and \
  590.            attrs.keys() == [] and \
  591.            attrs.get((ns_uri, "attr")) is None and \
  592.            attrs.get((ns_uri, "attr"), 25) == 25 and \
  593.            attrs.items() == [] and \
  594.            attrs.values() == [] and \
  595.            gvk and gvqk and gnqk and gik and gqnk
  596.  
  597. def test_nsattrs_empty():
  598.     return verify_empty_nsattrs(AttributesNSImpl({}, {}))
  599.  
  600. def test_nsattrs_wattr():
  601.     attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
  602.                              {(ns_uri, "attr") : "ns:attr"})
  603.  
  604.     return attrs.getLength() == 1 and \
  605.            attrs.getNames() == [(ns_uri, "attr")] and \
  606.            attrs.getQNames() == ["ns:attr"] and \
  607.            len(attrs) == 1 and \
  608.            attrs.has_key((ns_uri, "attr")) and \
  609.            attrs.keys() == [(ns_uri, "attr")] and \
  610.            attrs.get((ns_uri, "attr")) == "val" and \
  611.            attrs.get((ns_uri, "attr"), 25) == "val" and \
  612.            attrs.items() == [((ns_uri, "attr"), "val")] and \
  613.            attrs.values() == ["val"] and \
  614.            attrs.getValue((ns_uri, "attr")) == "val" and \
  615.            attrs.getValueByQName("ns:attr") == "val" and \
  616.            attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
  617.            attrs[(ns_uri, "attr")] == "val" and \
  618.            attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
  619.  
  620.  
  621. # ===== Main program
  622.  
  623. def make_test_output():
  624.     parser = create_parser()
  625.     result = StringIO()
  626.     xmlgen = XMLGenerator(result)
  627.  
  628.     parser.setContentHandler(xmlgen)
  629.     parser.parse(findfile("test"+os.extsep+"xml"))
  630.  
  631.     outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w")
  632.     outf.write(result.getvalue())
  633.     outf.close()
  634.  
  635. items = locals().items()
  636. items.sort()
  637. for (name, value) in items:
  638.     if name[ : 5] == "test_":
  639.         confirm(value(), name)
  640.  
  641. print "%d tests, %d failures" % (tests, fails)
  642. if fails != 0:
  643.     raise TestFailed, "%d of %d tests failed" % (fails, tests)
  644.