diff options
author | Aron Xu <aron@debian.org> | 2013-06-09 00:17:44 +0800 |
---|---|---|
committer | Aron Xu <aron@debian.org> | 2013-06-09 00:17:44 +0800 |
commit | 2c8fe012ef1ff6e0613480dd182dec099aa9636e (patch) | |
tree | f220f4e6733d3204aef57831a8dee2dd8551ed40 /python/tests/input_callback.py | |
parent | 3c845c4be476dc0ecb93388de9cfedb3f611e6a8 (diff) | |
download | libxml2-2c8fe012ef1ff6e0613480dd182dec099aa9636e.tar.gz |
Imported Upstream version 2.9.1upstream/2.9.1
Diffstat (limited to 'python/tests/input_callback.py')
-rwxr-xr-x | python/tests/input_callback.py | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/python/tests/input_callback.py b/python/tests/input_callback.py new file mode 100755 index 0000000..495ab62 --- /dev/null +++ b/python/tests/input_callback.py @@ -0,0 +1,148 @@ +#!/usr/bin/python -u +# +# This tests custom input callbacks +# +import sys +import libxml2 +try: + import StringIO + str_io = StringIO.StringIO +except: + import io + str_io = io.StringIO + +# We implement a new scheme, py://strings/ that will reference this dictionary +pystrings = { + 'catalogs/catalog.xml' : +'''<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"> +<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"> + <rewriteSystem systemIdStartString="http://example.com/dtds/" rewritePrefix="../dtds/"/> +</catalog>''', + + 'xml/sample.xml' : +'''<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE root SYSTEM "http://example.com/dtds/sample.dtd"> +<root>&sample.entity;</root>''', + + 'dtds/sample.dtd' : +''' +<!ELEMENT root (#PCDATA)> +<!ENTITY sample.entity "replacement text">''' +} + +prefix = "py://strings/" +startURL = prefix + "xml/sample.xml" +catURL = prefix + "catalogs/catalog.xml" + +def my_input_cb(URI): + if not(URI.startswith(prefix)): + return None + path = URI[len(prefix):] + if path not in pystrings: + return None + return str_io(pystrings[path]) + + +def run_test(desc, docpath, catalog, exp_status="verified", exp_err=[], test_callback=None, + root_name="root", root_content="replacement text"): + opts = libxml2.XML_PARSE_DTDLOAD | libxml2.XML_PARSE_NONET | libxml2.XML_PARSE_COMPACT + actual_err = [] + + def my_global_error_cb(ctx, msg): + actual_err.append((-1, msg)) + def my_ctx_error_cb(arg, msg, severity, reserved): + actual_err.append((severity, msg)) + + libxml2.registerErrorHandler(my_global_error_cb, None) + try: + parser = libxml2.createURLParserCtxt(docpath, opts) + parser.setErrorHandler(my_ctx_error_cb, None) + if catalog is not None: + parser.addLocalCatalog(catalog) + if test_callback is not None: + test_callback() + parser.parseDocument() + doc = parser.doc() + actual_status = "loaded" + e = doc.getRootElement() + if e.name == root_name and e.content == root_content: + actual_status = "verified" + doc.freeDoc() + except libxml2.parserError: + actual_status = "not loaded" + + if actual_status != exp_status: + print("Test '%s' failed: expect status '%s', actual '%s'" % (desc, exp_status, actual_status)) + sys.exit(1) + elif actual_err != exp_err: + print("Test '%s' failed" % desc) + print("Expect errors:") + for s,m in exp_err: print(" [%2d] '%s'" % (s,m)) + print("Actual errors:") + for s,m in actual_err: print(" [%2d] '%s'" % (s,m)) + sys.exit(1) + + +# Check that we cannot read custom schema without custom callback +run_test(desc="Loading entity without custom callback", + docpath=startURL, catalog=None, + exp_status="not loaded", exp_err=[ + (-1, "I/O "), + (-1, "warning : "), + (-1, "failed to load external entity \"py://strings/xml/sample.xml\"\n") + ]) + +# Register handler and try to load the same entity +libxml2.registerInputCallback(my_input_cb) +run_test(desc="Loading entity with custom callback", + docpath=startURL, catalog=None, + exp_status="loaded", exp_err=[ + (-1, "Attempt to load network entity http://example.com/dtds/sample.dtd"), + ( 4, "Entity 'sample.entity' not defined\n") + ]) + +# Register a catalog (also accessible via pystr://) and retry +run_test(desc="Loading entity with custom callback and catalog", + docpath=startURL, catalog=catURL) + +# Unregister custom callback when parser is already created +run_test(desc="Loading entity and unregistering callback", + docpath=startURL, catalog=catURL, + test_callback=lambda: libxml2.popInputCallbacks(), + exp_status="loaded", exp_err=[ + ( 3, "failed to load external entity \"py://strings/dtds/sample.dtd\"\n"), + ( 4, "Entity 'sample.entity' not defined\n") + ]) + +# Try to load the document again +run_test(desc="Retry loading document after unregistering callback", + docpath=startURL, catalog=catURL, + exp_status="not loaded", exp_err=[ + (-1, "I/O "), + (-1, "warning : "), + (-1, "failed to load external entity \"py://strings/xml/sample.xml\"\n") + ]) + +# But should be able to read standard I/O yet... +run_test(desc="Loading using standard i/o after unregistering callback", + docpath="tst.xml", catalog=None, + root_name='doc', root_content='bar') + +# Now pop ALL input callbacks, should fail to load even standard I/O +try: + while True: + libxml2.popInputCallbacks() +except IndexError: + pass + +run_test(desc="Loading using standard i/o after unregistering all callbacks", + docpath="tst.xml", catalog=None, + exp_status="not loaded", exp_err=[ + (-1, "I/O "), + (-1, "warning : "), + (-1, "failed to load external entity \"tst.xml\"\n") + ]) + +print("OK") +sys.exit(0); |