summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/README47
-rw-r--r--Lib/test/crashers/modify_dict_attr.py9
-rw-r--r--Lib/test/infinite_reload.py7
-rw-r--r--Lib/test/output/test_operations19
-rw-r--r--Lib/test/output/test_popen29
-rw-r--r--Lib/test/output/test_pty3
-rw-r--r--Lib/test/output/test_pyexpat110
-rw-r--r--Lib/test/output/test_threadedtempfile5
-rw-r--r--Lib/test/output/xmltests364
-rw-r--r--Lib/test/outstanding_bugs.py37
-rw-r--r--Lib/test/pickletester.py32
-rwxr-xr-xLib/test/regrtest.py2
-rw-r--r--Lib/test/ssl_cert.pem14
-rw-r--r--Lib/test/ssl_key.pem9
-rw-r--r--Lib/test/string_tests.py3
-rw-r--r--Lib/test/test___all__.py12
-rwxr-xr-xLib/test/test_array.py16
-rw-r--r--Lib/test/test_atexit.py32
-rw-r--r--Lib/test/test_base64.py12
-rwxr-xr-xLib/test/test_binascii.py9
-rw-r--r--Lib/test/test_bool.py2
-rw-r--r--Lib/test/test_bsddb3.py8
-rw-r--r--Lib/test/test_builtin.py18
-rw-r--r--Lib/test/test_cfgparser.py12
-rwxr-xr-xLib/test/test_cmath.py246
-rw-r--r--Lib/test/test_cmd_line.py2
-rw-r--r--Lib/test/test_codecencodings_cn.py6
-rw-r--r--Lib/test/test_codecencodings_hk.py4
-rw-r--r--Lib/test/test_codecencodings_jp.py8
-rw-r--r--Lib/test/test_codecencodings_kr.py6
-rw-r--r--Lib/test/test_codecencodings_tw.py4
-rw-r--r--Lib/test/test_codecmaps_cn.py5
-rw-r--r--Lib/test/test_codecmaps_hk.py4
-rw-r--r--Lib/test/test_codecmaps_jp.py8
-rw-r--r--Lib/test/test_codecmaps_kr.py6
-rw-r--r--Lib/test/test_codecmaps_tw.py5
-rw-r--r--Lib/test/test_collections.py57
-rw-r--r--Lib/test/test_commands.py4
-rw-r--r--Lib/test/test_compile.py17
-rw-r--r--Lib/test/test_compiler.py4
-rw-r--r--Lib/test/test_complex.py12
-rw-r--r--Lib/test/test_contextlib.py6
-rwxr-xr-xLib/test/test_crypt.py2
-rw-r--r--Lib/test/test_csv.py4
-rw-r--r--Lib/test/test_ctypes.py4
-rw-r--r--Lib/test/test_curses.py15
-rw-r--r--Lib/test/test_datetime.py69
-rw-r--r--Lib/test/test_defaultdict.py9
-rw-r--r--Lib/test/test_deque.py2
-rw-r--r--Lib/test/test_descr.py131
-rw-r--r--Lib/test/test_descrtut.py2
-rw-r--r--Lib/test/test_dict.py76
-rw-r--r--Lib/test/test_dis.py8
-rw-r--r--Lib/test/test_doctest.py10
-rw-r--r--Lib/test/test_email.py4
-rw-r--r--Lib/test/test_email_codecs.py2
-rw-r--r--Lib/test/test_email_renamed.py4
-rw-r--r--Lib/test/test_exceptions.py5
-rw-r--r--Lib/test/test_fileinput.py397
-rw-r--r--Lib/test/test_fileio.py4
-rw-r--r--Lib/test/test_ftplib.py93
-rw-r--r--Lib/test/test_functools.py6
-rw-r--r--Lib/test/test_gc.py1132
-rw-r--r--Lib/test/test_getopt.py347
-rw-r--r--Lib/test/test_gettext.py15
-rw-r--r--Lib/test/test_glob.py10
-rw-r--r--Lib/test/test_grammar.py2
-rwxr-xr-xLib/test/test_htmlparser.py5
-rw-r--r--Lib/test/test_httplib.py47
-rw-r--r--Lib/test/test_import.py10
-rw-r--r--Lib/test/test_itertools.py18
-rw-r--r--Lib/test/test_keywordonlyarg.py2
-rw-r--r--Lib/test/test_locale.py2
-rw-r--r--Lib/test/test_logging.py2
-rw-r--r--Lib/test/test_long_future.py100
-rw-r--r--Lib/test/test_macpath.py2
-rw-r--r--Lib/test/test_mailbox.py5
-rw-r--r--Lib/test/test_metaclass.py2
-rw-r--r--Lib/test/test_minidom.py2594
-rw-r--r--Lib/test/test_module.py103
-rw-r--r--Lib/test/test_multibytecodec.py8
-rw-r--r--Lib/test/test_normalization.py118
-rw-r--r--Lib/test/test_ntpath.py20
-rw-r--r--Lib/test/test_operations.py77
-rw-r--r--Lib/test/test_operator.py6
-rw-r--r--Lib/test/test_optparse.py14
-rw-r--r--Lib/test/test_os.py78
-rw-r--r--Lib/test/test_ossaudiodev.py247
-rw-r--r--Lib/test/test_peepholer.py11
-rw-r--r--Lib/test/test_popen2.py150
-rw-r--r--Lib/test/test_poplib.py71
-rw-r--r--Lib/test/test_posixpath.py208
-rw-r--r--Lib/test/test_pty.py256
-rw-r--r--Lib/test/test_pyexpat.py677
-rw-r--r--Lib/test/test_re.py15
-rw-r--r--Lib/test/test_robotparser.py4
-rw-r--r--Lib/test/test_sax.py1193
-rw-r--r--Lib/test/test_scope.py35
-rw-r--r--Lib/test/test_set.py11
-rw-r--r--Lib/test/test_slice.py19
-rw-r--r--Lib/test/test_smtplib.py71
-rw-r--r--Lib/test/test_socket.py106
-rw-r--r--Lib/test/test_socket_ssl.py299
-rw-r--r--Lib/test/test_socketserver.py11
-rw-r--r--Lib/test/test_stringprep.py130
-rw-r--r--Lib/test/test_strptime.py29
-rw-r--r--Lib/test/test_struct.py24
-rw-r--r--Lib/test/test_structmembers.py39
-rw-r--r--Lib/test/test_support.py125
-rw-r--r--Lib/test/test_syntax.py55
-rw-r--r--Lib/test/test_tarfile.py1342
-rw-r--r--Lib/test/test_telnetlib.py74
-rw-r--r--Lib/test/test_tempfile.py125
-rw-r--r--Lib/test/test_textwrap.py8
-rw-r--r--Lib/test/test_threadedtempfile.py79
-rw-r--r--Lib/test/test_threading_local.py2
-rw-r--r--Lib/test/test_unicode.py2
-rw-r--r--Lib/test/test_unicode_file.py6
-rw-r--r--Lib/test/test_unittest.py2303
-rw-r--r--Lib/test/test_unpack.py2
-rw-r--r--Lib/test/test_urllib.py9
-rw-r--r--Lib/test/test_urllib2.py24
-rw-r--r--Lib/test/test_urllib2net.py3
-rw-r--r--Lib/test/test_userdict.py6
-rw-r--r--Lib/test/test_warnings.py146
-rw-r--r--Lib/test/test_weakref.py4
-rwxr-xr-xLib/test/test_wsgiref.py9
-rw-r--r--Lib/test/test_zipfile.py433
-rw-r--r--Lib/test/test_zlib.py34
-rw-r--r--Lib/test/testtar.tarbin133120 -> 256000 bytes
-rw-r--r--Lib/test/warning_tests.py9
131 files changed, 9420 insertions, 5747 deletions
diff --git a/Lib/test/README b/Lib/test/README
index 27f696c..747d842 100644
--- a/Lib/test/README
+++ b/Lib/test/README
@@ -15,7 +15,7 @@ testing facility provided with Python; any particular test should use only
one of these options. Each option requires writing a test module using the
conventions of the selected option:
- - PyUnit_ based tests
+ - unittest_ based tests
- doctest_ based tests
- "traditional" Python test modules
@@ -28,31 +28,34 @@ your test cases to exercise it more completely. In particular, you will be
able to refer to the C and Python code in the CVS repository when writing
your regression test cases.
-.. _PyUnit:
.. _unittest: http://www.python.org/doc/current/lib/module-unittest.html
.. _doctest: http://www.python.org/doc/current/lib/module-doctest.html
-PyUnit based tests
+unittest-based tests
------------------
-The PyUnit_ framework is based on the ideas of unit testing as espoused
+The unittest_ framework is based on the ideas of unit testing as espoused
by Kent Beck and the `Extreme Programming`_ (XP) movement. The specific
interface provided by the framework is tightly based on the JUnit_
Java implementation of Beck's original SmallTalk test framework. Please
see the documentation of the unittest_ module for detailed information on
-the interface and general guidelines on writing PyUnit based tests.
-
-The test_support helper module provides two functions for use by
-PyUnit based tests in the Python regression testing framework:
-
-- ``run_unittest()`` takes a ``unittest.TestCase`` derived class as a
- parameter and runs the tests defined in that class
+the interface and general guidelines on writing unittest-based tests.
+
+The test_support helper module provides a function for use by
+unittest-based tests in the Python regression testing framework,
+``run_unittest()``. This is the primary way of running tests in the
+standard library. You can pass it any number of the following:
+
+- classes derived from or instances of ``unittest.TestCase`` or
+ ``unittest.TestSuite``. These will be handed off to unittest for
+ converting into a proper TestSuite instance.
+
+- a string; this must be a key in sys.modules. The module associated with
+ that string will be scanned by ``unittest.TestLoader.loadTestsFromModule``.
+ This is usually seen as ``test_support.run_unittest(__name__)`` in a test
+ module's ``test_main()`` function. This has the advantage of picking up
+ new tests automatically, without you having to add each new test case
+ manually.
-- ``run_suite()`` takes a populated ``TestSuite`` instance and runs the
- tests
-
-``run_suite()`` is preferred because unittest files typically grow multiple
-test classes, and you might as well be prepared.
-
All test methods in the Python regression framework have names that
start with "``test_``" and use lower-case names with words separated with
underscores.
@@ -63,7 +66,7 @@ and the full class name. When there's a problem with a test, the
latter information makes it easier to find the source for the test
than the docstring.
-All PyUnit-based tests in the Python test suite use boilerplate that
+All unittest-based tests in the Python test suite use boilerplate that
looks like this (with minor variations)::
import unittest
@@ -97,11 +100,7 @@ looks like this (with minor variations)::
...etc...
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(MyTestCase1))
- suite.addTest(unittest.makeSuite(MyTestCase2))
- ...add more suites...
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
@@ -415,7 +414,7 @@ Some Non-Obvious regrtest Features
This is rarely required with the "traditional" Python tests, and
you shouldn't create a module global with name test_main unless
you're specifically exploiting this gimmick. This usage does
- prove useful with PyUnit-based tests as well, however; defining
+ prove useful with unittest-based tests as well, however; defining
a ``test_main()`` which is run by regrtest and a script-stub in the
test module ("``if __name__ == '__main__': test_main()``") allows
the test to be used like any other Python test and also work
diff --git a/Lib/test/crashers/modify_dict_attr.py b/Lib/test/crashers/modify_dict_attr.py
index ac1f0a8..be675c1 100644
--- a/Lib/test/crashers/modify_dict_attr.py
+++ b/Lib/test/crashers/modify_dict_attr.py
@@ -4,15 +4,16 @@
class Y(object):
pass
-class type_with_modifiable_dict(Y, type):
+class type_with_modifiable_dict(type, Y):
pass
class MyClass(object, metaclass=type_with_modifiable_dict):
- """This class has its __dict__ attribute completely exposed:
- user code can read, reassign and even delete it.
+ """This class has its __dict__ attribute indirectly
+ exposed via the __dict__ getter/setter of Y.
"""
if __name__ == '__main__':
- del MyClass.__dict__ # if we set tp_dict to NULL,
+ dictattr = Y.__dict__['__dict__']
+ dictattr.__delete__(MyClass) # if we set tp_dict to NULL,
print(MyClass) # doing anything with MyClass segfaults
diff --git a/Lib/test/infinite_reload.py b/Lib/test/infinite_reload.py
new file mode 100644
index 0000000..bfbec91
--- /dev/null
+++ b/Lib/test/infinite_reload.py
@@ -0,0 +1,7 @@
+# For testing http://python.org/sf/742342, which reports that Python
+# segfaults (infinite recursion in C) in the presence of infinite
+# reload()ing. This module is imported by test_import.py:test_infinite_reload
+# to make sure this doesn't happen any more.
+
+import infinite_reload
+reload(infinite_reload)
diff --git a/Lib/test/output/test_operations b/Lib/test/output/test_operations
deleted file mode 100644
index 309cd5b..0000000
--- a/Lib/test/output/test_operations
+++ /dev/null
@@ -1,19 +0,0 @@
-test_operations
-3. Operations
-XXX Mostly not yet implemented
-3.1 Dictionary lookups fail if __cmp__() raises an exception
-raising error
-d[x2] = 2: caught the RuntimeError outside
-raising error
-z = d[x2]: caught the RuntimeError outside
-raising error
-x2 in d: caught the RuntimeError outside
-raising error
-d.get(x2): caught the RuntimeError outside
-raising error
-d.setdefault(x2, 42): caught the RuntimeError outside
-raising error
-d.pop(x2): caught the RuntimeError outside
-raising error
-d.update({x2: 2}): caught the RuntimeError outside
-resize bugs not triggered.
diff --git a/Lib/test/output/test_popen2 b/Lib/test/output/test_popen2
deleted file mode 100644
index a66cde9..0000000
--- a/Lib/test/output/test_popen2
+++ /dev/null
@@ -1,9 +0,0 @@
-test_popen2
-Test popen2 module:
-testing popen2...
-testing popen3...
-All OK
-Testing os module:
-testing popen2...
-testing popen3...
-All OK
diff --git a/Lib/test/output/test_pty b/Lib/test/output/test_pty
deleted file mode 100644
index b6e0e32..0000000
--- a/Lib/test/output/test_pty
+++ /dev/null
@@ -1,3 +0,0 @@
-test_pty
-I wish to buy a fish license.
-For my pet fish, Eric.
diff --git a/Lib/test/output/test_pyexpat b/Lib/test/output/test_pyexpat
deleted file mode 100644
index 61fe81d..0000000
--- a/Lib/test/output/test_pyexpat
+++ /dev/null
@@ -1,110 +0,0 @@
-test_pyexpat
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-PI:
- 'xml-stylesheet' 'href="stylesheet.css"'
-Comment:
- ' comment data '
-Notation declared: ('notation', None, 'notation.jpeg', None)
-Unparsed entity decl:
- ('unparsed_entity', None, 'entity.file', None, 'notation')
-Start element:
- 'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
-NS decl:
- 'myns' 'http://www.python.org/namespace'
-Start element:
- 'http://www.python.org/namespace!subelement' {}
-Character data:
- 'Contents of subelements'
-End element:
- 'http://www.python.org/namespace!subelement'
-End of NS decl:
- 'myns'
-Start element:
- 'sub2' {}
-Start of CDATA section
-Character data:
- 'contents of CDATA section'
-End of CDATA section
-End element:
- 'sub2'
-External entity ref: (None, 'entity.file', None)
-End element:
- 'root'
-PI:
- u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
- u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
- (u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
- u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
- u'myns' u'http://www.python.org/namespace'
-Start element:
- u'http://www.python.org/namespace!subelement' {}
-Character data:
- u'Contents of subelements'
-End element:
- u'http://www.python.org/namespace!subelement'
-End of NS decl:
- u'myns'
-Start element:
- u'sub2' {}
-Start of CDATA section
-Character data:
- u'contents of CDATA section'
-End of CDATA section
-End element:
- u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
- u'root'
-PI:
- u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
- u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
- (u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
- u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
- u'myns' u'http://www.python.org/namespace'
-Start element:
- u'http://www.python.org/namespace!subelement' {}
-Character data:
- u'Contents of subelements'
-End element:
- u'http://www.python.org/namespace!subelement'
-End of NS decl:
- u'myns'
-Start element:
- u'sub2' {}
-Start of CDATA section
-Character data:
- u'contents of CDATA section'
-End of CDATA section
-End element:
- u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
- u'root'
-
-Testing constructor for proper handling of namespace_separator values:
-Legal values tested o.k.
-Caught expected TypeError:
-ParserCreate() argument 2 must be string or None, not int
-Caught expected ValueError:
-namespace_separator must be at most one character, omitted, or None
diff --git a/Lib/test/output/test_threadedtempfile b/Lib/test/output/test_threadedtempfile
deleted file mode 100644
index 2552877..0000000
--- a/Lib/test/output/test_threadedtempfile
+++ /dev/null
@@ -1,5 +0,0 @@
-test_threadedtempfile
-Creating
-Starting
-Reaping
-Done: errors 0 ok 1000
diff --git a/Lib/test/output/xmltests b/Lib/test/output/xmltests
deleted file mode 100644
index c798f6e..0000000
--- a/Lib/test/output/xmltests
+++ /dev/null
@@ -1,364 +0,0 @@
-xmltests
-Passed testAAA
-Passed setAttribute() sets ownerDocument
-Passed setAttribute() sets ownerElement
-Test Succeeded testAAA
-Passed assertion: len(Node.allnodes) == 0
-Passed testAAB
-Test Succeeded testAAB
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testAddAttr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testAppendChild
-Passed assertion: len(Node.allnodes) == 0
-Passed appendChild(<fragment>)
-Test Succeeded testAppendChildFragment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItem
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItemNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItems
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListKeys
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListKeysNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListLength
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListValues
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrList__getitem__
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrList__setitem__
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testAttributeRepr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testChangeAttr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testChildNodes
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneAttributeDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneAttributeShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneDocumentDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneDocumentShallow
-Passed assertion: len(Node.allnodes) == 0
-Passed clone of element has same attribute keys
-Passed clone of attribute node has proper attribute values
-Passed clone of attribute node correctly owned
-Passed testCloneElementDeep
-Test Succeeded testCloneElementDeep
-Passed assertion: len(Node.allnodes) == 0
-Passed clone of element has same attribute keys
-Passed clone of attribute node has proper attribute values
-Passed clone of attribute node correctly owned
-Passed testCloneElementShallow
-Test Succeeded testCloneElementShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testClonePIDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testClonePIShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testComment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCreateAttributeNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCreateElementNS
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testDeleteAttr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testDocumentElement
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testElement
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testElementReprAndStr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testFirstChild
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrLength
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrList
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrValues
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttribute
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttributeNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttributeNode
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testGetElementsByTagName
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testGetElementsByTagNameNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetEmptyNodeListFromElementsByTagNameNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testHasChildNodes
-Passed assertion: len(Node.allnodes) == 0
-Passed testInsertBefore -- node properly placed in tree
-Passed testInsertBefore -- node properly placed in tree
-Passed testInsertBefore -- node properly placed in tree
-Test Succeeded testInsertBefore
-Passed assertion: len(Node.allnodes) == 0
-Passed insertBefore(<fragment>, None)
-Passed insertBefore(<fragment>, orig)
-Test Succeeded testInsertBeforeFragment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testLegalChildren
-Passed assertion: len(Node.allnodes) == 0
-Passed NamedNodeMap.__setitem__() sets ownerDocument
-Passed NamedNodeMap.__setitem__() sets ownerElement
-Passed NamedNodeMap.__setitem__() sets value
-Passed NamedNodeMap.__setitem__() sets nodeValue
-Test Succeeded testNamedNodeMapSetItem
-Passed assertion: len(Node.allnodes) == 0
-Passed test NodeList.item()
-Test Succeeded testNodeListItem
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testNonZero
-Passed assertion: len(Node.allnodes) == 0
-Passed testNormalize -- preparation
-Passed testNormalize -- result
-Passed testNormalize -- single empty node removed
-Test Succeeded testNormalize
-Passed assertion: len(Node.allnodes) == 0
-Passed testParents
-Test Succeeded testParents
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParse
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseAttributeNamespaces
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseAttributes
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseElement
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseElementNamespaces
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testParseFromFile
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseProcessingInstructions
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseString
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testProcessingInstruction
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testProcessingInstructionRepr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttrNS
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttributeNode
-Passed assertion: len(Node.allnodes) == 0
-Passed replaceChild(<fragment>)
-Test Succeeded testReplaceChildFragment
-Passed assertion: len(Node.allnodes) == 0
-Passed testSAX2DOM - siblings
-Passed testSAX2DOM - parents
-Test Succeeded testSAX2DOM
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testSetAttrValueandNodeValue
-Passed assertion: len(Node.allnodes) == 0
-Passed testSiblings
-Test Succeeded testSiblings
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testTextNodeRepr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testTextRepr
-Passed assertion: len(Node.allnodes) == 0
-Caught expected exception when adding extra document element.
-Test Succeeded testTooManyDocumentElements
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testUnlink
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testWriteText
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testWriteXML
-Passed assertion: len(Node.allnodes) == 0
-All tests succeeded
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-PI:
- 'xml-stylesheet' 'href="stylesheet.css"'
-Comment:
- ' comment data '
-Notation declared: ('notation', None, 'notation.jpeg', None)
-Unparsed entity decl:
- ('unparsed_entity', None, 'entity.file', None, 'notation')
-Start element:
- 'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
-NS decl:
- 'myns' 'http://www.python.org/namespace'
-Start element:
- 'http://www.python.org/namespace!subelement' {}
-Character data:
- 'Contents of subelements'
-End element:
- 'http://www.python.org/namespace!subelement'
-End of NS decl:
- 'myns'
-Start element:
- 'sub2' {}
-Start of CDATA section
-Character data:
- 'contents of CDATA section'
-End of CDATA section
-End element:
- 'sub2'
-External entity ref: (None, 'entity.file', None)
-End element:
- 'root'
-PI:
- u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
- u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
- (u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
- u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
- u'myns' u'http://www.python.org/namespace'
-Start element:
- u'http://www.python.org/namespace!subelement' {}
-Character data:
- u'Contents of subelements'
-End element:
- u'http://www.python.org/namespace!subelement'
-End of NS decl:
- u'myns'
-Start element:
- u'sub2' {}
-Start of CDATA section
-Character data:
- u'contents of CDATA section'
-End of CDATA section
-End element:
- u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
- u'root'
-PI:
- u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
- u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
- (u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
- u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
- u'myns' u'http://www.python.org/namespace'
-Start element:
- u'http://www.python.org/namespace!subelement' {}
-Character data:
- u'Contents of subelements'
-End element:
- u'http://www.python.org/namespace!subelement'
-End of NS decl:
- u'myns'
-Start element:
- u'sub2' {}
-Start of CDATA section
-Character data:
- u'contents of CDATA section'
-End of CDATA section
-End element:
- u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
- u'root'
-
-Testing constructor for proper handling of namespace_separator values:
-Legal values tested o.k.
-Caught expected TypeError:
-ParserCreate() argument 2 must be string or None, not int
-Caught expected ValueError:
-namespace_separator must be at most one character, omitted, or None
-Passed test_attrs_empty
-Passed test_attrs_wattr
-Passed test_double_quoteattr
-Passed test_escape_all
-Passed test_escape_basic
-Passed test_escape_extra
-Passed test_expat_attrs_empty
-Passed test_expat_attrs_wattr
-Passed test_expat_dtdhandler
-Passed test_expat_entityresolver
-Passed test_expat_file
-Passed test_expat_incomplete
-Passed test_expat_incremental
-Passed test_expat_incremental_reset
-Passed test_expat_inpsource_filename
-Passed test_expat_inpsource_location
-Passed test_expat_inpsource_stream
-Passed test_expat_inpsource_sysid
-Passed test_expat_locator_noinfo
-Passed test_expat_locator_withinfo
-Passed test_expat_nsattrs_empty
-Passed test_expat_nsattrs_wattr
-Passed test_filter_basic
-Passed test_make_parser
-Passed test_make_parser2
-Passed test_nsattrs_empty
-Passed test_nsattrs_wattr
-Passed test_quoteattr_basic
-Passed test_single_double_quoteattr
-Passed test_single_quoteattr
-Passed test_xmlgen_attr_escape
-Passed test_xmlgen_basic
-Passed test_xmlgen_content
-Passed test_xmlgen_content_escape
-Passed test_xmlgen_ignorable
-Passed test_xmlgen_ns
-Passed test_xmlgen_pi
-37 tests, 0 failures
diff --git a/Lib/test/outstanding_bugs.py b/Lib/test/outstanding_bugs.py
index 04afcbd..7c6cd9e 100644
--- a/Lib/test/outstanding_bugs.py
+++ b/Lib/test/outstanding_bugs.py
@@ -10,13 +10,44 @@ import unittest
from test import test_support
#
-# No test cases for outstanding bugs at the moment.
+# One test case for outstanding bugs at the moment:
#
+class TestDifflibLongestMatch(unittest.TestCase):
+ # From Patch #1678339:
+ # The find_longest_match method in the difflib's SequenceMatcher has a bug.
+
+ # The bug is in turn caused by a problem with creating a b2j mapping which
+ # should contain a list of indices for each of the list elements in b.
+ # However, when the b2j mapping is being created (this is being done in
+ # __chain_b method in the SequenceMatcher) the mapping becomes broken. The
+ # cause of this is that for the frequently used elements the list of indices
+ # is removed and the element is being enlisted in the populardict mapping.
+
+ # The test case tries to match two strings like:
+ # abbbbbb.... and ...bbbbbbc
+
+ # The number of b is equal and the find_longest_match should have returned
+ # the proper amount. However, in case the number of "b"s is large enough, the
+ # method reports that the length of the longest common substring is 0. It
+ # simply can't find it.
+
+ # A bug was raised some time ago on this matter. It's ID is 1528074.
+
+ def test_find_longest_match(self):
+ import difflib
+ for i in (190, 200, 210):
+ text1 = "a" + "b"*i
+ text2 = "b"*i + "c"
+ m = difflib.SequenceMatcher(None, text1, text2)
+ (aptr, bptr, l) = m.find_longest_match(0, len(text1), 0, len(text2))
+ self.assertEquals(i, l)
+ self.assertEquals(aptr, 1)
+ self.assertEquals(bptr, 0)
+
def test_main():
- #test_support.run_unittest()
- pass
+ test_support.run_unittest(TestDifflibLongestMatch)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index b10c57d..4691e13 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -835,6 +835,24 @@ class AbstractPickleTests(unittest.TestCase):
y = self.loads(s)
self.assertEqual(y._proto, None)
+ def test_reduce_ex_calls_base(self):
+ for proto in 0, 1, 2:
+ x = REX_four()
+ self.assertEqual(x._proto, None)
+ s = self.dumps(x, proto)
+ self.assertEqual(x._proto, proto)
+ y = self.loads(s)
+ self.assertEqual(y._proto, proto)
+
+ def test_reduce_calls_base(self):
+ for proto in 0, 1, 2:
+ x = REX_five()
+ self.assertEqual(x._reduce_called, 0)
+ s = self.dumps(x, proto)
+ self.assertEqual(x._reduce_called, 1)
+ y = self.loads(s)
+ self.assertEqual(y._reduce_called, 1)
+
# Test classes for reduce_ex
class REX_one(object):
@@ -859,6 +877,20 @@ class REX_three(object):
def __reduce__(self):
raise TestFailed, "This __reduce__ shouldn't be called"
+class REX_four(object):
+ _proto = None
+ def __reduce_ex__(self, proto):
+ self._proto = proto
+ return object.__reduce_ex__(self, proto)
+ # Calling base class method should succeed
+
+class REX_five(object):
+ _reduce_called = 0
+ def __reduce__(self):
+ self._reduce_called = 1
+ return object.__reduce__(self)
+ # This one used to fail with infinite recursion
+
# Test classes for newobj
class MyInt(int):
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 6ef6663..87d9dc9 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -474,7 +474,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False,
STDTESTS = [
'test_grammar',
'test_opcodes',
- 'test_operations',
+ 'test_dict',
'test_builtin',
'test_exceptions',
'test_types',
diff --git a/Lib/test/ssl_cert.pem b/Lib/test/ssl_cert.pem
new file mode 100644
index 0000000..9d7ac23
--- /dev/null
+++ b/Lib/test/ssl_cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD
+VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv
+bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy
+dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X
+DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw
+EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l
+dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT
+EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp
+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw
+L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN
+BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX
+9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4=
+-----END CERTIFICATE-----
diff --git a/Lib/test/ssl_key.pem b/Lib/test/ssl_key.pem
new file mode 100644
index 0000000..239ad66
--- /dev/null
+++ b/Lib/test/ssl_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNwL4lYKbpzzlmC5beaQXeQ
+2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAAQJBALjkK+jc2+iihI98riEF
+oudmkNziSRTYjnwjx8mCoAjPWviB3c742eO3FG4/soi1jD9A5alihEOXfUzloenr
+8IECIQD3B5+0l+68BA/6d76iUNqAAV8djGTzvxnCxycnxPQydQIhAMXt4trUI3nc
+a+U8YL2HPFA3gmhBsSICbq2OptOCnM7hAiEA6Xi3JIQECob8YwkRj29DU3/4WYD7
+WLPgsQpwo1GuSpECICGsnWH5oaeD9t9jbFoSfhJvv0IZmxdcLpRcpslpeWBBAiEA
+6/5B8J0GHdJq89FHwEG/H2eVVUYu5y/aD6sgcm+0Avg=
+-----END RSA PRIVATE KEY-----
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index b0852ee..2431262 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -1104,6 +1104,9 @@ class MixinStrStringUserStringTest:
self.checkequal('Abc', 'abc', 'translate', table)
self.checkequal('xyz', 'xyz', 'translate', table)
self.checkequal('yz', 'xyz', 'translate', table, 'x')
+ self.checkequal('yx', 'zyzzx', 'translate', None, 'z')
+ self.checkequal('zyzzx', 'zyzzx', 'translate', None, '')
+ self.checkequal('zyzzx', 'zyzzx', 'translate', None)
self.checkraises(ValueError, 'xyz', 'translate', 'too short', 'strip')
self.checkraises(ValueError, 'xyz', 'translate', 'too short')
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index bb1fd8d..6003733 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -1,7 +1,5 @@
import unittest
-from test import test_support
-
-from test.test_support import verify, verbose
+from test.test_support import verbose, run_unittest
import sys
import warnings
@@ -20,15 +18,15 @@ class AllTest(unittest.TestCase):
# Silent fail here seems the best route since some modules
# may not be available in all environments.
return
- verify(hasattr(sys.modules[modname], "__all__"),
- "%s has no __all__ attribute" % modname)
+ self.failUnless(hasattr(sys.modules[modname], "__all__"),
+ "%s has no __all__ attribute" % modname)
names = {}
exec("from %s import *" % modname, names)
if "__builtins__" in names:
del names["__builtins__"]
keys = set(names)
all = set(sys.modules[modname].__all__)
- verify(keys==all, "%s != %s" % (keys, all))
+ self.assertEqual(keys, all)
def test_all(self):
if not sys.platform.startswith('java'):
@@ -177,7 +175,7 @@ class AllTest(unittest.TestCase):
def test_main():
- test_support.run_unittest(AllTest)
+ run_unittest(AllTest)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
index ae7156b..34b573f 100755
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -111,6 +111,21 @@ class BaseTest(unittest.TestCase):
self.assertEqual(a.x, b.x)
self.assertEqual(type(a), type(b))
+ def test_pickle_for_empty_array(self):
+ for protocol in (0, 1, 2):
+ a = array.array(self.typecode)
+ b = loads(dumps(a, protocol))
+ self.assertNotEqual(id(a), id(b))
+ self.assertEqual(a, b)
+
+ a = ArraySubclass(self.typecode)
+ a.x = 10
+ b = loads(dumps(a, protocol))
+ self.assertNotEqual(id(a), id(b))
+ self.assertEqual(a, b)
+ self.assertEqual(a.x, b.x)
+ self.assertEqual(type(a), type(b))
+
def test_insert(self):
a = array.array(self.typecode, self.example)
a.insert(0, self.example[0])
@@ -713,7 +728,6 @@ class CharacterTest(StringTest):
return array.array.__new__(cls, 'c', s)
def __init__(self, s, color='blue'):
- array.array.__init__(self, 'c', s)
self.color = color
def strip(self):
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 56077e7..142e543 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -28,7 +28,7 @@ class TestCase(unittest.TestCase):
self.stream = StringIO.StringIO()
sys.stdout = sys.stderr = self.stream
atexit._clear()
-
+
def tearDown(self):
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
@@ -50,63 +50,63 @@ class TestCase(unittest.TestCase):
atexit.register(h2)
atexit.register(h3)
atexit._run_exitfuncs()
-
+
self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
def test_raise(self):
# be sure raises are handled properly
atexit.register(raise1)
atexit.register(raise2)
-
+
self.assertRaises(TypeError, atexit._run_exitfuncs)
-
+
def test_stress(self):
a = [0]
def inc():
a[0] += 1
-
+
for i in range(128):
atexit.register(inc)
atexit._run_exitfuncs()
-
+
self.assertEqual(a[0], 128)
-
+
def test_clear(self):
a = [0]
def inc():
a[0] += 1
-
+
atexit.register(inc)
atexit._clear()
atexit._run_exitfuncs()
-
+
self.assertEqual(a[0], 0)
-
+
def test_unregister(self):
a = [0]
def inc():
a[0] += 1
def dec():
a[0] -= 1
-
- for i in range(4):
+
+ for i in range(4):
atexit.register(inc)
atexit.register(dec)
atexit.unregister(inc)
atexit._run_exitfuncs()
-
+
self.assertEqual(a[0], -1)
-
+
def test_bound_methods(self):
l = []
atexit.register(l.append, 5)
atexit._run_exitfuncs()
self.assertEqual(l, [5])
-
+
atexit.unregister(l.append)
atexit._run_exitfuncs()
self.assertEqual(l, [5])
-
+
def test_main():
test_support.run_unittest(TestCase)
diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py
index 997a413..ff2c370 100644
--- a/Lib/test/test_base64.py
+++ b/Lib/test/test_base64.py
@@ -183,16 +183,8 @@ class BaseXYTestCase(unittest.TestCase):
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(LegacyBase64TestCase))
- suite.addTest(unittest.makeSuite(BaseXYTestCase))
- return suite
-
-
def test_main():
- test_support.run_suite(suite())
-
+ test_support.run_unittest(__name__)
if __name__ == '__main__':
- unittest.main(defaultTest='suite')
+ test_main()
diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py
index 8272ad9..ea8be31 100755
--- a/Lib/test/test_binascii.py
+++ b/Lib/test/test_binascii.py
@@ -148,6 +148,15 @@ class BinASCIITest(unittest.TestCase):
"0"*75+"=\r\n=FF\r\n=FF\r\n=FF"
)
+ self.assertEqual(binascii.b2a_qp('\0\n'), '=00\n')
+ self.assertEqual(binascii.b2a_qp('\0\n', quotetabs=True), '=00\n')
+ self.assertEqual(binascii.b2a_qp('foo\tbar\t\n'), 'foo\tbar=09\n')
+ self.assertEqual(binascii.b2a_qp('foo\tbar\t\n', quotetabs=True), 'foo=09bar=09\n')
+
+ self.assertEqual(binascii.b2a_qp('.'), '=2E')
+ self.assertEqual(binascii.b2a_qp('.\n'), '=2E\n')
+ self.assertEqual(binascii.b2a_qp('a.\n'), 'a.\n')
+
def test_empty_string(self):
# A test for SF bug #1022953. Make sure SystemError is not raised.
for n in ['b2a_qp', 'a2b_hex', 'b2a_base64', 'a2b_uu', 'a2b_qp',
diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py
index 1e19cf5..dd04b27 100644
--- a/Lib/test/test_bool.py
+++ b/Lib/test/test_bool.py
@@ -321,7 +321,7 @@ class BoolTest(unittest.TestCase):
self.assertEqual(pickle.dumps(False), "I00\n.")
self.assertEqual(pickle.dumps(True, True), "I01\n.")
self.assertEqual(pickle.dumps(False, True), "I00\n.")
-
+
try:
import cPickle
except ImportError:
diff --git a/Lib/test/test_bsddb3.py b/Lib/test/test_bsddb3.py
index 69e99c0..fe0469c 100644
--- a/Lib/test/test_bsddb3.py
+++ b/Lib/test/test_bsddb3.py
@@ -4,7 +4,7 @@ Run all test cases.
"""
import sys
import unittest
-from test.test_support import requires, verbose, run_suite, unlink
+from test.test_support import requires, verbose, run_unittest, unlink
# When running as a script instead of within the regrtest framework, skip the
# requires test, since it's obvious we want to run them.
@@ -58,9 +58,7 @@ def suite():
# For invocation through regrtest
def test_main():
- tests = suite()
- run_suite(tests)
-
+ run_unittest(suite())
# For invocation as a script
if __name__ == '__main__':
@@ -73,4 +71,4 @@ if __name__ == '__main__':
print('python version: %s' % sys.version)
print('-=' * 38)
- unittest.main(defaultTest='suite')
+ test_main()
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 500516c..ffa74af 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -107,9 +107,12 @@ class BuiltinTest(unittest.TestCase):
__import__('sys')
__import__('time')
__import__('string')
+ __import__(name='sys')
+ __import__(name='time', level=0)
self.assertRaises(ImportError, __import__, 'spamspam')
self.assertRaises(TypeError, __import__, 1, 2, 3, 4)
self.assertRaises(ValueError, __import__, '')
+ self.assertRaises(TypeError, __import__, 'sys', name='sys')
def test_abs(self):
# int
@@ -207,15 +210,21 @@ class BuiltinTest(unittest.TestCase):
compile('print(1)\n', '', 'exec')
bom = '\xef\xbb\xbf'
compile(bom + 'print(1)\n', '', 'exec')
+ compile(source='pass', filename='?', mode='exec')
+ compile(dont_inherit=0, filename='tmp', source='0', mode='eval')
+ compile('pass', '?', dont_inherit=1, mode='exec')
self.assertRaises(TypeError, compile)
self.assertRaises(ValueError, compile, 'print(42)\n', '<string>', 'badmode')
self.assertRaises(ValueError, compile, 'print(42)\n', '<string>', 'single', 0xff)
self.assertRaises(TypeError, compile, chr(0), 'f', 'exec')
+ self.assertRaises(TypeError, compile, 'pass', '?', 'exec',
+ mode='eval', source='0', filename='tmp')
if have_unicode:
compile(unicode('print(u"\xc3\xa5")\n', 'utf8'), '', 'exec')
self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec')
self.assertRaises(ValueError, compile, unicode('a = 1'), 'f', 'bad')
+
def test_delattr(self):
import sys
sys.spam = 1
@@ -1035,6 +1044,11 @@ class BuiltinTest(unittest.TestCase):
self.assertRaises(ValueError, int, '53', 40)
self.assertRaises(TypeError, int, 1, 12)
+ # SF patch #1638879: embedded NULs were not detected with
+ # explicit base
+ self.assertRaises(ValueError, int, '123\0', 10)
+ self.assertRaises(ValueError, int, '123\x00 245', 20)
+
self.assertEqual(int('100000000000000000000000000000000', 2),
4294967296)
self.assertEqual(int('102002022201221111211', 3), 4294967296)
@@ -1138,10 +1152,10 @@ class BuiltinTest(unittest.TestCase):
self.assertEqual(int(Foo0()), 42)
self.assertEqual(int(Foo1()), 42)
- # XXX invokes __int__ now
+ # XXX invokes __int__ now
# self.assertEqual(long(Foo2()), 42L)
self.assertEqual(int(Foo3()), 0)
- # XXX likewise
+ # XXX likewise
# self.assertEqual(long(Foo4()), 42)
# self.assertRaises(TypeError, long, Foo5())
diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py
index 2295772..85dfa32 100644
--- a/Lib/test/test_cfgparser.py
+++ b/Lib/test/test_cfgparser.py
@@ -417,6 +417,18 @@ class SafeConfigParserTestCase(ConfigParserTestCase):
self.assertEqual(cf.get("section", "ok"), "xxx/%s")
self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
+ def test_set_malformatted_interpolation(self):
+ cf = self.fromstring("[sect]\n"
+ "option1=foo\n")
+
+ self.assertEqual(cf.get('sect', "option1"), "foo")
+
+ self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
+ self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
+ self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
+
+ self.assertEqual(cf.get('sect', "option1"), "foo")
+
def test_set_nonstring_types(self):
cf = self.fromstring("[sect]\n"
"option1=foo\n")
diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py
index fd3a6bf..e091bd6 100755
--- a/Lib/test/test_cmath.py
+++ b/Lib/test/test_cmath.py
@@ -1,52 +1,196 @@
-#! /usr/bin/env python
-""" Simple test script for cmathmodule.c
- Roger E. Masse
-"""
+from test.test_support import run_unittest
+import unittest
import cmath, math
-from test.test_support import verbose, verify, TestFailed
-
-verify(abs(cmath.log(10) - math.log(10)) < 1e-9)
-verify(abs(cmath.log(10,2) - math.log(10,2)) < 1e-9)
-try:
- cmath.log('a')
-except TypeError:
- pass
-else:
- raise TestFailed
-
-try:
- cmath.log(10, 'a')
-except TypeError:
- pass
-else:
- raise TestFailed
-
-
-testdict = {'acos' : 1.0,
- 'acosh' : 1.0,
- 'asin' : 1.0,
- 'asinh' : 1.0,
- 'atan' : 0.2,
- 'atanh' : 0.2,
- 'cos' : 1.0,
- 'cosh' : 1.0,
- 'exp' : 1.0,
- 'log' : 1.0,
- 'log10' : 1.0,
- 'sin' : 1.0,
- 'sinh' : 1.0,
- 'sqrt' : 1.0,
- 'tan' : 1.0,
- 'tanh' : 1.0}
-
-for func in testdict.keys():
- f = getattr(cmath, func)
- r = f(testdict[func])
- if verbose:
- print('Calling %s(%f) = %f' % (func, testdict[func], abs(r)))
-
-p = cmath.pi
-e = cmath.e
-if verbose:
- print('PI = ', abs(p))
- print('E = ', abs(e))
+
+class CMathTests(unittest.TestCase):
+ # list of all functions in cmath
+ test_functions = [getattr(cmath, fname) for fname in [
+ 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
+ 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh',
+ 'sqrt', 'tan', 'tanh']]
+ # test first and second arguments independently for 2-argument log
+ test_functions.append(lambda x : cmath.log(x, 1729. + 0j))
+ test_functions.append(lambda x : cmath.log(14.-27j, x))
+
+ def cAssertAlmostEqual(self, a, b, rel_eps = 1e-10, abs_eps = 1e-100):
+ """Check that two complex numbers are almost equal."""
+ # the two complex numbers are considered almost equal if
+ # either the relative error is <= rel_eps or the absolute error
+ # is tiny, <= abs_eps.
+ if a == b == 0:
+ return
+ absolute_error = abs(a-b)
+ relative_error = absolute_error/max(abs(a), abs(b))
+ if relative_error > rel_eps and absolute_error > abs_eps:
+ self.fail("%s and %s are not almost equal" % (a, b))
+
+ def test_constants(self):
+ e_expected = 2.71828182845904523536
+ pi_expected = 3.14159265358979323846
+ self.assertAlmostEqual(cmath.pi, pi_expected, 9,
+ "cmath.pi is %s; should be %s" % (cmath.pi, pi_expected))
+ self.assertAlmostEqual(cmath.e, e_expected, 9,
+ "cmath.e is %s; should be %s" % (cmath.e, e_expected))
+
+ def test_user_object(self):
+ # Test automatic calling of __complex__ and __float__ by cmath
+ # functions
+
+ # some random values to use as test values; we avoid values
+ # for which any of the functions in cmath is undefined
+ # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow
+ cx_arg = 4.419414439 + 1.497100113j
+ flt_arg = -6.131677725
+
+ # a variety of non-complex numbers, used to check that
+ # non-complex return values from __complex__ give an error
+ non_complexes = ["not complex", 1, 5, 2., None,
+ object(), NotImplemented]
+
+ # Now we introduce a variety of classes whose instances might
+ # end up being passed to the cmath functions
+
+ # usual case: new-style class implementing __complex__
+ class MyComplex(object):
+ def __init__(self, value):
+ self.value = value
+ def __complex__(self):
+ return self.value
+
+ # old-style class implementing __complex__
+ class MyComplexOS:
+ def __init__(self, value):
+ self.value = value
+ def __complex__(self):
+ return self.value
+
+ # classes for which __complex__ raises an exception
+ class SomeException(Exception):
+ pass
+ class MyComplexException(object):
+ def __complex__(self):
+ raise SomeException
+ class MyComplexExceptionOS:
+ def __complex__(self):
+ raise SomeException
+
+ # some classes not providing __float__ or __complex__
+ class NeitherComplexNorFloat(object):
+ pass
+ class NeitherComplexNorFloatOS:
+ pass
+ class MyInt(object):
+ def __int__(self): return 2
+ def __long__(self): return 2
+ def __index__(self): return 2
+ class MyIntOS:
+ def __int__(self): return 2
+ def __long__(self): return 2
+ def __index__(self): return 2
+
+ # other possible combinations of __float__ and __complex__
+ # that should work
+ class FloatAndComplex(object):
+ def __float__(self):
+ return flt_arg
+ def __complex__(self):
+ return cx_arg
+ class FloatAndComplexOS:
+ def __float__(self):
+ return flt_arg
+ def __complex__(self):
+ return cx_arg
+ class JustFloat(object):
+ def __float__(self):
+ return flt_arg
+ class JustFloatOS:
+ def __float__(self):
+ return flt_arg
+
+ for f in self.test_functions:
+ # usual usage
+ self.cAssertAlmostEqual(f(MyComplex(cx_arg)), f(cx_arg))
+ self.cAssertAlmostEqual(f(MyComplexOS(cx_arg)), f(cx_arg))
+ # other combinations of __float__ and __complex__
+ self.cAssertAlmostEqual(f(FloatAndComplex()), f(cx_arg))
+ self.cAssertAlmostEqual(f(FloatAndComplexOS()), f(cx_arg))
+ self.cAssertAlmostEqual(f(JustFloat()), f(flt_arg))
+ self.cAssertAlmostEqual(f(JustFloatOS()), f(flt_arg))
+ # TypeError should be raised for classes not providing
+ # either __complex__ or __float__, even if they provide
+ # __int__, __long__ or __index__. An old-style class
+ # currently raises AttributeError instead of a TypeError;
+ # this could be considered a bug.
+ self.assertRaises(TypeError, f, NeitherComplexNorFloat())
+ self.assertRaises(TypeError, f, MyInt())
+ self.assertRaises(Exception, f, NeitherComplexNorFloatOS())
+ self.assertRaises(Exception, f, MyIntOS())
+ # non-complex return value from __complex__ -> TypeError
+ for bad_complex in non_complexes:
+ self.assertRaises(TypeError, f, MyComplex(bad_complex))
+ self.assertRaises(TypeError, f, MyComplexOS(bad_complex))
+ # exceptions in __complex__ should be propagated correctly
+ self.assertRaises(SomeException, f, MyComplexException())
+ self.assertRaises(SomeException, f, MyComplexExceptionOS())
+
+ def test_input_type(self):
+ # ints and longs should be acceptable inputs to all cmath
+ # functions, by virtue of providing a __float__ method
+ for f in self.test_functions:
+ for arg in [2, 2.]:
+ self.cAssertAlmostEqual(f(arg), f(arg.__float__()))
+
+ # but strings should give a TypeError
+ for f in self.test_functions:
+ for arg in ["a", "long_string", "0", "1j", ""]:
+ self.assertRaises(TypeError, f, arg)
+
+ def test_cmath_matches_math(self):
+ # check that corresponding cmath and math functions are equal
+ # for floats in the appropriate range
+
+ # test_values in (0, 1)
+ test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
+
+ # test_values for functions defined on [-1., 1.]
+ unit_interval = test_values + [-x for x in test_values] + \
+ [0., 1., -1.]
+
+ # test_values for log, log10, sqrt
+ positive = test_values + [1.] + [1./x for x in test_values]
+ nonnegative = [0.] + positive
+
+ # test_values for functions defined on the whole real line
+ real_line = [0.] + positive + [-x for x in positive]
+
+ test_functions = {
+ 'acos' : unit_interval,
+ 'asin' : unit_interval,
+ 'atan' : real_line,
+ 'cos' : real_line,
+ 'cosh' : real_line,
+ 'exp' : real_line,
+ 'log' : positive,
+ 'log10' : positive,
+ 'sin' : real_line,
+ 'sinh' : real_line,
+ 'sqrt' : nonnegative,
+ 'tan' : real_line,
+ 'tanh' : real_line}
+
+ for fn, values in test_functions.items():
+ float_fn = getattr(math, fn)
+ complex_fn = getattr(cmath, fn)
+ for v in values:
+ self.cAssertAlmostEqual(float_fn(v), complex_fn(v))
+
+ # test two-argument version of log with various bases
+ for base in [0.5, 2., 10.]:
+ for v in positive:
+ self.cAssertAlmostEqual(cmath.log(v, base), math.log(v, base))
+
+def test_main():
+ run_unittest(CMathTests)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 5e89863..cacae7a 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -6,7 +6,7 @@ import subprocess
class CmdLineTest(unittest.TestCase):
def start_python(self, cmd_line):
- outfp, infp = popen2.popen4('%s %s' % (sys.executable, cmd_line))
+ outfp, infp = popen2.popen4('"%s" %s' % (sys.executable, cmd_line))
infp.close()
data = outfp.read()
outfp.close()
diff --git a/Lib/test/test_codecencodings_cn.py b/Lib/test/test_codecencodings_cn.py
index c558f1b..96b0d77 100644
--- a/Lib/test/test_codecencodings_cn.py
+++ b/Lib/test/test_codecencodings_cn.py
@@ -51,11 +51,7 @@ class Test_GB18030(test_multibytecodec_support.TestBase, unittest.TestCase):
has_iso10646 = True
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_GB2312))
- suite.addTest(unittest.makeSuite(Test_GBK))
- suite.addTest(unittest.makeSuite(Test_GB18030))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecencodings_hk.py b/Lib/test/test_codecencodings_hk.py
index 1cd020f..b1c2606 100644
--- a/Lib/test/test_codecencodings_hk.py
+++ b/Lib/test/test_codecencodings_hk.py
@@ -21,9 +21,7 @@ class Test_Big5HKSCS(test_multibytecodec_support.TestBase, unittest.TestCase):
)
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_Big5HKSCS))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecencodings_jp.py b/Lib/test/test_codecencodings_jp.py
index 558598a..5f81f41 100644
--- a/Lib/test/test_codecencodings_jp.py
+++ b/Lib/test/test_codecencodings_jp.py
@@ -99,13 +99,7 @@ class Test_SJISX0213(test_multibytecodec_support.TestBase, unittest.TestCase):
)
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_CP932))
- suite.addTest(unittest.makeSuite(Test_EUC_JISX0213))
- suite.addTest(unittest.makeSuite(Test_EUC_JP_COMPAT))
- suite.addTest(unittest.makeSuite(Test_SJIS_COMPAT))
- suite.addTest(unittest.makeSuite(Test_SJISX0213))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecencodings_kr.py b/Lib/test/test_codecencodings_kr.py
index 8139f76..a30eaf9 100644
--- a/Lib/test/test_codecencodings_kr.py
+++ b/Lib/test/test_codecencodings_kr.py
@@ -45,11 +45,7 @@ class Test_JOHAB(test_multibytecodec_support.TestBase, unittest.TestCase):
)
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_CP949))
- suite.addTest(unittest.makeSuite(Test_EUCKR))
- suite.addTest(unittest.makeSuite(Test_JOHAB))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecencodings_tw.py b/Lib/test/test_codecencodings_tw.py
index 7c59478..983d06f 100644
--- a/Lib/test/test_codecencodings_tw.py
+++ b/Lib/test/test_codecencodings_tw.py
@@ -21,9 +21,7 @@ class Test_Big5(test_multibytecodec_support.TestBase, unittest.TestCase):
)
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_Big5))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecmaps_cn.py b/Lib/test/test_codecmaps_cn.py
index 8cbee76..75541ac 100644
--- a/Lib/test/test_codecmaps_cn.py
+++ b/Lib/test/test_codecmaps_cn.py
@@ -20,10 +20,7 @@ class TestGBKMap(test_multibytecodec_support.TestBase_Mapping,
'MICSFT/WINDOWS/CP936.TXT'
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestGB2312Map))
- suite.addTest(unittest.makeSuite(TestGBKMap))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecmaps_hk.py b/Lib/test/test_codecmaps_hk.py
index e7f7b96..1068d0b 100644
--- a/Lib/test/test_codecmaps_hk.py
+++ b/Lib/test/test_codecmaps_hk.py
@@ -14,9 +14,7 @@ class TestBig5HKSCSMap(test_multibytecodec_support.TestBase_Mapping,
mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS.TXT'
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestBig5HKSCSMap))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecmaps_jp.py b/Lib/test/test_codecmaps_jp.py
index 08052d4..5466a98 100644
--- a/Lib/test/test_codecmaps_jp.py
+++ b/Lib/test/test_codecmaps_jp.py
@@ -61,13 +61,7 @@ class TestSJISX0213Map(test_multibytecodec_support.TestBase_Mapping,
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestCP932Map))
- suite.addTest(unittest.makeSuite(TestEUCJPCOMPATMap))
- suite.addTest(unittest.makeSuite(TestSJISCOMPATMap))
- suite.addTest(unittest.makeSuite(TestEUCJISX0213Map))
- suite.addTest(unittest.makeSuite(TestSJISX0213Map))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecmaps_kr.py b/Lib/test/test_codecmaps_kr.py
index 7484a66..1b350b9 100644
--- a/Lib/test/test_codecmaps_kr.py
+++ b/Lib/test/test_codecmaps_kr.py
@@ -34,11 +34,7 @@ class TestJOHABMap(test_multibytecodec_support.TestBase_Mapping,
pass_dectest = [('\\', u'\u20a9')]
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestCP949Map))
- suite.addTest(unittest.makeSuite(TestEUCKRMap))
- suite.addTest(unittest.makeSuite(TestJOHABMap))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_codecmaps_tw.py b/Lib/test/test_codecmaps_tw.py
index 0b195f4..143ae23 100644
--- a/Lib/test/test_codecmaps_tw.py
+++ b/Lib/test/test_codecmaps_tw.py
@@ -25,10 +25,7 @@ class TestCP950Map(test_multibytecodec_support.TestBase_Mapping,
]
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestBIG5Map))
- suite.addTest(unittest.makeSuite(TestCP950Map))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
new file mode 100644
index 0000000..a139129
--- /dev/null
+++ b/Lib/test/test_collections.py
@@ -0,0 +1,57 @@
+import unittest
+from test import test_support
+from collections import NamedTuple
+
+class TestNamedTuple(unittest.TestCase):
+
+ def test_factory(self):
+ Point = NamedTuple('Point', 'x y')
+ self.assertEqual(Point.__name__, 'Point')
+ self.assertEqual(Point.__doc__, 'Point(x, y)')
+ self.assertEqual(Point.__slots__, ())
+ self.assertEqual(Point.__module__, __name__)
+ self.assertEqual(Point.__getitem__, tuple.__getitem__)
+ self.assert_('__getitem__' in Point.__dict__) # superclass methods localized
+
+ def test_instance(self):
+ Point = NamedTuple('Point', 'x y')
+ p = Point(11, 22)
+ self.assertEqual(p, Point(x=11, y=22))
+ self.assertEqual(p, Point(11, y=22))
+ self.assertEqual(p, Point(y=22, x=11))
+ self.assertEqual(p, Point(*(11, 22)))
+ self.assertEqual(p, Point(**dict(x=11, y=22)))
+ self.assertRaises(TypeError, Point, 1) # too few args
+ self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
+ self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
+ self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
+ self.assertEqual(repr(p), 'Point(x=11, y=22)')
+ self.assert_('__dict__' not in dir(p)) # verify instance has no dict
+ self.assert_('__weakref__' not in dir(p))
+
+ def test_tupleness(self):
+ Point = NamedTuple('Point', 'x y')
+ p = Point(11, 22)
+
+ self.assert_(isinstance(p, tuple))
+ self.assertEqual(p, (11, 22)) # matches a real tuple
+ self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
+ self.assertEqual(list(p), [11, 22]) # coercable to a list
+ self.assertEqual(max(p), 22) # iterable
+ self.assertEqual(max(*p), 22) # star-able
+ x, y = p
+ self.assertEqual(p, (x, y)) # unpacks like a tuple
+ self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
+ self.assertRaises(IndexError, p.__getitem__, 3)
+
+ self.assertEqual(p.x, x)
+ self.assertEqual(p.y, y)
+ self.assertRaises(AttributeError, eval, 'p.z', locals())
+
+
+def test_main(verbose=None):
+ test_classes = [TestNamedTuple]
+ test_support.run_unittest(*test_classes)
+
+if __name__ == "__main__":
+ test_main(verbose=True)
diff --git a/Lib/test/test_commands.py b/Lib/test/test_commands.py
index b72a1b9..d899d66 100644
--- a/Lib/test/test_commands.py
+++ b/Lib/test/test_commands.py
@@ -4,6 +4,10 @@
'''
import unittest
import os, tempfile, re
+import warnings
+
+warnings.filterwarnings('ignore', r".*commands.getstatus.. is deprecated",
+ DeprecationWarning)
from test.test_support import TestSkipped, run_unittest, reap_children
from commands import *
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index d5fda13..ae55485 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -399,13 +399,26 @@ if 1:
# is the max. Ensure the result of too many annotations is a
# SyntaxError.
s = "def f((%s)): pass"
- s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65535))
+ s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65535))
self.assertRaises(SyntaxError, compile, s, '?', 'exec')
# Test that the max # of annotations compiles.
s = "def f((%s)): pass"
s %= ', '.join('a%d:%d' % (i,i) for i in xrange(65534))
compile(s, '?', 'exec')
-
+
+ def test_mangling(self):
+ class A:
+ def f():
+ __mangled = 1
+ __not_mangled__ = 2
+ import __mangled_mod
+ import __package__.module
+
+ self.assert_("_A__mangled" in A.f.__code__.co_varnames)
+ self.assert_("__not_mangled__" in A.f.__code__.co_varnames)
+ self.assert_("_A__mangled_mod" in A.f.__code__.co_varnames)
+ self.assert_("__package__" in A.f.__code__.co_varnames)
+
def test_main():
test_support.run_unittest(TestSpecifics)
diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py
index 4fb6cc1..c55dc0e 100644
--- a/Lib/test/test_compiler.py
+++ b/Lib/test/test_compiler.py
@@ -190,7 +190,7 @@ class CompilerTest(unittest.TestCase):
def testBytesLiteral(self):
c = compiler.compile("b'foo'", '<string>', 'eval')
b = eval(c)
-
+
c = compiler.compile('def f(b=b"foo"):\n'
' b[0] += 1\n'
' return b\n'
@@ -200,7 +200,7 @@ class CompilerTest(unittest.TestCase):
dct = {}
exec(c, dct)
self.assertEquals(dct.get('result'), b"ioo")
-
+
c = compiler.compile('def f():\n'
' b = b"foo"\n'
' b[0] += 1\n'
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index 91f074b..0d034f5 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -208,6 +208,8 @@ class ComplexTest(unittest.TestCase):
self.assertAlmostEqual(complex(), 0)
self.assertAlmostEqual(complex("-1"), -1)
self.assertAlmostEqual(complex("+1"), +1)
+ self.assertAlmostEqual(complex("(1+2j)"), 1+2j)
+ self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)
class complex2(complex): pass
self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
@@ -237,12 +239,17 @@ class ComplexTest(unittest.TestCase):
self.assertRaises(ValueError, complex, "")
self.assertRaises(TypeError, complex, None)
self.assertRaises(ValueError, complex, "\0")
+ self.assertRaises(ValueError, complex, "3\09")
self.assertRaises(TypeError, complex, "1", "2")
self.assertRaises(TypeError, complex, "1", 42)
self.assertRaises(TypeError, complex, 1, "2")
self.assertRaises(ValueError, complex, "1+")
self.assertRaises(ValueError, complex, "1+1j+1j")
self.assertRaises(ValueError, complex, "--")
+ self.assertRaises(ValueError, complex, "(1+2j")
+ self.assertRaises(ValueError, complex, "1+2j)")
+ self.assertRaises(ValueError, complex, "1+(2j)")
+ self.assertRaises(ValueError, complex, "(1+2j)123")
if test_support.have_unicode:
self.assertRaises(ValueError, complex, unicode("1"*500))
self.assertRaises(ValueError, complex, unicode("x"))
@@ -305,6 +312,11 @@ class ComplexTest(unittest.TestCase):
self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')
+ self.assertEqual(1-6j,complex(repr(1-6j)))
+ self.assertEqual(1+6j,complex(repr(1+6j)))
+ self.assertEqual(-6j,complex(repr(-6j)))
+ self.assertEqual(6j,complex(repr(6j)))
+
def test_neg(self):
self.assertEqual(-(1+6j), -1-6j)
diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py
index 9142428..a3a9a5b 100644
--- a/Lib/test/test_contextlib.py
+++ b/Lib/test/test_contextlib.py
@@ -9,7 +9,7 @@ import tempfile
import unittest
import threading
from contextlib import * # Tests __all__
-from test.test_support import run_suite
+from test import test_support
class ContextManagerTestCase(unittest.TestCase):
@@ -332,9 +332,7 @@ class LockContextTestCase(unittest.TestCase):
# This is needed to make the test actually run under regrtest.py!
def test_main():
- run_suite(
- unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__])
- )
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py
index 7336711..a9c28cd 100755
--- a/Lib/test/test_crypt.py
+++ b/Lib/test/test_crypt.py
@@ -3,7 +3,7 @@
Roger E. Masse
"""
-from test.test_support import verify, verbose
+from test.test_support import verbose
import crypt
c = crypt.crypt('mypassword', 'ab')
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index 980f3fc..0ca6b78 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -484,12 +484,16 @@ class TestDialectExcel(TestCsvBase):
self.readerAssertEqual('a"b"c', [['a"b"c']])
def test_quotes_and_more(self):
+ # Excel would never write a field containing '"a"b', but when
+ # reading one, it will return 'ab'.
self.readerAssertEqual('"a"b', [['ab']])
def test_lone_quote(self):
self.readerAssertEqual('a"b', [['a"b']])
def test_quote_and_quote(self):
+ # Excel would never write a field containing '"a" "b"', but when
+ # reading one, it will return 'a "b"'.
self.readerAssertEqual('"a" "b"', [['a "b"']])
def test_space_and_quote(self):
diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py
index fd2032b..7a81ab4 100644
--- a/Lib/test/test_ctypes.py
+++ b/Lib/test/test_ctypes.py
@@ -1,12 +1,12 @@
import unittest
-from test.test_support import run_suite
+from test.test_support import run_unittest
import ctypes.test
def test_main():
skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0)
suites = [unittest.makeSuite(t) for t in testcases]
- run_suite(unittest.TestSuite(suites))
+ run_unittest(unittest.TestSuite(suites))
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index fd8e6ed..ee679e7 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -129,6 +129,12 @@ def window_funcs(stdscr):
stdscr.touchline(5,5,0)
stdscr.vline('a', 3)
stdscr.vline('a', 3, curses.A_STANDOUT)
+ stdscr.chgat(5, 2, 3, curses.A_BLINK)
+ stdscr.chgat(3, curses.A_BOLD)
+ stdscr.chgat(5, 8, curses.A_UNDERLINE)
+ stdscr.chgat(curses.A_BLINK)
+ stdscr.refresh()
+
stdscr.vline(1,1, 'a', 3)
stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
@@ -241,12 +247,21 @@ def test_userptr_without_set(stdscr):
except curses.panel.error:
pass
+def test_resize_term(stdscr):
+ if hasattr(curses, 'resizeterm'):
+ lines, cols = curses.LINES, curses.COLS
+ curses.resizeterm(lines - 1, cols + 1)
+
+ if curses.LINES != lines - 1 or curses.COLS != cols + 1:
+ raise RuntimeError, "Expected resizeterm to update LINES and COLS"
+
def main(stdscr):
curses.savetty()
try:
module_funcs(stdscr)
window_funcs(stdscr)
test_userptr_without_set(stdscr)
+ test_resize_term(stdscr)
finally:
curses.resetty()
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index 8a7c1b6..287585e 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -3,6 +3,7 @@
See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
"""
+import os
import sys
import pickle
import unittest
@@ -135,7 +136,7 @@ class TestTZInfo(unittest.TestCase):
# Base clase for testing a particular aspect of timedelta, time, date and
# datetime comparisons.
-class HarmlessMixedComparison(unittest.TestCase):
+class HarmlessMixedComparison:
# Test that __eq__ and __ne__ don't complain for mixed-type comparisons.
# Subclasses must define 'theclass', and theclass(1, 1, 1) must be a
@@ -174,7 +175,7 @@ class HarmlessMixedComparison(unittest.TestCase):
#############################################################################
# timedelta tests
-class TestTimeDelta(HarmlessMixedComparison):
+class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
theclass = timedelta
@@ -521,7 +522,7 @@ class TestDateOnly(unittest.TestCase):
class SubclassDate(date):
sub_var = 1
-class TestDate(HarmlessMixedComparison):
+class TestDate(HarmlessMixedComparison, unittest.TestCase):
# Tests here should pass for both dates and datetimes, except for a
# few tests that TestDateTime overrides.
@@ -1452,6 +1453,21 @@ class TestDateTime(TestDate):
self.assertRaises(ValueError, self.theclass.utcfromtimestamp,
insane)
+ def test_negative_float_fromtimestamp(self):
+ # Windows doesn't accept negative timestamps
+ if os.name == "nt":
+ return
+ # The result is tz-dependent; at least test that this doesn't
+ # fail (like it did before bug 1646728 was fixed).
+ self.theclass.fromtimestamp(-1.05)
+
+ def test_negative_float_utcfromtimestamp(self):
+ # Windows doesn't accept negative timestamps
+ if os.name == "nt":
+ return
+ d = self.theclass.utcfromtimestamp(-1.05)
+ self.assertEquals(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000))
+
def test_utcnow(self):
import time
@@ -1607,7 +1623,7 @@ class TestDateTime(TestDate):
class SubclassTime(time):
sub_var = 1
-class TestTime(HarmlessMixedComparison):
+class TestTime(HarmlessMixedComparison, unittest.TestCase):
theclass = time
@@ -1890,7 +1906,7 @@ class TestTime(HarmlessMixedComparison):
# A mixin for classes with a tzinfo= argument. Subclasses must define
# theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever)
# must be legit (which is true for time and datetime).
-class TZInfoBase(unittest.TestCase):
+class TZInfoBase:
def test_argument_passing(self):
cls = self.theclass
@@ -2050,7 +2066,7 @@ class TZInfoBase(unittest.TestCase):
# Testing time objects with a non-None tzinfo.
-class TestTimeTZ(TestTime, TZInfoBase):
+class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
theclass = time
def test_empty(self):
@@ -2298,7 +2314,7 @@ class TestTimeTZ(TestTime, TZInfoBase):
# Testing datetime objects with a non-None tzinfo.
-class TestDateTimeTZ(TestDateTime, TZInfoBase):
+class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
theclass = datetime
def test_trivial(self):
@@ -3259,45 +3275,8 @@ class Oddballs(unittest.TestCase):
self.assertEqual(as_datetime, datetime_sc)
self.assertEqual(datetime_sc, as_datetime)
-def test_suite():
- allsuites = [unittest.makeSuite(klass, 'test')
- for klass in (TestModule,
- TestTZInfo,
- TestTimeDelta,
- TestDateOnly,
- TestDate,
- TestDateTime,
- TestTime,
- TestTimeTZ,
- TestDateTimeTZ,
- TestTimezoneConversions,
- Oddballs,
- )
- ]
- return unittest.TestSuite(allsuites)
-
def test_main():
- import gc
- import sys
-
- thesuite = test_suite()
- lastrc = None
- while True:
- test_support.run_suite(thesuite)
- if 1: # change to 0, under a debug build, for some leak detection
- break
- gc.collect()
- if gc.garbage:
- raise SystemError("gc.garbage not empty after test run: %r" %
- gc.garbage)
- if hasattr(sys, 'gettotalrefcount'):
- thisrc = sys.gettotalrefcount()
- print('*' * 10, 'total refs:', thisrc, end=' ', file=sys.stderr)
- if lastrc:
- print('delta:', thisrc - lastrc, file=sys.stderr)
- else:
- print(file=sys.stderr)
- lastrc = thisrc
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py
index c8ae2be..a8dfdb1 100644
--- a/Lib/test/test_defaultdict.py
+++ b/Lib/test/test_defaultdict.py
@@ -132,6 +132,15 @@ class TestDefaultDict(unittest.TestCase):
self.assertEqual(d2.default_factory, list)
self.assertEqual(d2, d1)
+ def test_keyerror_without_factory(self):
+ d1 = defaultdict()
+ try:
+ d1[(1,)]
+ except KeyError as err:
+ self.assertEqual(err.message, (1,))
+ else:
+ self.fail("expected KeyError")
+
def test_main():
test_support.run_unittest(TestDefaultDict)
diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
index 7df31b7..4f7e60c 100644
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -575,7 +575,7 @@ deque(['a', 'b', 'd', 'e', 'f'])
>>> for value in roundrobin('abc', 'd', 'efgh'):
... print(value)
-...
+...
a
d
e
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index eec4e40..aba1c74 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -773,6 +773,22 @@ def metaclass():
except TypeError: pass
else: raise TestFailed, "calling object w/o call method should raise TypeError"
+ # Testing code to find most derived baseclass
+ class A(type):
+ def __new__(*args, **kwargs):
+ return type.__new__(*args, **kwargs)
+
+ class B(object):
+ pass
+
+ class C(object, metaclass=A):
+ pass
+
+ # The most derived metaclass of D is A rather than type.
+ class D(B, C):
+ pass
+
+
def pymods():
if verbose: print("Testing Python subclass of module...")
log = []
@@ -1072,6 +1088,45 @@ def slots():
raise TestFailed, "[''] slots not caught"
class C(object):
__slots__ = ["a", "a_b", "_a", "A0123456789Z"]
+ # XXX(nnorwitz): was there supposed to be something tested
+ # from the class above?
+
+ # Test a single string is not expanded as a sequence.
+ class C(object):
+ __slots__ = "abc"
+ c = C()
+ c.abc = 5
+ vereq(c.abc, 5)
+
+ # Test unicode slot names
+ try:
+ unicode
+ except NameError:
+ pass
+ else:
+ # Test a single unicode string is not expanded as a sequence.
+ class C(object):
+ __slots__ = unicode("abc")
+ c = C()
+ c.abc = 5
+ vereq(c.abc, 5)
+
+ # _unicode_to_string used to modify slots in certain circumstances
+ slots = (unicode("foo"), unicode("bar"))
+ class C(object):
+ __slots__ = slots
+ x = C()
+ x.foo = 5
+ vereq(x.foo, 5)
+ veris(type(slots[0]), unicode)
+ # this used to leak references
+ try:
+ class C(object):
+ __slots__ = [unichr(128)]
+ except (TypeError, UnicodeEncodeError):
+ pass
+ else:
+ raise TestFailed, "[unichr(128)] slots not caught"
# Test leaks
class Counted(object):
@@ -1318,6 +1373,22 @@ def errors():
else:
verify(0, "__slots__ = [1] should be illegal")
+ class M1(type):
+ pass
+ class M2(type):
+ pass
+ class A1(object, metaclass=M1):
+ pass
+ class A2(object, metaclass=M2):
+ pass
+ try:
+ class B(A1, A2):
+ pass
+ except TypeError:
+ pass
+ else:
+ verify(0, "finding the most derived metaclass should have failed")
+
def classmethods():
if verbose: print("Testing class methods...")
class C(object):
@@ -2092,7 +2163,6 @@ def inherits():
__slots__ = ['prec']
def __init__(self, value=0.0, prec=12):
self.prec = int(prec)
- float.__init__(self, value)
def __repr__(self):
return "%.*g" % (self.prec, self)
vereq(repr(precfloat(1.1)), "1.1")
@@ -2644,6 +2714,51 @@ def setclass():
cant(o, type(1))
cant(o, type(None))
del o
+ class G(object):
+ __slots__ = ["a", "b"]
+ class H(object):
+ __slots__ = ["b", "a"]
+ try:
+ unicode
+ except NameError:
+ class I(object):
+ __slots__ = ["a", "b"]
+ else:
+ class I(object):
+ __slots__ = [unicode("a"), unicode("b")]
+ class J(object):
+ __slots__ = ["c", "b"]
+ class K(object):
+ __slots__ = ["a", "b", "d"]
+ class L(H):
+ __slots__ = ["e"]
+ class M(I):
+ __slots__ = ["e"]
+ class N(J):
+ __slots__ = ["__weakref__"]
+ class P(J):
+ __slots__ = ["__dict__"]
+ class Q(J):
+ pass
+ class R(J):
+ __slots__ = ["__dict__", "__weakref__"]
+
+ for cls, cls2 in ((G, H), (G, I), (I, H), (Q, R), (R, Q)):
+ x = cls()
+ x.a = 1
+ x.__class__ = cls2
+ verify(x.__class__ is cls2,
+ "assigning %r as __class__ for %r silently failed" % (cls2, x))
+ vereq(x.a, 1)
+ x.__class__ = cls
+ verify(x.__class__ is cls,
+ "assigning %r as __class__ for %r silently failed" % (cls, x))
+ vereq(x.a, 1)
+ for cls in G, J, K, L, M, N, P, R, list, Int:
+ for cls2 in G, J, K, L, M, N, P, R, list, Int:
+ if cls is cls2:
+ continue
+ cant(cls(), cls2)
def setdict():
if verbose: print("Testing __dict__ assignment...")
@@ -3999,6 +4114,19 @@ def notimplemented():
check(iexpr, c, N1)
check(iexpr, c, N2)
+def test_assign_slice():
+ # ceval.c's assign_slice used to check for
+ # tp->tp_as_sequence->sq_slice instead of
+ # tp->tp_as_sequence->sq_ass_slice
+
+ class C(object):
+ def __setslice__(self, start, stop, value):
+ self.value = value
+
+ c = C()
+ c[1:2] = 3
+ vereq(c.value, 3)
+
def test_main():
weakref_segfault() # Must be first, somehow
wrapper_segfault()
@@ -4094,6 +4222,7 @@ def test_main():
test_init()
methodwrapper()
notimplemented()
+ test_assign_slice()
if verbose: print("All OK")
diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py
index 001aa49..5b11666 100644
--- a/Lib/test/test_descrtut.py
+++ b/Lib/test/test_descrtut.py
@@ -243,7 +243,7 @@ methods. Static methods are easy to describe: they behave pretty much like
static methods in C++ or Java. Here's an example:
>>> class C:
- ...
+ ...
... @staticmethod
... def foo(x, y):
... print("staticmethod", x, y)
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index d8dfd7e..d98c607 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -425,7 +425,7 @@ class DictTest(unittest.TestCase):
except RuntimeError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("e[42] didn't raise RuntimeError")
+ self.fail("e[42] didn't raise RuntimeError")
class F(dict):
def __init__(self):
# An instance variable __missing__ should have no effect
@@ -436,7 +436,7 @@ class DictTest(unittest.TestCase):
except KeyError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("f[42] didn't raise KeyError")
+ self.fail("f[42] didn't raise KeyError")
class G(dict):
pass
g = G()
@@ -445,7 +445,7 @@ class DictTest(unittest.TestCase):
except KeyError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("g[42] didn't raise KeyError")
+ self.fail("g[42] didn't raise KeyError")
def test_tuple_keyerror(self):
# SF #1576657
@@ -457,6 +457,76 @@ class DictTest(unittest.TestCase):
else:
self.fail("missing KeyError")
+ def test_bad_key(self):
+ # Dictionary lookups should fail if __cmp__() raises an exception.
+ class CustomException(Exception):
+ pass
+
+ class BadDictKey:
+ def __hash__(self):
+ return hash(self.__class__)
+
+ def __eq__(self, other):
+ if isinstance(other, self.__class__):
+ raise CustomException
+ return other
+
+ d = {}
+ x1 = BadDictKey()
+ x2 = BadDictKey()
+ d[x1] = 1
+ for stmt in ['d[x2] = 2',
+ 'z = d[x2]',
+ 'x2 in d',
+ 'd.get(x2)',
+ 'd.setdefault(x2, 42)',
+ 'd.pop(x2)',
+ 'd.update({x2: 2})']:
+ try:
+ exec(stmt, locals())
+ except CustomException:
+ pass
+ else:
+ self.fail("Statement %r didn't raise exception" % stmt)
+
+ def test_resize1(self):
+ # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
+ # This version got an assert failure in debug build, infinite loop in
+ # release build. Unfortunately, provoking this kind of stuff requires
+ # a mix of inserts and deletes hitting exactly the right hash codes in
+ # exactly the right order, and I can't think of a randomized approach
+ # that would be *likely* to hit a failing case in reasonable time.
+
+ d = {}
+ for i in range(5):
+ d[i] = i
+ for i in range(5):
+ del d[i]
+ for i in range(5, 9): # i==8 was the problem
+ d[i] = i
+
+ def test_resize2(self):
+ # Another dict resizing bug (SF bug #1456209).
+ # This caused Segmentation faults or Illegal instructions.
+
+ class X(object):
+ def __hash__(self):
+ return 5
+ def __eq__(self, other):
+ if resizing:
+ d.clear()
+ return False
+ d = {}
+ resizing = False
+ d[X()] = 1
+ d[X()] = 2
+ d[X()] = 3
+ d[X()] = 4
+ d[X()] = 5
+ # now trigger a resize
+ resizing = True
+ d[9] = 6
+
from test import mapping_tests
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 8e97a6a..5d82cd7 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -1,11 +1,11 @@
-from test.test_support import verify, verbose, TestFailed, run_unittest
+# Minimal tests for dis module
+
+from test.test_support import verbose, run_unittest
+import unittest
import sys
import dis
import StringIO
-# Minimal tests for dis module
-
-import unittest
def _f(a):
print(a)
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 087b340..60079a6 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -35,7 +35,7 @@ class SampleClass:
>>> for i in range(10):
... sc = sc.double()
... print(sc.get(), end=' ')
- 6 12 24 48 96 192 384 768 1536 3072
+ 6 12 24 48 96 192 384 768 1536 3072
"""
def __init__(self, val):
"""
@@ -571,7 +571,7 @@ DocTestFinder finds the line number of each example:
...
... >>> for x in range(10):
... ... print(x, end=' ')
- ... 0 1 2 3 4 5 6 7 8 9
+ ... 0 1 2 3 4 5 6 7 8 9
... >>> x//2
... 6
... '''
@@ -1461,11 +1461,11 @@ at the end of any line:
>>> def f(x): r'''
... >>> for x in range(10): # doctest: +ELLIPSIS
... ... print(x, end=' ')
- ... 0 1 2 ... 9
+ ... 0 1 2 ... 9
...
... >>> for x in range(10):
... ... print(x, end=' ') # doctest: +ELLIPSIS
- ... 0 1 2 ... 9
+ ... 0 1 2 ... 9
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
@@ -1478,7 +1478,7 @@ option directive, then they are combined:
... Should fail (option directive not on the last line):
... >>> for x in range(10): # doctest: +ELLIPSIS
... ... print(x, end=' ') # doctest: +NORMALIZE_WHITESPACE
- ... 0 1 2...9
+ ... 0 1 2...9
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
diff --git a/Lib/test/test_email.py b/Lib/test/test_email.py
index de0eee3..f609968 100644
--- a/Lib/test/test_email.py
+++ b/Lib/test/test_email.py
@@ -4,10 +4,10 @@
import unittest
# The specific tests now live in Lib/email/test
from email.test.test_email import suite
-from test.test_support import run_suite
+from test import test_support
def test_main():
- run_suite(suite())
+ test_support.run_unittest(suite())
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_email_codecs.py b/Lib/test/test_email_codecs.py
index c550a6f..8951f81 100644
--- a/Lib/test/test_email_codecs.py
+++ b/Lib/test/test_email_codecs.py
@@ -9,7 +9,7 @@ from test import test_support
def test_main():
suite = test_email_codecs.suite()
suite.addTest(test_email_codecs_renamed.suite())
- test_support.run_suite(suite)
+ test_support.run_unittest(suite)
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_email_renamed.py b/Lib/test/test_email_renamed.py
index c3af598..163e791 100644
--- a/Lib/test/test_email_renamed.py
+++ b/Lib/test/test_email_renamed.py
@@ -4,10 +4,10 @@
import unittest
# The specific tests now live in Lib/email/test
from email.test.test_email_renamed import suite
-from test.test_support import run_suite
+from test import test_support
def test_main():
- run_suite(suite())
+ test_support.run_unittest(suite())
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index c0a5094..5a22297 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -229,6 +229,9 @@ class ExceptionTests(unittest.TestCase):
(EnvironmentError, (1, 'strErrorStr', 'filenameStr'),
{'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1,
'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}),
+ (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None,
+ 'filename' : None, 'lineno' : None, 'offset' : None,
+ 'print_file_and_line' : None}),
(SyntaxError, ('msgStr',),
{'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None,
'print_file_and_line' : None, 'msg' : 'msgStr',
@@ -337,7 +340,7 @@ class ExceptionTests(unittest.TestCase):
def testExceptionCleanup(self):
# Make sure "except V as N" exceptions are cleaned up properly
-
+
try:
raise Exception()
except Exception as e:
diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py
index 17ca944..10d3cfc 100644
--- a/Lib/test/test_fileinput.py
+++ b/Lib/test/test_fileinput.py
@@ -3,7 +3,9 @@ Tests for fileinput module.
Nick Mathewson
'''
-from test.test_support import verify, verbose, TESTFN, TestFailed
+import unittest
+from test.test_support import verbose, TESTFN, run_unittest
+from test.test_support import unlink as safe_unlink
import sys, os, re
from StringIO import StringIO
from fileinput import FileInput, hook_encoded
@@ -18,211 +20,206 @@ from fileinput import FileInput, hook_encoded
def writeTmp(i, lines, mode='w'): # opening in text mode is the default
name = TESTFN + str(i)
f = open(name, mode)
- for line in lines:
- f.write(line)
+ f.writelines(lines)
f.close()
return name
-pat = re.compile(r'LINE (\d+) OF FILE (\d+)')
-
def remove_tempfiles(*names):
for name in names:
- try:
- os.unlink(name)
- except:
- pass
-
-def runTests(t1, t2, t3, t4, bs=0, round=0):
- start = 1 + round*6
- if verbose:
- print('%s. Simple iteration (bs=%s)' % (start+0, bs))
- fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
- lines = list(fi)
- fi.close()
- verify(len(lines) == 31)
- verify(lines[4] == 'Line 5 of file 1\n')
- verify(lines[30] == 'Line 1 of file 4\n')
- verify(fi.lineno() == 31)
- verify(fi.filename() == t4)
-
- if verbose:
- print('%s. Status variables (bs=%s)' % (start+1, bs))
- fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
- s = "x"
- while s and s != 'Line 6 of file 2\n':
- s = fi.readline()
- verify(fi.filename() == t2)
- verify(fi.lineno() == 21)
- verify(fi.filelineno() == 6)
- verify(not fi.isfirstline())
- verify(not fi.isstdin())
-
- if verbose:
- print('%s. Nextfile (bs=%s)' % (start+2, bs))
- fi.nextfile()
- verify(fi.readline() == 'Line 1 of file 3\n')
- verify(fi.lineno() == 22)
- fi.close()
-
- if verbose:
- print('%s. Stdin (bs=%s)' % (start+3, bs))
- fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs)
- savestdin = sys.stdin
- try:
- sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n")
+ safe_unlink(name)
+
+class BufferSizesTests(unittest.TestCase):
+ def test_buffer_sizes(self):
+ # First, run the tests with default and teeny buffer size.
+ for round, bs in (0, 0), (1, 30):
+ try:
+ t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)])
+ t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)])
+ t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)])
+ t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)])
+ self.buffer_size_test(t1, t2, t3, t4, bs, round)
+ finally:
+ remove_tempfiles(t1, t2, t3, t4)
+
+ def buffer_size_test(self, t1, t2, t3, t4, bs=0, round=0):
+ pat = re.compile(r'LINE (\d+) OF FILE (\d+)')
+
+ start = 1 + round*6
+ if verbose:
+ print('%s. Simple iteration (bs=%s)' % (start+0, bs))
+ fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
lines = list(fi)
- verify(len(lines) == 33)
- verify(lines[32] == 'Line 2 of stdin\n')
- verify(fi.filename() == '<stdin>')
+ fi.close()
+ self.assertEqual(len(lines), 31)
+ self.assertEqual(lines[4], 'Line 5 of file 1\n')
+ self.assertEqual(lines[30], 'Line 1 of file 4\n')
+ self.assertEqual(fi.lineno(), 31)
+ self.assertEqual(fi.filename(), t4)
+
+ if verbose:
+ print('%s. Status variables (bs=%s)' % (start+1, bs))
+ fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
+ s = "x"
+ while s and s != 'Line 6 of file 2\n':
+ s = fi.readline()
+ self.assertEqual(fi.filename(), t2)
+ self.assertEqual(fi.lineno(), 21)
+ self.assertEqual(fi.filelineno(), 6)
+ self.failIf(fi.isfirstline())
+ self.failIf(fi.isstdin())
+
+ if verbose:
+ print('%s. Nextfile (bs=%s)' % (start+2, bs))
+ fi.nextfile()
+ self.assertEqual(fi.readline(), 'Line 1 of file 3\n')
+ self.assertEqual(fi.lineno(), 22)
+ fi.close()
+
+ if verbose:
+ print('%s. Stdin (bs=%s)' % (start+3, bs))
+ fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs)
+ savestdin = sys.stdin
+ try:
+ sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n")
+ lines = list(fi)
+ self.assertEqual(len(lines), 33)
+ self.assertEqual(lines[32], 'Line 2 of stdin\n')
+ self.assertEqual(fi.filename(), '<stdin>')
+ fi.nextfile()
+ finally:
+ sys.stdin = savestdin
+
+ if verbose:
+ print('%s. Boundary conditions (bs=%s)' % (start+4, bs))
+ fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
+ self.assertEqual(fi.lineno(), 0)
+ self.assertEqual(fi.filename(), None)
fi.nextfile()
- finally:
- sys.stdin = savestdin
-
- if verbose:
- print('%s. Boundary conditions (bs=%s)' % (start+4, bs))
- fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
- verify(fi.lineno() == 0)
- verify(fi.filename() == None)
- fi.nextfile()
- verify(fi.lineno() == 0)
- verify(fi.filename() == None)
-
- if verbose:
- print('%s. Inplace (bs=%s)' % (start+5, bs))
- savestdout = sys.stdout
- try:
- fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs)
+ self.assertEqual(fi.lineno(), 0)
+ self.assertEqual(fi.filename(), None)
+
+ if verbose:
+ print('%s. Inplace (bs=%s)' % (start+5, bs))
+ savestdout = sys.stdout
+ try:
+ fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs)
+ for line in fi:
+ line = line[:-1].upper()
+ print(line)
+ fi.close()
+ finally:
+ sys.stdout = savestdout
+
+ fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
for line in fi:
- line = line[:-1].upper()
- print(line)
+ self.assertEqual(line[-1], '\n')
+ m = pat.match(line[:-1])
+ self.assertNotEqual(m, None)
+ self.assertEqual(int(m.group(1)), fi.filelineno())
fi.close()
- finally:
- sys.stdout = savestdout
-
- fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
- for line in fi:
- verify(line[-1] == '\n')
- m = pat.match(line[:-1])
- verify(m != None)
- verify(int(m.group(1)) == fi.filelineno())
- fi.close()
-
-
-def writeFiles():
- global t1, t2, t3, t4
- t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)])
- t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)])
- t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)])
- t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)])
-
-# First, run the tests with default and teeny buffer size.
-for round, bs in (0, 0), (1, 30):
- try:
- writeFiles()
- runTests(t1, t2, t3, t4, bs, round)
- finally:
- remove_tempfiles(t1, t2, t3, t4)
-
-# Next, check for proper behavior with 0-byte files.
-if verbose:
- print("13. 0-byte files")
-try:
- t1 = writeTmp(1, [""])
- t2 = writeTmp(2, [""])
- t3 = writeTmp(3, ["The only line there is.\n"])
- t4 = writeTmp(4, [""])
- fi = FileInput(files=(t1, t2, t3, t4))
- line = fi.readline()
- verify(line == 'The only line there is.\n')
- verify(fi.lineno() == 1)
- verify(fi.filelineno() == 1)
- verify(fi.filename() == t3)
- line = fi.readline()
- verify(not line)
- verify(fi.lineno() == 1)
- verify(fi.filelineno() == 0)
- verify(fi.filename() == t4)
- fi.close()
-finally:
- remove_tempfiles(t1, t2, t3, t4)
-
-if verbose:
- print("14. Files that don't end with newline")
-try:
- t1 = writeTmp(1, ["A\nB\nC"])
- t2 = writeTmp(2, ["D\nE\nF"])
- fi = FileInput(files=(t1, t2))
- lines = list(fi)
- verify(lines == ["A\n", "B\n", "C", "D\n", "E\n", "F"])
- verify(fi.filelineno() == 3)
- verify(fi.lineno() == 6)
-finally:
- remove_tempfiles(t1, t2)
-
-if verbose:
- print("15. Unicode filenames")
-try:
- t1 = writeTmp(1, ["A\nB"])
- encoding = sys.getfilesystemencoding()
- if encoding is None:
- encoding = 'ascii'
- fi = FileInput(files=unicode(t1, encoding))
- lines = list(fi)
- verify(lines == ["A\n", "B"])
-finally:
- remove_tempfiles(t1)
-
-if verbose:
- print("16. fileno()")
-try:
- t1 = writeTmp(1, ["A\nB"])
- t2 = writeTmp(2, ["C\nD"])
- fi = FileInput(files=(t1, t2))
- verify(fi.fileno() == -1)
- line = next(fi)
- verify(fi.fileno() != -1)
- fi.nextfile()
- verify(fi.fileno() == -1)
- line = list(fi)
- verify(fi.fileno() == -1)
-finally:
- remove_tempfiles(t1, t2)
-
-if verbose:
- print("17. Specify opening mode")
-try:
- # invalid mode, should raise ValueError
- fi = FileInput(mode="w")
- raise TestFailed("FileInput should reject invalid mode argument")
-except ValueError:
- pass
-try:
- # try opening in universal newline mode
- t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb")
- fi = FileInput(files=t1, mode="U")
- lines = list(fi)
- verify(lines == ["A\n", "B\n", "C\n", "D"])
-finally:
- remove_tempfiles(t1)
-
-if verbose:
- print("18. Test file opening hook")
-try:
- # cannot use openhook and inplace mode
- fi = FileInput(inplace=1, openhook=lambda f,m: None)
- raise TestFailed("FileInput should raise if both inplace "
- "and openhook arguments are given")
-except ValueError:
- pass
-try:
- fi = FileInput(openhook=1)
- raise TestFailed("FileInput should check openhook for being callable")
-except ValueError:
- pass
-try:
- t1 = writeTmp(1, ["A\nB"], mode="wb")
- fi = FileInput(files=t1, openhook=hook_encoded("rot13"))
- lines = list(fi)
- verify(lines == ["N\n", "O"])
-finally:
- remove_tempfiles(t1)
+
+class FileInputTests(unittest.TestCase):
+ def test_zero_byte_files(self):
+ try:
+ t1 = writeTmp(1, [""])
+ t2 = writeTmp(2, [""])
+ t3 = writeTmp(3, ["The only line there is.\n"])
+ t4 = writeTmp(4, [""])
+ fi = FileInput(files=(t1, t2, t3, t4))
+
+ line = fi.readline()
+ self.assertEqual(line, 'The only line there is.\n')
+ self.assertEqual(fi.lineno(), 1)
+ self.assertEqual(fi.filelineno(), 1)
+ self.assertEqual(fi.filename(), t3)
+
+ line = fi.readline()
+ self.failIf(line)
+ self.assertEqual(fi.lineno(), 1)
+ self.assertEqual(fi.filelineno(), 0)
+ self.assertEqual(fi.filename(), t4)
+ fi.close()
+ finally:
+ remove_tempfiles(t1, t2, t3, t4)
+
+ def test_files_that_dont_end_with_newline(self):
+ try:
+ t1 = writeTmp(1, ["A\nB\nC"])
+ t2 = writeTmp(2, ["D\nE\nF"])
+ fi = FileInput(files=(t1, t2))
+ lines = list(fi)
+ self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"])
+ self.assertEqual(fi.filelineno(), 3)
+ self.assertEqual(fi.lineno(), 6)
+ finally:
+ remove_tempfiles(t1, t2)
+
+ def test_unicode_filenames(self):
+ try:
+ t1 = writeTmp(1, ["A\nB"])
+ encoding = sys.getfilesystemencoding()
+ if encoding is None:
+ encoding = 'ascii'
+ fi = FileInput(files=unicode(t1, encoding))
+ lines = list(fi)
+ self.assertEqual(lines, ["A\n", "B"])
+ finally:
+ remove_tempfiles(t1)
+
+ def test_fileno(self):
+ try:
+ t1 = writeTmp(1, ["A\nB"])
+ t2 = writeTmp(2, ["C\nD"])
+ fi = FileInput(files=(t1, t2))
+ self.assertEqual(fi.fileno(), -1)
+ line =next( fi)
+ self.assertNotEqual(fi.fileno(), -1)
+ fi.nextfile()
+ self.assertEqual(fi.fileno(), -1)
+ line = list(fi)
+ self.assertEqual(fi.fileno(), -1)
+ finally:
+ remove_tempfiles(t1, t2)
+
+ def test_opening_mode(self):
+ try:
+ # invalid mode, should raise ValueError
+ fi = FileInput(mode="w")
+ self.fail("FileInput should reject invalid mode argument")
+ except ValueError:
+ pass
+ try:
+ # try opening in universal newline mode
+ t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb")
+ fi = FileInput(files=t1, mode="U")
+ lines = list(fi)
+ self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"])
+ finally:
+ remove_tempfiles(t1)
+
+ def test_file_opening_hook(self):
+ try:
+ # cannot use openhook and inplace mode
+ fi = FileInput(inplace=1, openhook=lambda f, m: None)
+ self.fail("FileInput should raise if both inplace "
+ "and openhook arguments are given")
+ except ValueError:
+ pass
+ try:
+ fi = FileInput(openhook=1)
+ self.fail("FileInput should check openhook for being callable")
+ except ValueError:
+ pass
+ try:
+ t1 = writeTmp(1, ["A\nB"], mode="wb")
+ fi = FileInput(files=t1, openhook=hook_encoded("rot13"))
+ lines = list(fi)
+ self.assertEqual(lines, ["N\n", "O"])
+ finally:
+ remove_tempfiles(t1)
+
+def test_main():
+ run_unittest(BufferSizesTests, FileInputTests)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
index 6a78154..4d969f5 100644
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -110,13 +110,13 @@ class OtherFileTests(unittest.TestCase):
self.assertEquals(f.writable(), True)
self.assertEquals(f.seekable(), True)
f.close()
-
+
f = _fileio._FileIO(TESTFN, "r")
self.assertEquals(f.readable(), True)
self.assertEquals(f.writable(), False)
self.assertEquals(f.seekable(), True)
f.close()
-
+
f = _fileio._FileIO(TESTFN, "a+")
self.assertEquals(f.readable(), True)
self.assertEquals(f.writable(), True)
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
new file mode 100644
index 0000000..9298bf4
--- /dev/null
+++ b/Lib/test/test_ftplib.py
@@ -0,0 +1,93 @@
+import socket
+import threading
+import ftplib
+import time
+
+from unittest import TestCase
+from test import test_support
+
+def server(evt):
+ serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ serv.settimeout(3)
+ serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ serv.bind(("", 9091))
+ serv.listen(5)
+ try:
+ conn, addr = serv.accept()
+ except socket.timeout:
+ pass
+ else:
+ conn.send("1 Hola mundo\n")
+ conn.close()
+ finally:
+ serv.close()
+ evt.set()
+
+class GeneralTests(TestCase):
+
+ def setUp(self):
+ ftplib.FTP.port = 9091
+ self.evt = threading.Event()
+ threading.Thread(target=server, args=(self.evt,)).start()
+ time.sleep(.1)
+
+ def tearDown(self):
+ self.evt.wait()
+
+ def testBasic(self):
+ # do nothing
+ ftplib.FTP()
+
+ # connects
+ ftp = ftplib.FTP("localhost")
+ ftp.sock.close()
+
+ def testTimeoutDefault(self):
+ # default
+ ftp = ftplib.FTP("localhost")
+ self.assertTrue(ftp.sock.gettimeout() is None)
+ ftp.sock.close()
+
+ def testTimeoutValue(self):
+ # a value
+ ftp = ftplib.FTP("localhost", timeout=30)
+ self.assertEqual(ftp.sock.gettimeout(), 30)
+ ftp.sock.close()
+
+ def testTimeoutConnect(self):
+ ftp = ftplib.FTP()
+ ftp.connect("localhost", timeout=30)
+ self.assertEqual(ftp.sock.gettimeout(), 30)
+ ftp.sock.close()
+
+ def testTimeoutDifferentOrder(self):
+ ftp = ftplib.FTP(timeout=30)
+ ftp.connect("localhost")
+ self.assertEqual(ftp.sock.gettimeout(), 30)
+ ftp.sock.close()
+
+ def testTimeoutDirectAccess(self):
+ ftp = ftplib.FTP()
+ ftp.timeout = 30
+ ftp.connect("localhost")
+ self.assertEqual(ftp.sock.gettimeout(), 30)
+ ftp.sock.close()
+
+ def testTimeoutNone(self):
+ # None, having other default
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ ftp = ftplib.FTP("localhost", timeout=None)
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(ftp.sock.gettimeout(), 30)
+ ftp.close()
+
+
+
+def test_main(verbose=None):
+ test_support.run_unittest(GeneralTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index 2d5e33c..a2df21c 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -285,7 +285,7 @@ class TestReduce(unittest.TestCase):
self.sofar.append(n*n)
n += 1
return self.sofar[i]
-
+
self.assertEqual(self.func(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
self.assertEqual(
self.func(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
@@ -321,7 +321,7 @@ class TestReduce(unittest.TestCase):
return i
else:
raise IndexError
-
+
from operator import add
self.assertEqual(self.func(add, SequenceClass(5)), 10)
self.assertEqual(self.func(add, SequenceClass(5), 42), 52)
@@ -333,7 +333,7 @@ class TestReduce(unittest.TestCase):
d = {"one": 1, "two": 2, "three": 3}
self.assertEqual(self.func(add, d), "".join(d.keys()))
-
+
def test_main(verbose=None):
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
index 8068b35..10b02da 100644
--- a/Lib/test/test_gc.py
+++ b/Lib/test/test_gc.py
@@ -1,390 +1,11 @@
-from test.test_support import verify, verbose, TestFailed, vereq
+import unittest
+from test.test_support import verbose, run_unittest
import sys
import gc
import weakref
-def expect(actual, expected, name):
- if actual != expected:
- raise TestFailed, "test_%s: actual %r, expected %r" % (
- name, actual, expected)
-
-def expect_nonzero(actual, name):
- if actual == 0:
- raise TestFailed, "test_%s: unexpected zero" % name
-
-def run_test(name, thunk):
- if verbose:
- print("testing %s..." % name, end=' ')
- thunk()
- if verbose:
- print("ok")
-
-def test_list():
- l = []
- l.append(l)
- gc.collect()
- del l
- expect(gc.collect(), 1, "list")
-
-def test_dict():
- d = {}
- d[1] = d
- gc.collect()
- del d
- expect(gc.collect(), 1, "dict")
-
-def test_tuple():
- # since tuples are immutable we close the loop with a list
- l = []
- t = (l,)
- l.append(t)
- gc.collect()
- del t
- del l
- expect(gc.collect(), 2, "tuple")
-
-def test_class():
- class A:
- pass
- A.a = A
- gc.collect()
- del A
- expect_nonzero(gc.collect(), "class")
-
-def test_newstyleclass():
- class A(object):
- pass
- gc.collect()
- del A
- expect_nonzero(gc.collect(), "staticclass")
-
-def test_instance():
- class A:
- pass
- a = A()
- a.a = a
- gc.collect()
- del a
- expect_nonzero(gc.collect(), "instance")
-
-def test_newinstance():
- class A(object):
- pass
- a = A()
- a.a = a
- gc.collect()
- del a
- expect_nonzero(gc.collect(), "newinstance")
- class B(list):
- pass
- class C(B, A):
- pass
- a = C()
- a.a = a
- gc.collect()
- del a
- expect_nonzero(gc.collect(), "newinstance(2)")
- del B, C
- expect_nonzero(gc.collect(), "newinstance(3)")
- A.a = A()
- del A
- expect_nonzero(gc.collect(), "newinstance(4)")
- expect(gc.collect(), 0, "newinstance(5)")
-
-def test_method():
- # Tricky: self.__init__ is a bound method, it references the instance.
- class A:
- def __init__(self):
- self.init = self.__init__
- a = A()
- gc.collect()
- del a
- expect_nonzero(gc.collect(), "method")
-
-def test_finalizer():
- # A() is uncollectable if it is part of a cycle, make sure it shows up
- # in gc.garbage.
- class A:
- def __del__(self): pass
- class B:
- pass
- a = A()
- a.a = a
- id_a = id(a)
- b = B()
- b.b = b
- gc.collect()
- del a
- del b
- expect_nonzero(gc.collect(), "finalizer")
- for obj in gc.garbage:
- if id(obj) == id_a:
- del obj.a
- break
- else:
- raise TestFailed, "didn't find obj in garbage (finalizer)"
- gc.garbage.remove(obj)
-
-def test_finalizer_newclass():
- # A() is uncollectable if it is part of a cycle, make sure it shows up
- # in gc.garbage.
- class A(object):
- def __del__(self): pass
- class B(object):
- pass
- a = A()
- a.a = a
- id_a = id(a)
- b = B()
- b.b = b
- gc.collect()
- del a
- del b
- expect_nonzero(gc.collect(), "finalizer")
- for obj in gc.garbage:
- if id(obj) == id_a:
- del obj.a
- break
- else:
- raise TestFailed, "didn't find obj in garbage (finalizer)"
- gc.garbage.remove(obj)
-
-def test_function():
- # Tricky: f -> d -> f, code should call d.clear() after the exec to
- # break the cycle.
- d = {}
- exec("def f(): pass\n", d)
- gc.collect()
- del d
- expect(gc.collect(), 2, "function")
-
-def test_frame():
- def f():
- frame = sys._getframe()
- gc.collect()
- f()
- expect(gc.collect(), 1, "frame")
-
-
-def test_saveall():
- # Verify that cyclic garbage like lists show up in gc.garbage if the
- # SAVEALL option is enabled.
-
- # First make sure we don't save away other stuff that just happens to
- # be waiting for collection.
- gc.collect()
- vereq(gc.garbage, []) # if this fails, someone else created immortal trash
-
- L = []
- L.append(L)
- id_L = id(L)
-
- debug = gc.get_debug()
- gc.set_debug(debug | gc.DEBUG_SAVEALL)
- del L
- gc.collect()
- gc.set_debug(debug)
-
- vereq(len(gc.garbage), 1)
- obj = gc.garbage.pop()
- vereq(id(obj), id_L)
-
-def test_del():
- # __del__ methods can trigger collection, make this to happen
- thresholds = gc.get_threshold()
- gc.enable()
- gc.set_threshold(1)
-
- class A:
- def __del__(self):
- dir(self)
- a = A()
- del a
-
- gc.disable()
- gc.set_threshold(*thresholds)
-
-def test_del_newclass():
- # __del__ methods can trigger collection, make this to happen
- thresholds = gc.get_threshold()
- gc.enable()
- gc.set_threshold(1)
-
- class A(object):
- def __del__(self):
- dir(self)
- a = A()
- del a
-
- gc.disable()
- gc.set_threshold(*thresholds)
-
-def test_get_count():
- gc.collect()
- expect(gc.get_count(), (0, 0, 0), "get_count()")
- a = dict()
- expect(gc.get_count(), (1, 0, 0), "get_count()")
-
-def test_collect_generations():
- gc.collect()
- a = dict()
- gc.collect(0)
- expect(gc.get_count(), (0, 1, 0), "collect(0)")
- gc.collect(1)
- expect(gc.get_count(), (0, 0, 1), "collect(1)")
- gc.collect(2)
- expect(gc.get_count(), (0, 0, 0), "collect(1)")
-
-class Ouch:
- n = 0
- def __del__(self):
- Ouch.n = Ouch.n + 1
- if Ouch.n % 17 == 0:
- gc.collect()
-
-def test_trashcan():
- # "trashcan" is a hack to prevent stack overflow when deallocating
- # very deeply nested tuples etc. It works in part by abusing the
- # type pointer and refcount fields, and that can yield horrible
- # problems when gc tries to traverse the structures.
- # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
- # most likely die via segfault.
-
- # Note: In 2.3 the possibility for compiling without cyclic gc was
- # removed, and that in turn allows the trashcan mechanism to work
- # via much simpler means (e.g., it never abuses the type pointer or
- # refcount fields anymore). Since it's much less likely to cause a
- # problem now, the various constants in this expensive (we force a lot
- # of full collections) test are cut back from the 2.2 version.
- gc.enable()
- N = 150
- for count in range(2):
- t = []
- for i in range(N):
- t = [t, Ouch()]
- u = []
- for i in range(N):
- u = [u, Ouch()]
- v = {}
- for i in range(N):
- v = {1: v, 2: Ouch()}
- gc.disable()
-
-class Boom:
- def __getattr__(self, someattribute):
- del self.attr
- raise AttributeError
-
-def test_boom():
- a = Boom()
- b = Boom()
- a.attr = b
- b.attr = a
-
- gc.collect()
- garbagelen = len(gc.garbage)
- del a, b
- # a<->b are in a trash cycle now. Collection will invoke Boom.__getattr__
- # (to see whether a and b have __del__ methods), and __getattr__ deletes
- # the internal "attr" attributes as a side effect. That causes the
- # trash cycle to get reclaimed via refcounts falling to 0, thus mutating
- # the trash graph as a side effect of merely asking whether __del__
- # exists. This used to (before 2.3b1) crash Python. Now __getattr__
- # isn't called.
- expect(gc.collect(), 4, "boom")
- expect(len(gc.garbage), garbagelen, "boom")
-
-class Boom2:
- def __init__(self):
- self.x = 0
-
- def __getattr__(self, someattribute):
- self.x += 1
- if self.x > 1:
- del self.attr
- raise AttributeError
-
-def test_boom2():
- a = Boom2()
- b = Boom2()
- a.attr = b
- b.attr = a
-
- gc.collect()
- garbagelen = len(gc.garbage)
- del a, b
- # Much like test_boom(), except that __getattr__ doesn't break the
- # cycle until the second time gc checks for __del__. As of 2.3b1,
- # there isn't a second time, so this simply cleans up the trash cycle.
- # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get reclaimed
- # this way.
- expect(gc.collect(), 4, "boom2")
- expect(len(gc.garbage), garbagelen, "boom2")
-
-# boom__new and boom2_new are exactly like boom and boom2, except use
-# new-style classes.
-
-class Boom_New(object):
- def __getattr__(self, someattribute):
- del self.attr
- raise AttributeError
-
-def test_boom_new():
- a = Boom_New()
- b = Boom_New()
- a.attr = b
- b.attr = a
-
- gc.collect()
- garbagelen = len(gc.garbage)
- del a, b
- expect(gc.collect(), 4, "boom_new")
- expect(len(gc.garbage), garbagelen, "boom_new")
-
-class Boom2_New(object):
- def __init__(self):
- self.x = 0
-
- def __getattr__(self, someattribute):
- self.x += 1
- if self.x > 1:
- del self.attr
- raise AttributeError
-
-def test_boom2_new():
- a = Boom2_New()
- b = Boom2_New()
- a.attr = b
- b.attr = a
-
- gc.collect()
- garbagelen = len(gc.garbage)
- del a, b
- expect(gc.collect(), 4, "boom2_new")
- expect(len(gc.garbage), garbagelen, "boom2_new")
-
-def test_get_referents():
- alist = [1, 3, 5]
- got = gc.get_referents(alist)
- got.sort()
- expect(got, alist, "get_referents")
-
- atuple = tuple(alist)
- got = gc.get_referents(atuple)
- got.sort()
- expect(got, alist, "get_referents")
-
- adict = {1: 3, 5: 7}
- expected = [1, 3, 5, 7]
- got = gc.get_referents(adict)
- got.sort()
- expect(got, expected, "get_referents")
-
- got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
- got.sort()
- expect(got, [0, 0] + range(5), "get_referents")
-
- expect(gc.get_referents(1, 'a', 4j), [], "get_referents")
+### Support code
+###############################################################################
# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
# cyclic gc.
@@ -410,217 +31,556 @@ class GC_Detector(object):
# gc collects it.
self.wr = weakref.ref(C1055820(666), it_happened)
-def test_bug1055820b():
- # Corresponds to temp2b.py in the bug report.
-
- ouch = []
- def callback(ignored):
- ouch[:] = [wr() for wr in WRs]
-
- Cs = [C1055820(i) for i in range(2)]
- WRs = [weakref.ref(c, callback) for c in Cs]
- c = None
-
- gc.collect()
- expect(len(ouch), 0, "bug1055820b")
- # Make the two instances trash, and collect again. The bug was that
- # the callback materialized a strong reference to an instance, but gc
- # cleared the instance's dict anyway.
- Cs = None
- gc.collect()
- expect(len(ouch), 2, "bug1055820b") # else the callbacks didn't run
- for x in ouch:
- # If the callback resurrected one of these guys, the instance
- # would be damaged, with an empty __dict__.
- expect(x, None, "bug1055820b")
-
-def test_bug1055820c():
- # Corresponds to temp2c.py in the bug report. This is pretty elaborate.
-
- c0 = C1055820(0)
- # Move c0 into generation 2.
- gc.collect()
-
- c1 = C1055820(1)
- c1.keep_c0_alive = c0
- del c0.loop # now only c1 keeps c0 alive
-
- c2 = C1055820(2)
- c2wr = weakref.ref(c2) # no callback!
-
- ouch = []
- def callback(ignored):
- ouch[:] = [c2wr()]
-
- # The callback gets associated with a wr on an object in generation 2.
- c0wr = weakref.ref(c0, callback)
-
- c0 = c1 = c2 = None
-
- # What we've set up: c0, c1, and c2 are all trash now. c0 is in
- # generation 2. The only thing keeping it alive is that c1 points to it.
- # c1 and c2 are in generation 0, and are in self-loops. There's a global
- # weakref to c2 (c2wr), but that weakref has no callback. There's also
- # a global weakref to c0 (c0wr), and that does have a callback, and that
- # callback references c2 via c2wr().
- #
- # c0 has a wr with callback, which references c2wr
- # ^
- # |
- # | Generation 2 above dots
- #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
- # | Generation 0 below dots
- # |
- # |
- # ^->c1 ^->c2 has a wr but no callback
- # | | | |
- # <--v <--v
- #
- # So this is the nightmare: when generation 0 gets collected, we see that
- # c2 has a callback-free weakref, and c1 doesn't even have a weakref.
- # Collecting generation 0 doesn't see c0 at all, and c0 is the only object
- # that has a weakref with a callback. gc clears c1 and c2. Clearing c1
- # has the side effect of dropping the refcount on c0 to 0, so c0 goes
- # away (despite that it's in an older generation) and c0's wr callback
- # triggers. That in turn materializes a reference to c2 via c2wr(), but
- # c2 gets cleared anyway by gc.
-
- # We want to let gc happen "naturally", to preserve the distinction
- # between generations.
- junk = []
- i = 0
- detector = GC_Detector()
- while not detector.gc_happened:
- i += 1
- if i > 10000:
- raise TestFailed("gc didn't happen after 10000 iterations")
- expect(len(ouch), 0, "bug1055820c")
- junk.append([]) # this will eventually trigger gc
-
- expect(len(ouch), 1, "bug1055820c") # else the callback wasn't invoked
- for x in ouch:
- # If the callback resurrected c2, the instance would be damaged,
- # with an empty __dict__.
- expect(x, None, "bug1055820c")
-
-def test_bug1055820d():
- # Corresponds to temp2d.py in the bug report. This is very much like
- # test_bug1055820c, but uses a __del__ method instead of a weakref
- # callback to sneak in a resurrection of cyclic trash.
-
- ouch = []
- class D(C1055820):
- def __del__(self):
- ouch[:] = [c2wr()]
- d0 = D(0)
- # Move all the above into generation 2.
- gc.collect()
-
- c1 = C1055820(1)
- c1.keep_d0_alive = d0
- del d0.loop # now only c1 keeps d0 alive
-
- c2 = C1055820(2)
- c2wr = weakref.ref(c2) # no callback!
-
- d0 = c1 = c2 = None
-
- # What we've set up: d0, c1, and c2 are all trash now. d0 is in
- # generation 2. The only thing keeping it alive is that c1 points to it.
- # c1 and c2 are in generation 0, and are in self-loops. There's a global
- # weakref to c2 (c2wr), but that weakref has no callback. There are no
- # other weakrefs.
- #
- # d0 has a __del__ method that references c2wr
- # ^
- # |
- # | Generation 2 above dots
- #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
- # | Generation 0 below dots
- # |
- # |
- # ^->c1 ^->c2 has a wr but no callback
- # | | | |
- # <--v <--v
- #
- # So this is the nightmare: when generation 0 gets collected, we see that
- # c2 has a callback-free weakref, and c1 doesn't even have a weakref.
- # Collecting generation 0 doesn't see d0 at all. gc clears c1 and c2.
- # Clearing c1 has the side effect of dropping the refcount on d0 to 0, so
- # d0 goes away (despite that it's in an older generation) and d0's __del__
- # triggers. That in turn materializes a reference to c2 via c2wr(), but
- # c2 gets cleared anyway by gc.
-
- # We want to let gc happen "naturally", to preserve the distinction
- # between generations.
- detector = GC_Detector()
- junk = []
- i = 0
- while not detector.gc_happened:
- i += 1
- if i > 10000:
- raise TestFailed("gc didn't happen after 10000 iterations")
- expect(len(ouch), 0, "bug1055820d")
- junk.append([]) # this will eventually trigger gc
-
- expect(len(ouch), 1, "bug1055820d") # else __del__ wasn't invoked
- for x in ouch:
- # If __del__ resurrected c2, the instance would be damaged, with an
- # empty __dict__.
- expect(x, None, "bug1055820d")
-
-
-def test_all():
- gc.collect() # Delete 2nd generation garbage
- run_test("lists", test_list)
- run_test("dicts", test_dict)
- run_test("tuples", test_tuple)
- run_test("classes", test_class)
- run_test("new style classes", test_newstyleclass)
- run_test("instances", test_instance)
- run_test("new instances", test_newinstance)
- run_test("methods", test_method)
- run_test("functions", test_function)
- run_test("frames", test_frame)
- run_test("finalizers", test_finalizer)
- run_test("finalizers (new class)", test_finalizer_newclass)
- run_test("__del__", test_del)
- run_test("__del__ (new class)", test_del_newclass)
- run_test("get_count()", test_get_count)
- run_test("collect(n)", test_collect_generations)
- run_test("saveall", test_saveall)
- run_test("trashcan", test_trashcan)
- run_test("boom", test_boom)
- run_test("boom2", test_boom2)
- run_test("boom_new", test_boom_new)
- run_test("boom2_new", test_boom2_new)
- run_test("get_referents", test_get_referents)
- run_test("bug1055820b", test_bug1055820b)
-
- gc.enable()
- try:
- run_test("bug1055820c", test_bug1055820c)
- finally:
+### Tests
+###############################################################################
+
+class GCTests(unittest.TestCase):
+ def test_list(self):
+ l = []
+ l.append(l)
+ gc.collect()
+ del l
+ self.assertEqual(gc.collect(), 1)
+
+ def test_dict(self):
+ d = {}
+ d[1] = d
+ gc.collect()
+ del d
+ self.assertEqual(gc.collect(), 1)
+
+ def test_tuple(self):
+ # since tuples are immutable we close the loop with a list
+ l = []
+ t = (l,)
+ l.append(t)
+ gc.collect()
+ del t
+ del l
+ self.assertEqual(gc.collect(), 2)
+
+ def test_class(self):
+ class A:
+ pass
+ A.a = A
+ gc.collect()
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_newstyleclass(self):
+ class A(object):
+ pass
+ gc.collect()
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_instance(self):
+ class A:
+ pass
+ a = A()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_newinstance(self):
+ class A(object):
+ pass
+ a = A()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+ class B(list):
+ pass
+ class C(B, A):
+ pass
+ a = C()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+ del B, C
+ self.assertNotEqual(gc.collect(), 0)
+ A.a = A()
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+ self.assertEqual(gc.collect(), 0)
+
+ def test_method(self):
+ # Tricky: self.__init__ is a bound method, it references the instance.
+ class A:
+ def __init__(self):
+ self.init = self.__init__
+ a = A()
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_finalizer(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A:
+ def __del__(self): pass
+ class B:
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+ def test_finalizer_newclass(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A(object):
+ def __del__(self): pass
+ class B(object):
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+ def test_function(self):
+ # Tricky: f -> d -> f, code should call d.clear() after the exec to
+ # break the cycle.
+ d = {}
+ exec("def f(): pass\n", d)
+ gc.collect()
+ del d
+ self.assertEqual(gc.collect(), 2)
+
+ def test_frame(self):
+ def f():
+ frame = sys._getframe()
+ gc.collect()
+ f()
+ self.assertEqual(gc.collect(), 1)
+
+ def test_saveall(self):
+ # Verify that cyclic garbage like lists show up in gc.garbage if the
+ # SAVEALL option is enabled.
+
+ # First make sure we don't save away other stuff that just happens to
+ # be waiting for collection.
+ gc.collect()
+ # if this fails, someone else created immortal trash
+ self.assertEqual(gc.garbage, [])
+
+ L = []
+ L.append(L)
+ id_L = id(L)
+
+ debug = gc.get_debug()
+ gc.set_debug(debug | gc.DEBUG_SAVEALL)
+ del L
+ gc.collect()
+ gc.set_debug(debug)
+
+ self.assertEqual(len(gc.garbage), 1)
+ obj = gc.garbage.pop()
+ self.assertEqual(id(obj), id_L)
+
+ def test_del(self):
+ # __del__ methods can trigger collection, make this to happen
+ thresholds = gc.get_threshold()
+ gc.enable()
+ gc.set_threshold(1)
+
+ class A:
+ def __del__(self):
+ dir(self)
+ a = A()
+ del a
+
gc.disable()
+ gc.set_threshold(*thresholds)
- gc.enable()
- try:
- run_test("bug1055820d", test_bug1055820d)
- finally:
+ def test_del_newclass(self):
+ # __del__ methods can trigger collection, make this to happen
+ thresholds = gc.get_threshold()
+ gc.enable()
+ gc.set_threshold(1)
+
+ class A(object):
+ def __del__(self):
+ dir(self)
+ a = A()
+ del a
+
+ gc.disable()
+ gc.set_threshold(*thresholds)
+
+ def test_get_count(self):
+ gc.collect()
+ self.assertEqual(gc.get_count(), (0, 0, 0))
+ a = dict()
+ self.assertEqual(gc.get_count(), (1, 0, 0))
+
+ def test_collect_generations(self):
+ gc.collect()
+ a = dict()
+ gc.collect(0)
+ self.assertEqual(gc.get_count(), (0, 1, 0))
+ gc.collect(1)
+ self.assertEqual(gc.get_count(), (0, 0, 1))
+ gc.collect(2)
+ self.assertEqual(gc.get_count(), (0, 0, 0))
+
+ def test_trashcan(self):
+ class Ouch:
+ n = 0
+ def __del__(self):
+ Ouch.n = Ouch.n + 1
+ if Ouch.n % 17 == 0:
+ gc.collect()
+
+ # "trashcan" is a hack to prevent stack overflow when deallocating
+ # very deeply nested tuples etc. It works in part by abusing the
+ # type pointer and refcount fields, and that can yield horrible
+ # problems when gc tries to traverse the structures.
+ # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
+ # most likely die via segfault.
+
+ # Note: In 2.3 the possibility for compiling without cyclic gc was
+ # removed, and that in turn allows the trashcan mechanism to work
+ # via much simpler means (e.g., it never abuses the type pointer or
+ # refcount fields anymore). Since it's much less likely to cause a
+ # problem now, the various constants in this expensive (we force a lot
+ # of full collections) test are cut back from the 2.2 version.
+ gc.enable()
+ N = 150
+ for count in range(2):
+ t = []
+ for i in range(N):
+ t = [t, Ouch()]
+ u = []
+ for i in range(N):
+ u = [u, Ouch()]
+ v = {}
+ for i in range(N):
+ v = {1: v, 2: Ouch()}
gc.disable()
-def test():
- if verbose:
- print("disabling automatic collection")
+ def test_boom(self):
+ class Boom:
+ def __getattr__(self, someattribute):
+ del self.attr
+ raise AttributeError
+
+ a = Boom()
+ b = Boom()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ # a<->b are in a trash cycle now. Collection will invoke
+ # Boom.__getattr__ (to see whether a and b have __del__ methods), and
+ # __getattr__ deletes the internal "attr" attributes as a side effect.
+ # That causes the trash cycle to get reclaimed via refcounts falling to
+ # 0, thus mutating the trash graph as a side effect of merely asking
+ # whether __del__ exists. This used to (before 2.3b1) crash Python.
+ # Now __getattr__ isn't called.
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom2(self):
+ class Boom2:
+ def __init__(self):
+ self.x = 0
+
+ def __getattr__(self, someattribute):
+ self.x += 1
+ if self.x > 1:
+ del self.attr
+ raise AttributeError
+
+ a = Boom2()
+ b = Boom2()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ # Much like test_boom(), except that __getattr__ doesn't break the
+ # cycle until the second time gc checks for __del__. As of 2.3b1,
+ # there isn't a second time, so this simply cleans up the trash cycle.
+ # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
+ # reclaimed this way.
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom_new(self):
+ # boom__new and boom2_new are exactly like boom and boom2, except use
+ # new-style classes.
+
+ class Boom_New(object):
+ def __getattr__(self, someattribute):
+ del self.attr
+ raise AttributeError
+
+ a = Boom_New()
+ b = Boom_New()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom2_new(self):
+ class Boom2_New(object):
+ def __init__(self):
+ self.x = 0
+
+ def __getattr__(self, someattribute):
+ self.x += 1
+ if self.x > 1:
+ del self.attr
+ raise AttributeError
+
+ a = Boom2_New()
+ b = Boom2_New()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_get_referents(self):
+ alist = [1, 3, 5]
+ got = gc.get_referents(alist)
+ got.sort()
+ self.assertEqual(got, alist)
+
+ atuple = tuple(alist)
+ got = gc.get_referents(atuple)
+ got.sort()
+ self.assertEqual(got, alist)
+
+ adict = {1: 3, 5: 7}
+ expected = [1, 3, 5, 7]
+ got = gc.get_referents(adict)
+ got.sort()
+ self.assertEqual(got, expected)
+
+ got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
+ got.sort()
+ self.assertEqual(got, [0, 0] + range(5))
+
+ self.assertEqual(gc.get_referents(1, 'a', 4j), [])
+
+ def test_bug1055820b(self):
+ # Corresponds to temp2b.py in the bug report.
+
+ ouch = []
+ def callback(ignored):
+ ouch[:] = [wr() for wr in WRs]
+
+ Cs = [C1055820(i) for i in range(2)]
+ WRs = [weakref.ref(c, callback) for c in Cs]
+ c = None
+
+ gc.collect()
+ self.assertEqual(len(ouch), 0)
+ # Make the two instances trash, and collect again. The bug was that
+ # the callback materialized a strong reference to an instance, but gc
+ # cleared the instance's dict anyway.
+ Cs = None
+ gc.collect()
+ self.assertEqual(len(ouch), 2) # else the callbacks didn't run
+ for x in ouch:
+ # If the callback resurrected one of these guys, the instance
+ # would be damaged, with an empty __dict__.
+ self.assertEqual(x, None)
+
+class GCTogglingTests(unittest.TestCase):
+ def setUp(self):
+ gc.enable()
+
+ def tearDown(self):
+ gc.disable()
+
+ def test_bug1055820c(self):
+ # Corresponds to temp2c.py in the bug report. This is pretty
+ # elaborate.
+
+ c0 = C1055820(0)
+ # Move c0 into generation 2.
+ gc.collect()
+
+ c1 = C1055820(1)
+ c1.keep_c0_alive = c0
+ del c0.loop # now only c1 keeps c0 alive
+
+ c2 = C1055820(2)
+ c2wr = weakref.ref(c2) # no callback!
+
+ ouch = []
+ def callback(ignored):
+ ouch[:] = [c2wr()]
+
+ # The callback gets associated with a wr on an object in generation 2.
+ c0wr = weakref.ref(c0, callback)
+
+ c0 = c1 = c2 = None
+
+ # What we've set up: c0, c1, and c2 are all trash now. c0 is in
+ # generation 2. The only thing keeping it alive is that c1 points to
+ # it. c1 and c2 are in generation 0, and are in self-loops. There's a
+ # global weakref to c2 (c2wr), but that weakref has no callback.
+ # There's also a global weakref to c0 (c0wr), and that does have a
+ # callback, and that callback references c2 via c2wr().
+ #
+ # c0 has a wr with callback, which references c2wr
+ # ^
+ # |
+ # | Generation 2 above dots
+ #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
+ # | Generation 0 below dots
+ # |
+ # |
+ # ^->c1 ^->c2 has a wr but no callback
+ # | | | |
+ # <--v <--v
+ #
+ # So this is the nightmare: when generation 0 gets collected, we see
+ # that c2 has a callback-free weakref, and c1 doesn't even have a
+ # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
+ # the only object that has a weakref with a callback. gc clears c1
+ # and c2. Clearing c1 has the side effect of dropping the refcount on
+ # c0 to 0, so c0 goes away (despite that it's in an older generation)
+ # and c0's wr callback triggers. That in turn materializes a reference
+ # to c2 via c2wr(), but c2 gets cleared anyway by gc.
+
+ # We want to let gc happen "naturally", to preserve the distinction
+ # between generations.
+ junk = []
+ i = 0
+ detector = GC_Detector()
+ while not detector.gc_happened:
+ i += 1
+ if i > 10000:
+ self.fail("gc didn't happen after 10000 iterations")
+ self.assertEqual(len(ouch), 0)
+ junk.append([]) # this will eventually trigger gc
+
+ self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
+ for x in ouch:
+ # If the callback resurrected c2, the instance would be damaged,
+ # with an empty __dict__.
+ self.assertEqual(x, None)
+
+ def test_bug1055820d(self):
+ # Corresponds to temp2d.py in the bug report. This is very much like
+ # test_bug1055820c, but uses a __del__ method instead of a weakref
+ # callback to sneak in a resurrection of cyclic trash.
+
+ ouch = []
+ class D(C1055820):
+ def __del__(self):
+ ouch[:] = [c2wr()]
+
+ d0 = D(0)
+ # Move all the above into generation 2.
+ gc.collect()
+
+ c1 = C1055820(1)
+ c1.keep_d0_alive = d0
+ del d0.loop # now only c1 keeps d0 alive
+
+ c2 = C1055820(2)
+ c2wr = weakref.ref(c2) # no callback!
+
+ d0 = c1 = c2 = None
+
+ # What we've set up: d0, c1, and c2 are all trash now. d0 is in
+ # generation 2. The only thing keeping it alive is that c1 points to
+ # it. c1 and c2 are in generation 0, and are in self-loops. There's
+ # a global weakref to c2 (c2wr), but that weakref has no callback.
+ # There are no other weakrefs.
+ #
+ # d0 has a __del__ method that references c2wr
+ # ^
+ # |
+ # | Generation 2 above dots
+ #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
+ # | Generation 0 below dots
+ # |
+ # |
+ # ^->c1 ^->c2 has a wr but no callback
+ # | | | |
+ # <--v <--v
+ #
+ # So this is the nightmare: when generation 0 gets collected, we see
+ # that c2 has a callback-free weakref, and c1 doesn't even have a
+ # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
+ # c1 and c2. Clearing c1 has the side effect of dropping the refcount
+ # on d0 to 0, so d0 goes away (despite that it's in an older
+ # generation) and d0's __del__ triggers. That in turn materializes
+ # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
+
+ # We want to let gc happen "naturally", to preserve the distinction
+ # between generations.
+ detector = GC_Detector()
+ junk = []
+ i = 0
+ while not detector.gc_happened:
+ i += 1
+ if i > 10000:
+ self.fail("gc didn't happen after 10000 iterations")
+ self.assertEqual(len(ouch), 0)
+ junk.append([]) # this will eventually trigger gc
+
+ self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
+ for x in ouch:
+ # If __del__ resurrected c2, the instance would be damaged, with an
+ # empty __dict__.
+ self.assertEqual(x, None)
+
+def test_main():
enabled = gc.isenabled()
gc.disable()
- verify(not gc.isenabled())
+ assert not gc.isenabled()
debug = gc.get_debug()
gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
try:
- test_all()
+ gc.collect() # Delete 2nd generation garbage
+ run_unittest(GCTests, GCTogglingTests)
finally:
gc.set_debug(debug)
# test gc.enable() even if GC is disabled by default
@@ -628,9 +588,9 @@ def test():
print("restoring automatic collection")
# make sure to always test gc.enable()
gc.enable()
- verify(gc.isenabled())
+ assert gc.isenabled()
if not enabled:
gc.disable()
-
-test()
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_getopt.py b/Lib/test/test_getopt.py
index 10bd256..a3a9940 100644
--- a/Lib/test/test_getopt.py
+++ b/Lib/test/test_getopt.py
@@ -1,180 +1,179 @@
# test_getopt.py
# David Goodger <dgoodger@bigfoot.com> 2000-08-19
+from test.test_support import verbose, run_doctest, run_unittest
+import unittest
+
import getopt
-from getopt import GetoptError
-from test.test_support import verify, verbose, run_doctest
import os
-def expectException(teststr, expected, failure=AssertionError):
- """Executes a statement passed in teststr, and raises an exception
- (failure) if the expected exception is *not* raised."""
- try:
- exec(teststr)
- except expected:
- pass
- else:
- raise failure
-
-old_posixly_correct = os.environ.get("POSIXLY_CORRECT")
-if old_posixly_correct is not None:
- del os.environ["POSIXLY_CORRECT"]
-
-if verbose:
- print('Running tests on getopt.short_has_arg')
-verify(getopt.short_has_arg('a', 'a:'))
-verify(not getopt.short_has_arg('a', 'a'))
-expectException("tmp = getopt.short_has_arg('a', 'b')", GetoptError)
-expectException("tmp = getopt.short_has_arg('a', '')", GetoptError)
-
-if verbose:
- print('Running tests on getopt.long_has_args')
-has_arg, option = getopt.long_has_args('abc', ['abc='])
-verify(has_arg)
-verify(option == 'abc')
-has_arg, option = getopt.long_has_args('abc', ['abc'])
-verify(not has_arg)
-verify(option == 'abc')
-has_arg, option = getopt.long_has_args('abc', ['abcd'])
-verify(not has_arg)
-verify(option == 'abcd')
-expectException("has_arg, option = getopt.long_has_args('abc', ['def'])",
- GetoptError)
-expectException("has_arg, option = getopt.long_has_args('abc', [])",
- GetoptError)
-expectException("has_arg, option = " + \
- "getopt.long_has_args('abc', ['abcd','abcde'])",
- GetoptError)
-
-if verbose:
- print('Running tests on getopt.do_shorts')
-opts, args = getopt.do_shorts([], 'a', 'a', [])
-verify(opts == [('-a', '')])
-verify(args == [])
-opts, args = getopt.do_shorts([], 'a1', 'a:', [])
-verify(opts == [('-a', '1')])
-verify(args == [])
-#opts, args = getopt.do_shorts([], 'a=1', 'a:', [])
-#verify(opts == [('-a', '1')])
-#verify(args == [])
-opts, args = getopt.do_shorts([], 'a', 'a:', ['1'])
-verify(opts == [('-a', '1')])
-verify(args == [])
-opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2'])
-verify(opts == [('-a', '1')])
-verify(args == ['2'])
-expectException("opts, args = getopt.do_shorts([], 'a1', 'a', [])",
- GetoptError)
-expectException("opts, args = getopt.do_shorts([], 'a', 'a:', [])",
- GetoptError)
-
-if verbose:
- print('Running tests on getopt.do_longs')
-opts, args = getopt.do_longs([], 'abc', ['abc'], [])
-verify(opts == [('--abc', '')])
-verify(args == [])
-opts, args = getopt.do_longs([], 'abc=1', ['abc='], [])
-verify(opts == [('--abc', '1')])
-verify(args == [])
-opts, args = getopt.do_longs([], 'abc=1', ['abcd='], [])
-verify(opts == [('--abcd', '1')])
-verify(args == [])
-opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], [])
-verify(opts == [('--abc', '')])
-verify(args == [])
-# Much like the preceding, except with a non-alpha character ("-") in
-# option name that precedes "="; failed in
-# http://sourceforge.net/bugs/?func=detailbug&bug_id=126863&group_id=5470
-opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], [])
-verify(opts == [('--foo', '42')])
-verify(args == [])
-expectException("opts, args = getopt.do_longs([], 'abc=1', ['abc'], [])",
- GetoptError)
-expectException("opts, args = getopt.do_longs([], 'abc', ['abc='], [])",
- GetoptError)
-
-# note: the empty string between '-a' and '--beta' is significant:
-# it simulates an empty string option argument ('-a ""') on the command line.
-cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', '',
- '--beta', 'arg1', 'arg2']
-
-if verbose:
- print('Running tests on getopt.getopt')
-opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta'])
-verify(opts == [('-a', '1'), ('-b', ''), ('--alpha', '2'), ('--beta', ''),
- ('-a', '3'), ('-a', ''), ('--beta', '')] )
-# Note ambiguity of ('-b', '') and ('-a', '') above. This must be
-# accounted for in the code that calls getopt().
-verify(args == ['arg1', 'arg2'])
-
-expectException(
- "opts, args = getopt.getopt(cmdline, 'a:b', ['alpha', 'beta'])",
- GetoptError)
-
-# Test handling of GNU style scanning mode.
-if verbose:
- print('Running tests on getopt.gnu_getopt')
-cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2']
-# GNU style
-opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta='])
-verify(opts == [('-a', ''), ('-b', '1'), ('--alpha', ''), ('--beta', '2')])
-verify(args == ['arg1'])
-# Posix style via +
-opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta='])
-verify(opts == [('-a', '')])
-verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2'])
-# Posix style via POSIXLY_CORRECT
-os.environ["POSIXLY_CORRECT"] = "1"
-opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta='])
-verify(opts == [('-a', '')])
-verify(args == ['arg1', '-b', '1', '--alpha', '--beta=2'])
-
-
-if old_posixly_correct is None:
- del os.environ["POSIXLY_CORRECT"]
-else:
- os.environ["POSIXLY_CORRECT"] = old_posixly_correct
-
-#------------------------------------------------------------------------------
-
-libreftest = """
-Examples from the Library Reference: Doc/lib/libgetopt.tex
-
-An example using only Unix style options:
-
-
->>> import getopt
->>> args = '-a -b -cfoo -d bar a1 a2'.split()
->>> args
-['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2']
->>> optlist, args = getopt.getopt(args, 'abc:d:')
->>> optlist
-[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')]
->>> args
-['a1', 'a2']
-
-Using long option names is equally easy:
-
-
->>> s = '--condition=foo --testing --output-file abc.def -x a1 a2'
->>> args = s.split()
->>> args
-['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2']
->>> optlist, args = getopt.getopt(args, 'x', [
-... 'condition=', 'output-file=', 'testing'])
->>> optlist
-[('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')]
->>> args
-['a1', 'a2']
-
-"""
-
-__test__ = {'libreftest' : libreftest}
-
-import sys
-run_doctest(sys.modules[__name__], verbose)
-
-#------------------------------------------------------------------------------
-
-if verbose:
- print("Module getopt: tests completed successfully.")
+sentinel = object()
+
+class GetoptTests(unittest.TestCase):
+ def setUp(self):
+ self.old_posixly_correct = os.environ.get("POSIXLY_CORRECT", sentinel)
+ if self.old_posixly_correct is not sentinel:
+ del os.environ["POSIXLY_CORRECT"]
+
+ def tearDown(self):
+ if self.old_posixly_correct is sentinel:
+ os.environ.pop("POSIXLY_CORRECT", None)
+ else:
+ os.environ["POSIXLY_CORRECT"] = self.old_posixly_correct
+
+ def assertError(self, *args, **kwargs):
+ self.assertRaises(getopt.GetoptError, *args, **kwargs)
+
+ def test_short_has_arg(self):
+ self.failUnless(getopt.short_has_arg('a', 'a:'))
+ self.failIf(getopt.short_has_arg('a', 'a'))
+ self.assertError(getopt.short_has_arg, 'a', 'b')
+
+ def test_long_has_args(self):
+ has_arg, option = getopt.long_has_args('abc', ['abc='])
+ self.failUnless(has_arg)
+ self.assertEqual(option, 'abc')
+
+ has_arg, option = getopt.long_has_args('abc', ['abc'])
+ self.failIf(has_arg)
+ self.assertEqual(option, 'abc')
+
+ has_arg, option = getopt.long_has_args('abc', ['abcd'])
+ self.failIf(has_arg)
+ self.assertEqual(option, 'abcd')
+
+ self.assertError(getopt.long_has_args, 'abc', ['def'])
+ self.assertError(getopt.long_has_args, 'abc', [])
+ self.assertError(getopt.long_has_args, 'abc', ['abcd','abcde'])
+
+ def test_do_shorts(self):
+ opts, args = getopt.do_shorts([], 'a', 'a', [])
+ self.assertEqual(opts, [('-a', '')])
+ self.assertEqual(args, [])
+
+ opts, args = getopt.do_shorts([], 'a1', 'a:', [])
+ self.assertEqual(opts, [('-a', '1')])
+ self.assertEqual(args, [])
+
+ #opts, args = getopt.do_shorts([], 'a=1', 'a:', [])
+ #self.assertEqual(opts, [('-a', '1')])
+ #self.assertEqual(args, [])
+
+ opts, args = getopt.do_shorts([], 'a', 'a:', ['1'])
+ self.assertEqual(opts, [('-a', '1')])
+ self.assertEqual(args, [])
+
+ opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2'])
+ self.assertEqual(opts, [('-a', '1')])
+ self.assertEqual(args, ['2'])
+
+ self.assertError(getopt.do_shorts, [], 'a1', 'a', [])
+ self.assertError(getopt.do_shorts, [], 'a', 'a:', [])
+
+ def test_do_longs(self):
+ opts, args = getopt.do_longs([], 'abc', ['abc'], [])
+ self.assertEqual(opts, [('--abc', '')])
+ self.assertEqual(args, [])
+
+ opts, args = getopt.do_longs([], 'abc=1', ['abc='], [])
+ self.assertEqual(opts, [('--abc', '1')])
+ self.assertEqual(args, [])
+
+ opts, args = getopt.do_longs([], 'abc=1', ['abcd='], [])
+ self.assertEqual(opts, [('--abcd', '1')])
+ self.assertEqual(args, [])
+
+ opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], [])
+ self.assertEqual(opts, [('--abc', '')])
+ self.assertEqual(args, [])
+
+ # Much like the preceding, except with a non-alpha character ("-") in
+ # option name that precedes "="; failed in
+ # http://python.org/sf/126863
+ opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], [])
+ self.assertEqual(opts, [('--foo', '42')])
+ self.assertEqual(args, [])
+
+ self.assertError(getopt.do_longs, [], 'abc=1', ['abc'], [])
+ self.assertError(getopt.do_longs, [], 'abc', ['abc='], [])
+
+ def test_getopt(self):
+ # note: the empty string between '-a' and '--beta' is significant:
+ # it simulates an empty string option argument ('-a ""') on the
+ # command line.
+ cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a',
+ '', '--beta', 'arg1', 'arg2']
+
+ opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta'])
+ self.assertEqual(opts, [('-a', '1'), ('-b', ''),
+ ('--alpha', '2'), ('--beta', ''),
+ ('-a', '3'), ('-a', ''), ('--beta', '')])
+ # Note ambiguity of ('-b', '') and ('-a', '') above. This must be
+ # accounted for in the code that calls getopt().
+ self.assertEqual(args, ['arg1', 'arg2'])
+
+ self.assertError(getopt.getopt, cmdline, 'a:b', ['alpha', 'beta'])
+
+ def test_gnu_getopt(self):
+ # Test handling of GNU style scanning mode.
+ cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2']
+
+ # GNU style
+ opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta='])
+ self.assertEqual(args, ['arg1'])
+ self.assertEqual(opts, [('-a', ''), ('-b', '1'),
+ ('--alpha', ''), ('--beta', '2')])
+
+ # Posix style via +
+ opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta='])
+ self.assertEqual(opts, [('-a', '')])
+ self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2'])
+
+ # Posix style via POSIXLY_CORRECT
+ os.environ["POSIXLY_CORRECT"] = "1"
+ opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta='])
+ self.assertEqual(opts, [('-a', '')])
+ self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2'])
+
+ def test_libref_examples(self):
+ s = """
+ Examples from the Library Reference: Doc/lib/libgetopt.tex
+
+ An example using only Unix style options:
+
+
+ >>> import getopt
+ >>> args = '-a -b -cfoo -d bar a1 a2'.split()
+ >>> args
+ ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2']
+ >>> optlist, args = getopt.getopt(args, 'abc:d:')
+ >>> optlist
+ [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')]
+ >>> args
+ ['a1', 'a2']
+
+ Using long option names is equally easy:
+
+
+ >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2'
+ >>> args = s.split()
+ >>> args
+ ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2']
+ >>> optlist, args = getopt.getopt(args, 'x', [
+ ... 'condition=', 'output-file=', 'testing'])
+ >>> optlist
+ [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')]
+ >>> args
+ ['a1', 'a2']
+ """
+
+ import new
+ m = new.module("libreftest", s)
+ run_doctest(m, verbose)
+
+
+def test_main():
+ run_unittest(GetoptTests)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py
index 76253de..ab6bc9a 100644
--- a/Lib/test/test_gettext.py
+++ b/Lib/test/test_gettext.py
@@ -4,7 +4,7 @@ import shutil
import gettext
import unittest
-from test.test_support import run_suite
+from test import test_support
# TODO:
@@ -336,19 +336,8 @@ class WeirdMetadataTest(GettextBaseTest):
'John Doe <jdoe@example.com>\nJane Foobar <jfoobar@example.com>')
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(GettextTestCase1))
- suite.addTest(unittest.makeSuite(GettextTestCase2))
- suite.addTest(unittest.makeSuite(PluralFormsTestCase))
- suite.addTest(unittest.makeSuite(UnicodeTranslationsTest))
- suite.addTest(unittest.makeSuite(WeirdMetadataTest))
- return suite
-
-
def test_main():
- run_suite(suite())
-
+ test_support.run_unittest(__name__)
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py
index 5ce09f9..f1993ab 100644
--- a/Lib/test/test_glob.py
+++ b/Lib/test/test_glob.py
@@ -52,6 +52,16 @@ class GlobTests(unittest.TestCase):
eq(self.glob('aab'), [self.norm('aab')])
eq(self.glob('zymurgy'), [])
+ # test return types are unicode, but only if os.listdir
+ # returns unicode filenames
+ uniset = set([unicode])
+ tmp = os.listdir(u'.')
+ if set(type(x) for x in tmp) == uniset:
+ u1 = glob.glob(u'*')
+ u2 = glob.glob(u'./*')
+ self.assertEquals(set(type(r) for r in u1), uniset)
+ self.assertEquals(set(type(r) for r in u2), uniset)
+
def test_glob_one_directory(self):
eq = self.assertSequencesEqual_noorder
eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa']))
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index 85be05b..96cf824 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -364,7 +364,7 @@ class GrammarTests(unittest.TestCase):
x = 1; pass; del x;
foo()
- ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
+ ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
# Tested below
def testExprStmt(self):
diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py
index 54b90cd..229bbed 100755
--- a/Lib/test/test_htmlparser.py
+++ b/Lib/test/test_htmlparser.py
@@ -309,6 +309,11 @@ DOCTYPE html [
("endtag", "script"),
])
+ def test_entityrefs_in_attributes(self):
+ self._run_check("<html foo='&euro;&amp;&#97;&#x61;&unsupported;'>", [
+ ("starttag", "html", [("foo", u"\u20AC&aa&unsupported;")])
+ ])
+
def test_main():
test_support.run_unittest(HTMLParserTestCase)
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 90a4e55..035f0b9 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -1,6 +1,7 @@
import httplib
import StringIO
import sys
+import socket
from unittest import TestCase
@@ -149,8 +150,52 @@ class OfflineTest(TestCase):
def test_responses(self):
self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
+PORT = 50003
+HOST = "localhost"
+
+class TimeoutTest(TestCase):
+
+ def setUp(self):
+ self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ global PORT
+ PORT = test_support.bind_port(self.serv, HOST, PORT)
+ self.serv.listen(5)
+
+ def tearDown(self):
+ self.serv.close()
+ self.serv = None
+
+ def testTimeoutAttribute(self):
+ '''This will prove that the timeout gets through
+ HTTPConnection and into the socket.
+ '''
+ # default
+ httpConn = httplib.HTTPConnection(HOST, PORT)
+ httpConn.connect()
+ self.assertTrue(httpConn.sock.gettimeout() is None)
+ httpConn.close()
+
+ # a value
+ httpConn = httplib.HTTPConnection(HOST, PORT, timeout=30)
+ httpConn.connect()
+ self.assertEqual(httpConn.sock.gettimeout(), 30)
+ httpConn.close()
+
+ # None, having other default
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ httpConn = httplib.HTTPConnection(HOST, PORT, timeout=None)
+ httpConn.connect()
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(httpConn.sock.gettimeout(), 30)
+ httpConn.close()
+
+
def test_main(verbose=None):
- test_support.run_unittest(HeaderTests, OfflineTest, BasicTest)
+ test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest)
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index a8f912f..87907c8 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -193,6 +193,16 @@ class ImportTest(unittest.TestCase):
if TESTFN in sys.modules:
del sys.modules[TESTFN]
+ def test_infinite_reload(self):
+ # Bug #742342 reports that Python segfaults (infinite recursion in C)
+ # when faced with self-recursive reload()ing.
+
+ sys.path.insert(0, os.path.dirname(__file__))
+ try:
+ import infinite_reload
+ finally:
+ sys.path.pop(0)
+
def test_import_name_binding(self):
# import x.y.z binds x in the current namespace
import test as x
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index d74b9d5..98c79c7 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -215,20 +215,20 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(list(izip_longest(*args, **{})), target)
target = [tuple((e is None and 'X' or e) for e in t) for t in target] # Replace None fills with 'X'
self.assertEqual(list(izip_longest(*args, **dict(fillvalue='X'))), target)
-
+
self.assertEqual(take(3,izip_longest('abcdef', count())), list(zip('abcdef', range(3)))) # take 3 from infinite input
self.assertEqual(list(izip_longest()), list(zip()))
self.assertEqual(list(izip_longest([])), list(zip([])))
self.assertEqual(list(izip_longest('abcdef')), list(zip('abcdef')))
-
+
self.assertEqual(list(izip_longest('abc', 'defg', **{})), map(None, 'abc', 'defg')) # empty keyword dict
self.assertRaises(TypeError, izip_longest, 3)
self.assertRaises(TypeError, izip_longest, range(3), 3)
for stmt in [
"izip_longest('abc', fv=1)",
- "izip_longest('abc', fillvalue=1, bogus_keyword=None)",
+ "izip_longest('abc', fillvalue=1, bogus_keyword=None)",
]:
try:
eval(stmt, globals(), locals())
@@ -236,7 +236,7 @@ class TestBasicOps(unittest.TestCase):
pass
else:
self.fail('Did not raise Type in: ' + stmt)
-
+
# Check tuple re-use (implementation detail)
self.assertEqual([tuple(list(pair)) for pair in izip_longest('abc', 'def')],
list(zip('abc', 'def')))
@@ -818,7 +818,7 @@ libreftest = """ Doctest for examples in the library reference: libitertools.tex
>>> amounts = [120.15, 764.05, 823.14]
>>> for checknum, amount in izip(count(1200), amounts):
... print('Check %d is for $%.2f' % (checknum, amount))
-...
+...
Check 1200 is for $120.15
Check 1201 is for $764.05
Check 1202 is for $823.14
@@ -826,7 +826,7 @@ Check 1202 is for $823.14
>>> import operator
>>> for cube in imap(operator.pow, xrange(1,4), repeat(3)):
... print(cube)
-...
+...
1
8
27
@@ -834,7 +834,7 @@ Check 1202 is for $823.14
>>> reportlines = ['EuroPython', 'Roster', '', 'alex', '', 'laura', '', 'martin', '', 'walter', '', 'samuele']
>>> for name in islice(reportlines, 3, None, 2):
... print(name.title())
-...
+...
Alex
Laura
Martin
@@ -846,7 +846,7 @@ Samuele
>>> di = sorted(sorted(d.items()), key=itemgetter(1))
>>> for k, g in groupby(di, itemgetter(1)):
... print(k, map(itemgetter(0), g))
-...
+...
1 ['a', 'c', 'e']
2 ['b', 'd', 'f']
3 ['g']
@@ -857,7 +857,7 @@ Samuele
>>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
>>> for k, g in groupby(enumerate(data), lambda (i,x):i-x):
... print(map(operator.itemgetter(1), g))
-...
+...
[1]
[4, 5, 6]
[10]
diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py
index 2e1f8bd..fc67c98 100644
--- a/Lib/test/test_keywordonlyarg.py
+++ b/Lib/test/test_keywordonlyarg.py
@@ -71,7 +71,7 @@ class KeywordOnlyArgTestCase(unittest.TestCase):
fundef3 += "i%d, "%i
fundef3 += "lastarg):\n pass\n"
compile(fundef3, "<test>", "single")
-
+
def testSyntaxErrorForFunctionCall(self):
self.assertRaisesSyntaxError("f(p, k=1, p2)")
self.assertRaisesSyntaxError("f(p, *(1,2), k1=100)")
diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py
index ba7d653..eba2cfd 100644
--- a/Lib/test/test_locale.py
+++ b/Lib/test/test_locale.py
@@ -7,7 +7,7 @@ if sys.platform == 'darwin':
oldlocale = locale.setlocale(locale.LC_NUMERIC)
if sys.platform.startswith("win"):
- tlocs = ("en",)
+ tlocs = ("En", "English")
else:
tlocs = ("en_US.UTF-8", "en_US.US-ASCII", "en_US")
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 843440a..e8e4a8d 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -554,6 +554,8 @@ def test5():
except KeyError:
logging.exception("just testing")
os.remove(fn)
+ hdlr = logging.getLogger().handlers[0]
+ logging.getLogger().handlers.remove(hdlr)
finally:
logging._acquireLock()
try:
diff --git a/Lib/test/test_long_future.py b/Lib/test/test_long_future.py
index fc01001..36840b4 100644
--- a/Lib/test/test_long_future.py
+++ b/Lib/test/test_long_future.py
@@ -3,53 +3,53 @@ from __future__ import division
# test_long.py instead. In the meantime, it's too obscure to try to
# trick just part of test_long into using future division.
-from test.test_support import TestFailed, verify, verbose
-
-def test_true_division():
- if verbose:
- print("long true division")
- huge = 1 << 40000
- mhuge = -huge
- verify(huge / huge == 1.0)
- verify(mhuge / mhuge == 1.0)
- verify(huge / mhuge == -1.0)
- verify(mhuge / huge == -1.0)
- verify(1 / huge == 0.0)
- verify(1 / huge == 0.0)
- verify(1 / mhuge == 0.0)
- verify(1 / mhuge == 0.0)
- verify((666 * huge + (huge >> 1)) / huge == 666.5)
- verify((666 * mhuge + (mhuge >> 1)) / mhuge == 666.5)
- verify((666 * huge + (huge >> 1)) / mhuge == -666.5)
- verify((666 * mhuge + (mhuge >> 1)) / huge == -666.5)
- verify(huge / (huge << 1) == 0.5)
- verify((1000000 * huge) / huge == 1000000)
-
- namespace = {'huge': huge, 'mhuge': mhuge}
-
- for overflow in ["float(huge)", "float(mhuge)",
- "huge / 1", "huge / 2", "huge / -1", "huge / -2",
- "mhuge / 100", "mhuge / 100"]:
- try:
- eval(overflow, namespace)
- except OverflowError:
- pass
- else:
- raise TestFailed("expected OverflowError from %r" % overflow)
-
- for underflow in ["1 / huge", "2 / huge", "-1 / huge", "-2 / huge",
- "100 / mhuge", "100 / mhuge"]:
- result = eval(underflow, namespace)
- if result != 0.0:
- raise TestFailed("expected underflow to 0 from %r" % underflow)
-
- for zero in ["huge / 0", "huge / 0",
- "mhuge / 0", "mhuge / 0"]:
- try:
- eval(zero, namespace)
- except ZeroDivisionError:
- pass
- else:
- raise TestFailed("expected ZeroDivisionError from %r" % zero)
-
-test_true_division()
+import unittest
+from test.test_support import run_unittest
+
+class TrueDivisionTests(unittest.TestCase):
+ def test(self):
+ huge = 1 << 40000
+ mhuge = -huge
+ self.assertEqual(huge / huge, 1.0)
+ self.assertEqual(mhuge / mhuge, 1.0)
+ self.assertEqual(huge / mhuge, -1.0)
+ self.assertEqual(mhuge / huge, -1.0)
+ self.assertEqual(1 / huge, 0.0)
+ self.assertEqual(1 / huge, 0.0)
+ self.assertEqual(1 / mhuge, 0.0)
+ self.assertEqual(1 / mhuge, 0.0)
+ self.assertEqual((666 * huge + (huge >> 1)) / huge, 666.5)
+ self.assertEqual((666 * mhuge + (mhuge >> 1)) / mhuge, 666.5)
+ self.assertEqual((666 * huge + (huge >> 1)) / mhuge, -666.5)
+ self.assertEqual((666 * mhuge + (mhuge >> 1)) / huge, -666.5)
+ self.assertEqual(huge / (huge << 1), 0.5)
+ self.assertEqual((1000000 * huge) / huge, 1000000)
+
+ namespace = {'huge': huge, 'mhuge': mhuge}
+
+ for overflow in ["float(huge)", "float(mhuge)",
+ "huge / 1", "huge / 2", "huge / -1", "huge / -2",
+ "mhuge / 100", "mhuge / 200"]:
+ # XXX(cwinter) this test doesn't pass when converted to
+ # use assertRaises.
+ try:
+ eval(overflow, namespace)
+ self.fail("expected OverflowError from %r" % overflow)
+ except OverflowError:
+ pass
+
+ for underflow in ["1 / huge", "2 / huge", "-1 / huge", "-2 / huge",
+ "100 / mhuge", "200 / mhuge"]:
+ result = eval(underflow, namespace)
+ self.assertEqual(result, 0.0,
+ "expected underflow to 0 from %r" % underflow)
+
+ for zero in ["huge / 0", "mhuge / 0"]:
+ self.assertRaises(ZeroDivisionError, eval, zero, namespace)
+
+
+def test_main():
+ run_unittest(TrueDivisionTests)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_macpath.py b/Lib/test/test_macpath.py
index 3a3cf04..2449b0a 100644
--- a/Lib/test/test_macpath.py
+++ b/Lib/test/test_macpath.py
@@ -48,7 +48,7 @@ class MacPathTestCase(unittest.TestCase):
splitext = macpath.splitext
self.assertEquals(splitext(":foo.ext"), (':foo', '.ext'))
self.assertEquals(splitext("foo:foo.ext"), ('foo:foo', '.ext'))
- self.assertEquals(splitext(".ext"), ('', '.ext'))
+ self.assertEquals(splitext(".ext"), ('.ext', ''))
self.assertEquals(splitext("foo.ext:foo"), ('foo.ext:foo', ''))
self.assertEquals(splitext(":foo.ext:"), (':foo.ext:', ''))
self.assertEquals(splitext(""), ('', ''))
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 8650cef..1972ca3 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -54,6 +54,7 @@ class TestMailbox(TestBase):
def setUp(self):
self._path = test_support.TESTFN
+ self._delete_recursively(self._path)
self._box = self._factory(self._path)
def tearDown(self):
@@ -686,7 +687,7 @@ class _TestMboxMMDF(TestMailbox):
self._box.close()
self._delete_recursively(self._path)
for lock_remnant in glob.glob(self._path + '.*'):
- os.remove(lock_remnant)
+ test_support.unlink(lock_remnant)
def test_add_from_string(self):
# Add a string starting with 'From ' to the mailbox
@@ -909,7 +910,7 @@ class TestBabyl(TestMailbox):
self._box.close()
self._delete_recursively(self._path)
for lock_remnant in glob.glob(self._path + '.*'):
- os.remove(lock_remnant)
+ test_support.unlink(lock_remnant)
def test_labels(self):
# Get labels from the mailbox
diff --git a/Lib/test/test_metaclass.py b/Lib/test/test_metaclass.py
index df81079..9126cf6 100644
--- a/Lib/test/test_metaclass.py
+++ b/Lib/test/test_metaclass.py
@@ -63,6 +63,8 @@ Use a metaclass with a __prepare__ static method.
... def __new__(cls, name, bases, namespace, **kwds):
... print("New called:", kwds)
... return type.__new__(cls, name, bases, namespace)
+ ... def __init__(cls, *args, **kwds):
+ ... pass
...
>>> class C(metaclass=M):
... def meth(self): print("Hello")
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
index 6c4dd94..5f95365 100644
--- a/Lib/test/test_minidom.py
+++ b/Lib/test/test_minidom.py
@@ -5,7 +5,8 @@ import sys
import pickle
import traceback
from StringIO import StringIO
-from test.test_support import verbose
+from test.test_support import verbose, run_unittest, TestSkipped
+import unittest
import xml.dom
import xml.dom.minidom
@@ -22,680 +23,9 @@ else:
tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
del base
-def confirm(test, testname = "Test"):
- if not test:
- print("Failed " + testname)
- raise Exception
-
-def testParseFromFile():
- dom = parse(StringIO(open(tstfile).read()))
- dom.unlink()
- confirm(isinstance(dom,Document))
-
-def testGetElementsByTagName():
- dom = parse(tstfile)
- confirm(dom.getElementsByTagName("LI") == \
- dom.documentElement.getElementsByTagName("LI"))
- dom.unlink()
-
-def testInsertBefore():
- dom = parseString("<doc><foo/></doc>")
- root = dom.documentElement
- elem = root.childNodes[0]
- nelem = dom.createElement("element")
- root.insertBefore(nelem, elem)
- confirm(len(root.childNodes) == 2
- and root.childNodes.length == 2
- and root.childNodes[0] is nelem
- and root.childNodes.item(0) is nelem
- and root.childNodes[1] is elem
- and root.childNodes.item(1) is elem
- and root.firstChild is nelem
- and root.lastChild is elem
- and root.toxml() == "<doc><element/><foo/></doc>"
- , "testInsertBefore -- node properly placed in tree")
- nelem = dom.createElement("element")
- root.insertBefore(nelem, None)
- confirm(len(root.childNodes) == 3
- and root.childNodes.length == 3
- and root.childNodes[1] is elem
- and root.childNodes.item(1) is elem
- and root.childNodes[2] is nelem
- and root.childNodes.item(2) is nelem
- and root.lastChild is nelem
- and nelem.previousSibling is elem
- and root.toxml() == "<doc><element/><foo/><element/></doc>"
- , "testInsertBefore -- node properly placed in tree")
- nelem2 = dom.createElement("bar")
- root.insertBefore(nelem2, nelem)
- confirm(len(root.childNodes) == 4
- and root.childNodes.length == 4
- and root.childNodes[2] is nelem2
- and root.childNodes.item(2) is nelem2
- and root.childNodes[3] is nelem
- and root.childNodes.item(3) is nelem
- and nelem2.nextSibling is nelem
- and nelem.previousSibling is nelem2
- and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
- , "testInsertBefore -- node properly placed in tree")
- dom.unlink()
-
-def _create_fragment_test_nodes():
- dom = parseString("<doc/>")
- orig = dom.createTextNode("original")
- c1 = dom.createTextNode("foo")
- c2 = dom.createTextNode("bar")
- c3 = dom.createTextNode("bat")
- dom.documentElement.appendChild(orig)
- frag = dom.createDocumentFragment()
- frag.appendChild(c1)
- frag.appendChild(c2)
- frag.appendChild(c3)
- return dom, orig, c1, c2, c3, frag
-
-def testInsertBeforeFragment():
- dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
- dom.documentElement.insertBefore(frag, None)
- confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
- "insertBefore(<fragment>, None)")
- frag.unlink()
- dom.unlink()
- #
- dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
- dom.documentElement.insertBefore(frag, orig)
- confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
- "insertBefore(<fragment>, orig)")
- frag.unlink()
- dom.unlink()
-
-def testAppendChild():
- dom = parse(tstfile)
- dom.documentElement.appendChild(dom.createComment(u"Hello"))
- confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
- confirm(dom.documentElement.childNodes[-1].data == "Hello")
- dom.unlink()
-
-def testAppendChildFragment():
- dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
- dom.documentElement.appendChild(frag)
- confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
- "appendChild(<fragment>)")
- frag.unlink()
- dom.unlink()
-
-def testReplaceChildFragment():
- dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
- dom.documentElement.replaceChild(frag, orig)
- orig.unlink()
- confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
- "replaceChild(<fragment>)")
- frag.unlink()
- dom.unlink()
-
-def testLegalChildren():
- dom = Document()
- elem = dom.createElement('element')
- text = dom.createTextNode('text')
-
- try: dom.appendChild(text)
- except xml.dom.HierarchyRequestErr: pass
- else:
- print("dom.appendChild didn't raise HierarchyRequestErr")
-
- dom.appendChild(elem)
- try: dom.insertBefore(text, elem)
- except xml.dom.HierarchyRequestErr: pass
- else:
- print("dom.appendChild didn't raise HierarchyRequestErr")
-
- try: dom.replaceChild(text, elem)
- except xml.dom.HierarchyRequestErr: pass
- else:
- print("dom.appendChild didn't raise HierarchyRequestErr")
-
- nodemap = elem.attributes
- try: nodemap.setNamedItem(text)
- except xml.dom.HierarchyRequestErr: pass
- else:
- print("NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr")
-
- try: nodemap.setNamedItemNS(text)
- except xml.dom.HierarchyRequestErr: pass
- else:
- print("NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr")
-
- elem.appendChild(text)
- dom.unlink()
-
-def testNamedNodeMapSetItem():
- dom = Document()
- elem = dom.createElement('element')
- attrs = elem.attributes
- attrs["foo"] = "bar"
- a = attrs.item(0)
- confirm(a.ownerDocument is dom,
- "NamedNodeMap.__setitem__() sets ownerDocument")
- confirm(a.ownerElement is elem,
- "NamedNodeMap.__setitem__() sets ownerElement")
- confirm(a.value == "bar",
- "NamedNodeMap.__setitem__() sets value")
- confirm(a.nodeValue == "bar",
- "NamedNodeMap.__setitem__() sets nodeValue")
- elem.unlink()
- dom.unlink()
-
-def testNonZero():
- dom = parse(tstfile)
- confirm(dom)# should not be zero
- dom.appendChild(dom.createComment("foo"))
- confirm(not dom.childNodes[-1].childNodes)
- dom.unlink()
-
-def testUnlink():
- dom = parse(tstfile)
- dom.unlink()
-
-def testElement():
- dom = Document()
- dom.appendChild(dom.createElement("abc"))
- confirm(dom.documentElement)
- dom.unlink()
-
-def testAAA():
- dom = parseString("<abc/>")
- el = dom.documentElement
- el.setAttribute("spam", "jam2")
- confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
- a = el.getAttributeNode("spam")
- confirm(a.ownerDocument is dom,
- "setAttribute() sets ownerDocument")
- confirm(a.ownerElement is dom.documentElement,
- "setAttribute() sets ownerElement")
- dom.unlink()
-
-def testAAB():
- dom = parseString("<abc/>")
- el = dom.documentElement
- el.setAttribute("spam", "jam")
- el.setAttribute("spam", "jam2")
- confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
- dom.unlink()
-
-def testAddAttr():
- dom = Document()
- child = dom.appendChild(dom.createElement("abc"))
-
- child.setAttribute("def", "ghi")
- confirm(child.getAttribute("def") == "ghi")
- confirm(child.attributes["def"].value == "ghi")
-
- child.setAttribute("jkl", "mno")
- confirm(child.getAttribute("jkl") == "mno")
- confirm(child.attributes["jkl"].value == "mno")
-
- confirm(len(child.attributes) == 2)
-
- child.setAttribute("def", "newval")
- confirm(child.getAttribute("def") == "newval")
- confirm(child.attributes["def"].value == "newval")
-
- confirm(len(child.attributes) == 2)
- dom.unlink()
-
-def testDeleteAttr():
- dom = Document()
- child = dom.appendChild(dom.createElement("abc"))
-
- confirm(len(child.attributes) == 0)
- child.setAttribute("def", "ghi")
- confirm(len(child.attributes) == 1)
- del child.attributes["def"]
- confirm(len(child.attributes) == 0)
- dom.unlink()
-
-def testRemoveAttr():
- dom = Document()
- child = dom.appendChild(dom.createElement("abc"))
-
- child.setAttribute("def", "ghi")
- confirm(len(child.attributes) == 1)
- child.removeAttribute("def")
- confirm(len(child.attributes) == 0)
-
- dom.unlink()
-
-def testRemoveAttrNS():
- dom = Document()
- child = dom.appendChild(
- dom.createElementNS("http://www.python.org", "python:abc"))
- child.setAttributeNS("http://www.w3.org", "xmlns:python",
- "http://www.python.org")
- child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
- confirm(len(child.attributes) == 2)
- child.removeAttributeNS("http://www.python.org", "abcattr")
- confirm(len(child.attributes) == 1)
-
- dom.unlink()
-
-def testRemoveAttributeNode():
- dom = Document()
- child = dom.appendChild(dom.createElement("foo"))
- child.setAttribute("spam", "jam")
- confirm(len(child.attributes) == 1)
- node = child.getAttributeNode("spam")
- child.removeAttributeNode(node)
- confirm(len(child.attributes) == 0
- and child.getAttributeNode("spam") is None)
-
- dom.unlink()
-
-def testChangeAttr():
- dom = parseString("<abc/>")
- el = dom.documentElement
- el.setAttribute("spam", "jam")
- confirm(len(el.attributes) == 1)
- el.setAttribute("spam", "bam")
- # Set this attribute to be an ID and make sure that doesn't change
- # when changing the value:
- el.setIdAttribute("spam")
- confirm(len(el.attributes) == 1
- and el.attributes["spam"].value == "bam"
- and el.attributes["spam"].nodeValue == "bam"
- and el.getAttribute("spam") == "bam"
- and el.getAttributeNode("spam").isId)
- el.attributes["spam"] = "ham"
- confirm(len(el.attributes) == 1
- and el.attributes["spam"].value == "ham"
- and el.attributes["spam"].nodeValue == "ham"
- and el.getAttribute("spam") == "ham"
- and el.attributes["spam"].isId)
- el.setAttribute("spam2", "bam")
- confirm(len(el.attributes) == 2
- and el.attributes["spam"].value == "ham"
- and el.attributes["spam"].nodeValue == "ham"
- and el.getAttribute("spam") == "ham"
- and el.attributes["spam2"].value == "bam"
- and el.attributes["spam2"].nodeValue == "bam"
- and el.getAttribute("spam2") == "bam")
- el.attributes["spam2"] = "bam2"
- confirm(len(el.attributes) == 2
- and el.attributes["spam"].value == "ham"
- and el.attributes["spam"].nodeValue == "ham"
- and el.getAttribute("spam") == "ham"
- and el.attributes["spam2"].value == "bam2"
- and el.attributes["spam2"].nodeValue == "bam2"
- and el.getAttribute("spam2") == "bam2")
- dom.unlink()
-
-def testGetAttrList():
- pass
-
-def testGetAttrValues(): pass
-
-def testGetAttrLength(): pass
-
-def testGetAttribute(): pass
-
-def testGetAttributeNS(): pass
-
-def testGetAttributeNode(): pass
-
-def testGetElementsByTagNameNS():
- d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
- <minidom:myelem/>
- </foo>"""
- dom = parseString(d)
- elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem")
- confirm(len(elems) == 1
- and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
- and elems[0].localName == "myelem"
- and elems[0].prefix == "minidom"
- and elems[0].tagName == "minidom:myelem"
- and elems[0].nodeName == "minidom:myelem")
- dom.unlink()
-
-def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname):
- nodelist = doc.getElementsByTagNameNS(nsuri, lname)
- confirm(len(nodelist) == 0)
-
-def testGetEmptyNodeListFromElementsByTagNameNS():
- doc = parseString('<doc/>')
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, 'http://xml.python.org/namespaces/a', 'localname')
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, '*', 'splat')
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, 'http://xml.python.org/namespaces/a', '*')
-
- doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, "http://xml.python.org/splat", "not-there")
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, "*", "not-there")
- get_empty_nodelist_from_elements_by_tagName_ns_helper(
- doc, "http://somewhere.else.net/not-there", "e")
-
-def testElementReprAndStr():
- dom = Document()
- el = dom.appendChild(dom.createElement("abc"))
- string1 = repr(el)
- string2 = str(el)
- confirm(string1 == string2)
- dom.unlink()
-
-# commented out until Fredrick's fix is checked in
-def _testElementReprAndStrUnicode():
- dom = Document()
- el = dom.appendChild(dom.createElement(u"abc"))
- string1 = repr(el)
- string2 = str(el)
- confirm(string1 == string2)
- dom.unlink()
-
-# commented out until Fredrick's fix is checked in
-def _testElementReprAndStrUnicodeNS():
- dom = Document()
- el = dom.appendChild(
- dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
- string1 = repr(el)
- string2 = str(el)
- confirm(string1 == string2)
- confirm(string1.find("slash:abc") != -1)
- dom.unlink()
-
-def testAttributeRepr():
- dom = Document()
- el = dom.appendChild(dom.createElement(u"abc"))
- node = el.setAttribute("abc", "def")
- confirm(str(node) == repr(node))
- dom.unlink()
-
-def testTextNodeRepr(): pass
-
-def testWriteXML():
- str = '<?xml version="1.0" ?><a b="c"/>'
- dom = parseString(str)
- domstr = dom.toxml()
- dom.unlink()
- confirm(str == domstr)
-
-def testAltNewline():
- str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
- dom = parseString(str)
- domstr = dom.toprettyxml(newl="\r\n")
- dom.unlink()
- confirm(domstr == str.replace("\n", "\r\n"))
-
-def testProcessingInstruction():
- dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
- pi = dom.documentElement.firstChild
- confirm(pi.target == "mypi"
- and pi.data == "data \t\n "
- and pi.nodeName == "mypi"
- and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
- and pi.attributes is None
- and not pi.hasChildNodes()
- and len(pi.childNodes) == 0
- and pi.firstChild is None
- and pi.lastChild is None
- and pi.localName is None
- and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
-
-def testProcessingInstructionRepr(): pass
-
-def testTextRepr(): pass
-
-def testWriteText(): pass
-
-def testDocumentElement(): pass
-
-def testTooManyDocumentElements():
- doc = parseString("<doc/>")
- elem = doc.createElement("extra")
- try:
- doc.appendChild(elem)
- except xml.dom.HierarchyRequestErr:
- pass
- else:
- print("Failed to catch expected exception when" \
- " adding extra document element.")
- elem.unlink()
- doc.unlink()
-
-def testCreateElementNS(): pass
-
-def testCreateAttributeNS(): pass
-
-def testParse(): pass
-
-def testParseString(): pass
-
-def testComment(): pass
-
-def testAttrListItem(): pass
-
-def testAttrListItems(): pass
-
-def testAttrListItemNS(): pass
-
-def testAttrListKeys(): pass
-
-def testAttrListKeysNS(): pass
-
-def testRemoveNamedItem():
- doc = parseString("<doc a=''/>")
- e = doc.documentElement
- attrs = e.attributes
- a1 = e.getAttributeNode("a")
- a2 = attrs.removeNamedItem("a")
- confirm(a1.isSameNode(a2))
- try:
- attrs.removeNamedItem("a")
- except xml.dom.NotFoundErr:
- pass
-
-def testRemoveNamedItemNS():
- doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
- e = doc.documentElement
- attrs = e.attributes
- a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
- a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
- confirm(a1.isSameNode(a2))
- try:
- attrs.removeNamedItemNS("http://xml.python.org/", "b")
- except xml.dom.NotFoundErr:
- pass
-
-def testAttrListValues(): pass
-
-def testAttrListLength(): pass
-
-def testAttrList__getitem__(): pass
-
-def testAttrList__setitem__(): pass
-
-def testSetAttrValueandNodeValue(): pass
-
-def testParseElement(): pass
-
-def testParseAttributes(): pass
-
-def testParseElementNamespaces(): pass
-
-def testParseAttributeNamespaces(): pass
-
-def testParseProcessingInstructions(): pass
-
-def testChildNodes(): pass
-
-def testFirstChild(): pass
-
-def testHasChildNodes(): pass
-
-def testCloneElementShallow():
- dom, clone = _setupCloneElement(0)
- confirm(len(clone.childNodes) == 0
- and clone.childNodes.length == 0
- and clone.parentNode is None
- and clone.toxml() == '<doc attr="value"/>'
- , "testCloneElementShallow")
- dom.unlink()
-
-def testCloneElementDeep():
- dom, clone = _setupCloneElement(1)
- confirm(len(clone.childNodes) == 1
- and clone.childNodes.length == 1
- and clone.parentNode is None
- and clone.toxml() == '<doc attr="value"><foo/></doc>'
- , "testCloneElementDeep")
- dom.unlink()
-
-def _setupCloneElement(deep):
- dom = parseString("<doc attr='value'><foo/></doc>")
- root = dom.documentElement
- clone = root.cloneNode(deep)
- _testCloneElementCopiesAttributes(
- root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
- # mutilate the original so shared data is detected
- root.tagName = root.nodeName = "MODIFIED"
- root.setAttribute("attr", "NEW VALUE")
- root.setAttribute("added", "VALUE")
- return dom, clone
-
-def _testCloneElementCopiesAttributes(e1, e2, test):
- attrs1 = e1.attributes
- attrs2 = e2.attributes
- keys1 = sorted(attrs1.keys())
- keys2 = sorted(attrs2.keys())
- confirm(keys1 == keys2, "clone of element has same attribute keys")
- for i in range(len(keys1)):
- a1 = attrs1.item(i)
- a2 = attrs2.item(i)
- confirm(a1 is not a2
- and a1.value == a2.value
- and a1.nodeValue == a2.nodeValue
- and a1.namespaceURI == a2.namespaceURI
- and a1.localName == a2.localName
- , "clone of attribute node has proper attribute values")
- confirm(a2.ownerElement is e2,
- "clone of attribute node correctly owned")
-
-def testCloneDocumentShallow():
- doc = parseString("<?xml version='1.0'?>\n"
- "<!-- comment -->"
- "<!DOCTYPE doc [\n"
- "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
- "]>\n"
- "<doc attr='value'/>")
- doc2 = doc.cloneNode(0)
- confirm(doc2 is None,
- "testCloneDocumentShallow:"
- " shallow cloning of documents makes no sense!")
-
-def testCloneDocumentDeep():
- doc = parseString("<?xml version='1.0'?>\n"
- "<!-- comment -->"
- "<!DOCTYPE doc [\n"
- "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
- "]>\n"
- "<doc attr='value'/>")
- doc2 = doc.cloneNode(1)
- confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
- "testCloneDocumentDeep: document objects not distinct")
- confirm(len(doc.childNodes) == len(doc2.childNodes),
- "testCloneDocumentDeep: wrong number of Document children")
- confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
- "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
- confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
- "testCloneDocumentDeep: documentElement owner is not new document")
- confirm(not doc.documentElement.isSameNode(doc2.documentElement),
- "testCloneDocumentDeep: documentElement should not be shared")
- if doc.doctype is not None:
- # check the doctype iff the original DOM maintained it
- confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
- "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
- confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
- confirm(not doc.doctype.isSameNode(doc2.doctype))
-
-def testCloneDocumentTypeDeepOk():
- doctype = create_nonempty_doctype()
- clone = doctype.cloneNode(1)
- confirm(clone is not None
- and clone.nodeName == doctype.nodeName
- and clone.name == doctype.name
- and clone.publicId == doctype.publicId
- and clone.systemId == doctype.systemId
- and len(clone.entities) == len(doctype.entities)
- and clone.entities.item(len(clone.entities)) is None
- and len(clone.notations) == len(doctype.notations)
- and clone.notations.item(len(clone.notations)) is None
- and len(clone.childNodes) == 0)
- for i in range(len(doctype.entities)):
- se = doctype.entities.item(i)
- ce = clone.entities.item(i)
- confirm((not se.isSameNode(ce))
- and (not ce.isSameNode(se))
- and ce.nodeName == se.nodeName
- and ce.notationName == se.notationName
- and ce.publicId == se.publicId
- and ce.systemId == se.systemId
- and ce.encoding == se.encoding
- and ce.actualEncoding == se.actualEncoding
- and ce.version == se.version)
- for i in range(len(doctype.notations)):
- sn = doctype.notations.item(i)
- cn = clone.notations.item(i)
- confirm((not sn.isSameNode(cn))
- and (not cn.isSameNode(sn))
- and cn.nodeName == sn.nodeName
- and cn.publicId == sn.publicId
- and cn.systemId == sn.systemId)
-
-def testCloneDocumentTypeDeepNotOk():
- doc = create_doc_with_doctype()
- clone = doc.doctype.cloneNode(1)
- confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
-
-def testCloneDocumentTypeShallowOk():
- doctype = create_nonempty_doctype()
- clone = doctype.cloneNode(0)
- confirm(clone is not None
- and clone.nodeName == doctype.nodeName
- and clone.name == doctype.name
- and clone.publicId == doctype.publicId
- and clone.systemId == doctype.systemId
- and len(clone.entities) == 0
- and clone.entities.item(0) is None
- and len(clone.notations) == 0
- and clone.notations.item(0) is None
- and len(clone.childNodes) == 0)
-
-def testCloneDocumentTypeShallowNotOk():
- doc = create_doc_with_doctype()
- clone = doc.doctype.cloneNode(0)
- confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
-
-def check_import_document(deep, testName):
- doc1 = parseString("<doc/>")
- doc2 = parseString("<doc/>")
- try:
- doc1.importNode(doc2, deep)
- except xml.dom.NotSupportedErr:
- pass
- else:
- raise Exception(testName +
- ": expected NotSupportedErr when importing a document")
-
-def testImportDocumentShallow():
- check_import_document(0, "testImportDocumentShallow")
-
-def testImportDocumentDeep():
- check_import_document(1, "testImportDocumentDeep")
-
# The tests of DocumentType importing use these helpers to construct
# the documents to work with, since not all DOM builders actually
# create the DocumentType nodes.
-
def create_doc_without_doctype(doctype=None):
return getDOMImplementation().createDocument(None, "doc", doctype)
@@ -722,673 +52,1263 @@ def create_doc_with_doctype():
doctype.notations.item(0).ownerDocument = doc
return doc
-def testImportDocumentTypeShallow():
- src = create_doc_with_doctype()
- target = create_doc_without_doctype()
- try:
- imported = target.importNode(src.doctype, 0)
- except xml.dom.NotSupportedErr:
- pass
- else:
- raise Exception(
- "testImportDocumentTypeShallow: expected NotSupportedErr")
-
-def testImportDocumentTypeDeep():
- src = create_doc_with_doctype()
- target = create_doc_without_doctype()
- try:
- imported = target.importNode(src.doctype, 1)
- except xml.dom.NotSupportedErr:
- pass
- else:
- raise Exception(
- "testImportDocumentTypeDeep: expected NotSupportedErr")
-
-# Testing attribute clones uses a helper, and should always be deep,
-# even if the argument to cloneNode is false.
-def check_clone_attribute(deep, testName):
- doc = parseString("<doc attr='value'/>")
- attr = doc.documentElement.getAttributeNode("attr")
- assert attr is not None
- clone = attr.cloneNode(deep)
- confirm(not clone.isSameNode(attr))
- confirm(not attr.isSameNode(clone))
- confirm(clone.ownerElement is None,
- testName + ": ownerElement should be None")
- confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
- testName + ": ownerDocument does not match")
- confirm(clone.specified,
- testName + ": cloned attribute must have specified == True")
-
-def testCloneAttributeShallow():
- check_clone_attribute(0, "testCloneAttributeShallow")
-
-def testCloneAttributeDeep():
- check_clone_attribute(1, "testCloneAttributeDeep")
-
-def check_clone_pi(deep, testName):
- doc = parseString("<?target data?><doc/>")
- pi = doc.firstChild
- assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
- clone = pi.cloneNode(deep)
- confirm(clone.target == pi.target
- and clone.data == pi.data)
-
-def testClonePIShallow():
- check_clone_pi(0, "testClonePIShallow")
-
-def testClonePIDeep():
- check_clone_pi(1, "testClonePIDeep")
-
-def testNormalize():
- doc = parseString("<doc/>")
- root = doc.documentElement
- root.appendChild(doc.createTextNode("first"))
- root.appendChild(doc.createTextNode("second"))
- confirm(len(root.childNodes) == 2
- and root.childNodes.length == 2, "testNormalize -- preparation")
- doc.normalize()
- confirm(len(root.childNodes) == 1
- and root.childNodes.length == 1
- and root.firstChild is root.lastChild
- and root.firstChild.data == "firstsecond"
- , "testNormalize -- result")
- doc.unlink()
-
- doc = parseString("<doc/>")
- root = doc.documentElement
- root.appendChild(doc.createTextNode(""))
- doc.normalize()
- confirm(len(root.childNodes) == 0
- and root.childNodes.length == 0,
- "testNormalize -- single empty node removed")
- doc.unlink()
-
-def testSiblings():
- doc = parseString("<doc><?pi?>text?<elm/></doc>")
- root = doc.documentElement
- (pi, text, elm) = root.childNodes
-
- confirm(pi.nextSibling is text and
- pi.previousSibling is None and
- text.nextSibling is elm and
- text.previousSibling is pi and
- elm.nextSibling is None and
- elm.previousSibling is text, "testSiblings")
-
- doc.unlink()
-
-def testParents():
- doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
- root = doc.documentElement
- elm1 = root.childNodes[0]
- (elm2a, elm2b) = elm1.childNodes
- elm3 = elm2b.childNodes[0]
-
- confirm(root.parentNode is doc and
- elm1.parentNode is root and
- elm2a.parentNode is elm1 and
- elm2b.parentNode is elm1 and
- elm3.parentNode is elm2b, "testParents")
-
- doc.unlink()
-
-def testNodeListItem():
- doc = parseString("<doc><e/><e/></doc>")
- children = doc.childNodes
- docelem = children[0]
- confirm(children[0] is children.item(0)
- and children.item(1) is None
- and docelem.childNodes.item(0) is docelem.childNodes[0]
- and docelem.childNodes.item(1) is docelem.childNodes[1]
- and docelem.childNodes.item(0).childNodes.item(0) is None,
- "test NodeList.item()")
- doc.unlink()
-
-def testSAX2DOM():
- from xml.dom import pulldom
-
- sax2dom = pulldom.SAX2DOM()
- sax2dom.startDocument()
- sax2dom.startElement("doc", {})
- sax2dom.characters("text")
- sax2dom.startElement("subelm", {})
- sax2dom.characters("text")
- sax2dom.endElement("subelm")
- sax2dom.characters("text")
- sax2dom.endElement("doc")
- sax2dom.endDocument()
-
- doc = sax2dom.document
- root = doc.documentElement
- (text1, elm1, text2) = root.childNodes
- text3 = elm1.childNodes[0]
-
- confirm(text1.previousSibling is None and
- text1.nextSibling is elm1 and
- elm1.previousSibling is text1 and
- elm1.nextSibling is text2 and
- text2.previousSibling is elm1 and
- text2.nextSibling is None and
- text3.previousSibling is None and
- text3.nextSibling is None, "testSAX2DOM - siblings")
-
- confirm(root.parentNode is doc and
- text1.parentNode is root and
- elm1.parentNode is root and
- text2.parentNode is root and
- text3.parentNode is elm1, "testSAX2DOM - parents")
-
- doc.unlink()
-
-def testEncodings():
- doc = parseString('<foo>&#x20ac;</foo>')
- confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
- and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
- and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
- "testEncodings - encoding EURO SIGN")
-
- # Verify that character decoding errors throw exceptions instead of crashing
- try:
- doc = parseString('<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
- except UnicodeDecodeError:
- pass
- else:
- print('parsing with bad encoding should raise a UnicodeDecodeError')
-
- doc.unlink()
-
-class UserDataHandler:
- called = 0
- def handle(self, operation, key, data, src, dst):
- dst.setUserData(key, data + 1, self)
- src.setUserData(key, None, None)
- self.called = 1
-
-def testUserData():
- dom = Document()
- n = dom.createElement('e')
- confirm(n.getUserData("foo") is None)
- n.setUserData("foo", None, None)
- confirm(n.getUserData("foo") is None)
- n.setUserData("foo", 12, 12)
- n.setUserData("bar", 13, 13)
- confirm(n.getUserData("foo") == 12)
- confirm(n.getUserData("bar") == 13)
- n.setUserData("foo", None, None)
- confirm(n.getUserData("foo") is None)
- confirm(n.getUserData("bar") == 13)
-
- handler = UserDataHandler()
- n.setUserData("bar", 12, handler)
- c = n.cloneNode(1)
- confirm(handler.called
- and n.getUserData("bar") is None
- and c.getUserData("bar") == 13)
- n.unlink()
- c.unlink()
- dom.unlink()
-
-def testRenameAttribute():
- doc = parseString("<doc a='v'/>")
- elem = doc.documentElement
- attrmap = elem.attributes
- attr = elem.attributes['a']
-
- # Simple renaming
- attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
- confirm(attr.name == "b"
- and attr.nodeName == "b"
- and attr.localName is None
- and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
- and attr.prefix is None
- and attr.value == "v"
- and elem.getAttributeNode("a") is None
- and elem.getAttributeNode("b").isSameNode(attr)
- and attrmap["b"].isSameNode(attr)
- and attr.ownerDocument.isSameNode(doc)
- and attr.ownerElement.isSameNode(elem))
-
- # Rename to have a namespace, no prefix
- attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
- confirm(attr.name == "c"
- and attr.nodeName == "c"
- and attr.localName == "c"
- and attr.namespaceURI == "http://xml.python.org/ns"
- and attr.prefix is None
- and attr.value == "v"
- and elem.getAttributeNode("a") is None
- and elem.getAttributeNode("b") is None
- and elem.getAttributeNode("c").isSameNode(attr)
- and elem.getAttributeNodeNS(
- "http://xml.python.org/ns", "c").isSameNode(attr)
- and attrmap["c"].isSameNode(attr)
- and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
-
- # Rename to have a namespace, with prefix
- attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
- confirm(attr.name == "p:d"
- and attr.nodeName == "p:d"
- and attr.localName == "d"
- and attr.namespaceURI == "http://xml.python.org/ns2"
- and attr.prefix == "p"
- and attr.value == "v"
- and elem.getAttributeNode("a") is None
- and elem.getAttributeNode("b") is None
- and elem.getAttributeNode("c") is None
- and elem.getAttributeNodeNS(
- "http://xml.python.org/ns", "c") is None
- and elem.getAttributeNode("p:d").isSameNode(attr)
- and elem.getAttributeNodeNS(
- "http://xml.python.org/ns2", "d").isSameNode(attr)
- and attrmap["p:d"].isSameNode(attr)
- and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
-
- # Rename back to a simple non-NS node
- attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
- confirm(attr.name == "e"
- and attr.nodeName == "e"
- and attr.localName is None
- and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
- and attr.prefix is None
- and attr.value == "v"
- and elem.getAttributeNode("a") is None
- and elem.getAttributeNode("b") is None
- and elem.getAttributeNode("c") is None
- and elem.getAttributeNode("p:d") is None
- and elem.getAttributeNodeNS(
- "http://xml.python.org/ns", "c") is None
- and elem.getAttributeNode("e").isSameNode(attr)
- and attrmap["e"].isSameNode(attr))
-
- try:
- doc.renameNode(attr, "http://xml.python.org/ns", "xmlns")
- except xml.dom.NamespaceErr:
- pass
- else:
- print("expected NamespaceErr")
-
- checkRenameNodeSharedConstraints(doc, attr)
- doc.unlink()
-
-def testRenameElement():
- doc = parseString("<doc/>")
- elem = doc.documentElement
-
- # Simple renaming
- elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
- confirm(elem.tagName == "a"
- and elem.nodeName == "a"
- and elem.localName is None
- and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
- and elem.prefix is None
- and elem.ownerDocument.isSameNode(doc))
-
- # Rename to have a namespace, no prefix
- elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
- confirm(elem.tagName == "b"
- and elem.nodeName == "b"
- and elem.localName == "b"
- and elem.namespaceURI == "http://xml.python.org/ns"
- and elem.prefix is None
- and elem.ownerDocument.isSameNode(doc))
-
- # Rename to have a namespace, with prefix
- elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
- confirm(elem.tagName == "p:c"
- and elem.nodeName == "p:c"
- and elem.localName == "c"
- and elem.namespaceURI == "http://xml.python.org/ns2"
- and elem.prefix == "p"
- and elem.ownerDocument.isSameNode(doc))
-
- # Rename back to a simple non-NS node
- elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
- confirm(elem.tagName == "d"
- and elem.nodeName == "d"
- and elem.localName is None
- and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
- and elem.prefix is None
- and elem.ownerDocument.isSameNode(doc))
-
- checkRenameNodeSharedConstraints(doc, elem)
- doc.unlink()
-
-def checkRenameNodeSharedConstraints(doc, node):
- # Make sure illegal NS usage is detected:
- try:
- doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo")
- except xml.dom.NamespaceErr:
- pass
- else:
- print("expected NamespaceErr")
+class MinidomTest(unittest.TestCase):
+ def tearDown(self):
+ try:
+ Node.allnodes
+ except AttributeError:
+ # We don't actually have the minidom from the standard library,
+ # but are picking up the PyXML version from site-packages.
+ pass
+ else:
+ self.confirm(len(Node.allnodes) == 0,
+ "assertion: len(Node.allnodes) == 0")
+ if len(Node.allnodes):
+ print("Garbage left over:")
+ if verbose:
+ print(list(Node.allnodes.items())[0:10])
+ else:
+ # Don't print specific nodes if repeatable results
+ # are needed
+ print(len(Node.allnodes))
+ Node.allnodes = {}
- doc2 = parseString("<doc/>")
- try:
- doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
- except xml.dom.WrongDocumentErr:
- pass
- else:
- print("expected WrongDocumentErr")
-
-def testRenameOther():
- # We have to create a comment node explicitly since not all DOM
- # builders used with minidom add comments to the DOM.
- doc = xml.dom.minidom.getDOMImplementation().createDocument(
- xml.dom.EMPTY_NAMESPACE, "e", None)
- node = doc.createComment("comment")
- try:
- doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
- except xml.dom.NotSupportedErr:
+ def confirm(self, test, testname = "Test"):
+ self.assertTrue(test, testname)
+
+ def checkWholeText(self, node, s):
+ t = node.wholeText
+ self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
+
+ def testParseFromFile(self):
+ dom = parse(StringIO(open(tstfile).read()))
+ dom.unlink()
+ self.confirm(isinstance(dom, Document))
+
+ def testGetElementsByTagName(self):
+ dom = parse(tstfile)
+ self.confirm(dom.getElementsByTagName("LI") == \
+ dom.documentElement.getElementsByTagName("LI"))
+ dom.unlink()
+
+ def testInsertBefore(self):
+ dom = parseString("<doc><foo/></doc>")
+ root = dom.documentElement
+ elem = root.childNodes[0]
+ nelem = dom.createElement("element")
+ root.insertBefore(nelem, elem)
+ self.confirm(len(root.childNodes) == 2
+ and root.childNodes.length == 2
+ and root.childNodes[0] is nelem
+ and root.childNodes.item(0) is nelem
+ and root.childNodes[1] is elem
+ and root.childNodes.item(1) is elem
+ and root.firstChild is nelem
+ and root.lastChild is elem
+ and root.toxml() == "<doc><element/><foo/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ nelem = dom.createElement("element")
+ root.insertBefore(nelem, None)
+ self.confirm(len(root.childNodes) == 3
+ and root.childNodes.length == 3
+ and root.childNodes[1] is elem
+ and root.childNodes.item(1) is elem
+ and root.childNodes[2] is nelem
+ and root.childNodes.item(2) is nelem
+ and root.lastChild is nelem
+ and nelem.previousSibling is elem
+ and root.toxml() == "<doc><element/><foo/><element/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ nelem2 = dom.createElement("bar")
+ root.insertBefore(nelem2, nelem)
+ self.confirm(len(root.childNodes) == 4
+ and root.childNodes.length == 4
+ and root.childNodes[2] is nelem2
+ and root.childNodes.item(2) is nelem2
+ and root.childNodes[3] is nelem
+ and root.childNodes.item(3) is nelem
+ and nelem2.nextSibling is nelem
+ and nelem.previousSibling is nelem2
+ and root.toxml() ==
+ "<doc><element/><foo/><bar/><element/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ dom.unlink()
+
+ def _create_fragment_test_nodes(self):
+ dom = parseString("<doc/>")
+ orig = dom.createTextNode("original")
+ c1 = dom.createTextNode("foo")
+ c2 = dom.createTextNode("bar")
+ c3 = dom.createTextNode("bat")
+ dom.documentElement.appendChild(orig)
+ frag = dom.createDocumentFragment()
+ frag.appendChild(c1)
+ frag.appendChild(c2)
+ frag.appendChild(c3)
+ return dom, orig, c1, c2, c3, frag
+
+ def testInsertBeforeFragment(self):
+ dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+ dom.documentElement.insertBefore(frag, None)
+ self.confirm(tuple(dom.documentElement.childNodes) ==
+ (orig, c1, c2, c3),
+ "insertBefore(<fragment>, None)")
+ frag.unlink()
+ dom.unlink()
+
+ dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+ dom.documentElement.insertBefore(frag, orig)
+ self.confirm(tuple(dom.documentElement.childNodes) ==
+ (c1, c2, c3, orig),
+ "insertBefore(<fragment>, orig)")
+ frag.unlink()
+ dom.unlink()
+
+ def testAppendChild(self):
+ dom = parse(tstfile)
+ dom.documentElement.appendChild(dom.createComment(u"Hello"))
+ self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
+ self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
+ dom.unlink()
+
+ def testAppendChildFragment(self):
+ dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+ dom.documentElement.appendChild(frag)
+ self.confirm(tuple(dom.documentElement.childNodes) ==
+ (orig, c1, c2, c3),
+ "appendChild(<fragment>)")
+ frag.unlink()
+ dom.unlink()
+
+ def testReplaceChildFragment(self):
+ dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+ dom.documentElement.replaceChild(frag, orig)
+ orig.unlink()
+ self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
+ "replaceChild(<fragment>)")
+ frag.unlink()
+ dom.unlink()
+
+ def testLegalChildren(self):
+ dom = Document()
+ elem = dom.createElement('element')
+ text = dom.createTextNode('text')
+ self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
+
+ dom.appendChild(elem)
+ self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
+ elem)
+ self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
+ elem)
+
+ nodemap = elem.attributes
+ self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
+ text)
+ self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
+ text)
+
+ elem.appendChild(text)
+ dom.unlink()
+
+ def testNamedNodeMapSetItem(self):
+ dom = Document()
+ elem = dom.createElement('element')
+ attrs = elem.attributes
+ attrs["foo"] = "bar"
+ a = attrs.item(0)
+ self.confirm(a.ownerDocument is dom,
+ "NamedNodeMap.__setitem__() sets ownerDocument")
+ self.confirm(a.ownerElement is elem,
+ "NamedNodeMap.__setitem__() sets ownerElement")
+ self.confirm(a.value == "bar",
+ "NamedNodeMap.__setitem__() sets value")
+ self.confirm(a.nodeValue == "bar",
+ "NamedNodeMap.__setitem__() sets nodeValue")
+ elem.unlink()
+ dom.unlink()
+
+ def testNonZero(self):
+ dom = parse(tstfile)
+ self.confirm(dom)# should not be zero
+ dom.appendChild(dom.createComment("foo"))
+ self.confirm(not dom.childNodes[-1].childNodes)
+ dom.unlink()
+
+ def testUnlink(self):
+ dom = parse(tstfile)
+ dom.unlink()
+
+ def testElement(self):
+ dom = Document()
+ dom.appendChild(dom.createElement("abc"))
+ self.confirm(dom.documentElement)
+ dom.unlink()
+
+ def testAAA(self):
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam2")
+ self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
+ a = el.getAttributeNode("spam")
+ self.confirm(a.ownerDocument is dom,
+ "setAttribute() sets ownerDocument")
+ self.confirm(a.ownerElement is dom.documentElement,
+ "setAttribute() sets ownerElement")
+ dom.unlink()
+
+ def testAAB(self):
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam")
+ el.setAttribute("spam", "jam2")
+ self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
+ dom.unlink()
+
+ def testAddAttr(self):
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ child.setAttribute("def", "ghi")
+ self.confirm(child.getAttribute("def") == "ghi")
+ self.confirm(child.attributes["def"].value == "ghi")
+
+ child.setAttribute("jkl", "mno")
+ self.confirm(child.getAttribute("jkl") == "mno")
+ self.confirm(child.attributes["jkl"].value == "mno")
+
+ self.confirm(len(child.attributes) == 2)
+
+ child.setAttribute("def", "newval")
+ self.confirm(child.getAttribute("def") == "newval")
+ self.confirm(child.attributes["def"].value == "newval")
+
+ self.confirm(len(child.attributes) == 2)
+ dom.unlink()
+
+ def testDeleteAttr(self):
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ self.confirm(len(child.attributes) == 0)
+ child.setAttribute("def", "ghi")
+ self.confirm(len(child.attributes) == 1)
+ del child.attributes["def"]
+ self.confirm(len(child.attributes) == 0)
+ dom.unlink()
+
+ def testRemoveAttr(self):
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ child.setAttribute("def", "ghi")
+ self.confirm(len(child.attributes) == 1)
+ child.removeAttribute("def")
+ self.confirm(len(child.attributes) == 0)
+ dom.unlink()
+
+ def testRemoveAttrNS(self):
+ dom = Document()
+ child = dom.appendChild(
+ dom.createElementNS("http://www.python.org", "python:abc"))
+ child.setAttributeNS("http://www.w3.org", "xmlns:python",
+ "http://www.python.org")
+ child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
+ self.confirm(len(child.attributes) == 2)
+ child.removeAttributeNS("http://www.python.org", "abcattr")
+ self.confirm(len(child.attributes) == 1)
+ dom.unlink()
+
+ def testRemoveAttributeNode(self):
+ dom = Document()
+ child = dom.appendChild(dom.createElement("foo"))
+ child.setAttribute("spam", "jam")
+ self.confirm(len(child.attributes) == 1)
+ node = child.getAttributeNode("spam")
+ child.removeAttributeNode(node)
+ self.confirm(len(child.attributes) == 0
+ and child.getAttributeNode("spam") is None)
+ dom.unlink()
+
+ def testChangeAttr(self):
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam")
+ self.confirm(len(el.attributes) == 1)
+ el.setAttribute("spam", "bam")
+ # Set this attribute to be an ID and make sure that doesn't change
+ # when changing the value:
+ el.setIdAttribute("spam")
+ self.confirm(len(el.attributes) == 1
+ and el.attributes["spam"].value == "bam"
+ and el.attributes["spam"].nodeValue == "bam"
+ and el.getAttribute("spam") == "bam"
+ and el.getAttributeNode("spam").isId)
+ el.attributes["spam"] = "ham"
+ self.confirm(len(el.attributes) == 1
+ and el.attributes["spam"].value == "ham"
+ and el.attributes["spam"].nodeValue == "ham"
+ and el.getAttribute("spam") == "ham"
+ and el.attributes["spam"].isId)
+ el.setAttribute("spam2", "bam")
+ self.confirm(len(el.attributes) == 2
+ and el.attributes["spam"].value == "ham"
+ and el.attributes["spam"].nodeValue == "ham"
+ and el.getAttribute("spam") == "ham"
+ and el.attributes["spam2"].value == "bam"
+ and el.attributes["spam2"].nodeValue == "bam"
+ and el.getAttribute("spam2") == "bam")
+ el.attributes["spam2"] = "bam2"
+ self.confirm(len(el.attributes) == 2
+ and el.attributes["spam"].value == "ham"
+ and el.attributes["spam"].nodeValue == "ham"
+ and el.getAttribute("spam") == "ham"
+ and el.attributes["spam2"].value == "bam2"
+ and el.attributes["spam2"].nodeValue == "bam2"
+ and el.getAttribute("spam2") == "bam2")
+ dom.unlink()
+
+ def testGetAttrList(self):
pass
- else:
- print("expected NotSupportedErr when renaming comment node")
- doc.unlink()
-
-def checkWholeText(node, s):
- t = node.wholeText
- confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
-
-def testWholeText():
- doc = parseString("<doc>a</doc>")
- elem = doc.documentElement
- text = elem.childNodes[0]
- assert text.nodeType == Node.TEXT_NODE
-
- checkWholeText(text, "a")
- elem.appendChild(doc.createTextNode("b"))
- checkWholeText(text, "ab")
- elem.insertBefore(doc.createCDATASection("c"), text)
- checkWholeText(text, "cab")
-
- # make sure we don't cross other nodes
- splitter = doc.createComment("comment")
- elem.appendChild(splitter)
- text2 = doc.createTextNode("d")
- elem.appendChild(text2)
- checkWholeText(text, "cab")
- checkWholeText(text2, "d")
-
- x = doc.createElement("x")
- elem.replaceChild(x, splitter)
- splitter = x
- checkWholeText(text, "cab")
- checkWholeText(text2, "d")
-
- x = doc.createProcessingInstruction("y", "z")
- elem.replaceChild(x, splitter)
- splitter = x
- checkWholeText(text, "cab")
- checkWholeText(text2, "d")
-
- elem.removeChild(splitter)
- checkWholeText(text, "cabd")
- checkWholeText(text2, "cabd")
-
-def testPatch1094164 ():
- doc = parseString("<doc><e/></doc>")
- elem = doc.documentElement
- e = elem.firstChild
- confirm(e.parentNode is elem, "Before replaceChild()")
- # Check that replacing a child with itself leaves the tree unchanged
- elem.replaceChild(e, e)
- confirm(e.parentNode is elem, "After replaceChild()")
-
-
-
-def testReplaceWholeText():
- def setup():
- doc = parseString("<doc>a<e/>d</doc>")
+
+ def testGetAttrValues(self): pass
+
+ def testGetAttrLength(self): pass
+
+ def testGetAttribute(self): pass
+
+ def testGetAttributeNS(self): pass
+
+ def testGetAttributeNode(self): pass
+
+ def testGetElementsByTagNameNS(self):
+ d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
+ <minidom:myelem/>
+ </foo>"""
+ dom = parseString(d)
+ elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
+ "myelem")
+ self.confirm(len(elems) == 1
+ and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
+ and elems[0].localName == "myelem"
+ and elems[0].prefix == "minidom"
+ and elems[0].tagName == "minidom:myelem"
+ and elems[0].nodeName == "minidom:myelem")
+ dom.unlink()
+
+ def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
+ lname):
+ nodelist = doc.getElementsByTagNameNS(nsuri, lname)
+ self.confirm(len(nodelist) == 0)
+
+ def testGetEmptyNodeListFromElementsByTagNameNS(self):
+ doc = parseString('<doc/>')
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, 'http://xml.python.org/namespaces/a', 'localname')
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, '*', 'splat')
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, 'http://xml.python.org/namespaces/a', '*')
+
+ doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, "http://xml.python.org/splat", "not-there")
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, "*", "not-there")
+ self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
+ doc, "http://somewhere.else.net/not-there", "e")
+
+ def testElementReprAndStr(self):
+ dom = Document()
+ el = dom.appendChild(dom.createElement("abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ self.confirm(string1 == string2)
+ dom.unlink()
+
+ def testElementReprAndStrUnicode(self):
+ dom = Document()
+ el = dom.appendChild(dom.createElement(u"abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ self.confirm(string1 == string2)
+ dom.unlink()
+
+ def testElementReprAndStrUnicodeNS(self):
+ dom = Document()
+ el = dom.appendChild(
+ dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ self.confirm(string1 == string2)
+ self.confirm(string1.find("slash:abc") != -1)
+ dom.unlink()
+
+ def testAttributeRepr(self):
+ dom = Document()
+ el = dom.appendChild(dom.createElement(u"abc"))
+ node = el.setAttribute("abc", "def")
+ self.confirm(str(node) == repr(node))
+ dom.unlink()
+
+ def testTextNodeRepr(self): pass
+
+ def testWriteXML(self):
+ str = '<?xml version="1.0" ?><a b="c"/>'
+ dom = parseString(str)
+ domstr = dom.toxml()
+ dom.unlink()
+ self.confirm(str == domstr)
+
+ def testAltNewline(self):
+ str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
+ dom = parseString(str)
+ domstr = dom.toprettyxml(newl="\r\n")
+ dom.unlink()
+ self.confirm(domstr == str.replace("\n", "\r\n"))
+
+ def testProcessingInstruction(self):
+ dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
+ pi = dom.documentElement.firstChild
+ self.confirm(pi.target == "mypi"
+ and pi.data == "data \t\n "
+ and pi.nodeName == "mypi"
+ and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
+ and pi.attributes is None
+ and not pi.hasChildNodes()
+ and len(pi.childNodes) == 0
+ and pi.firstChild is None
+ and pi.lastChild is None
+ and pi.localName is None
+ and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
+
+ def testProcessingInstructionRepr(self): pass
+
+ def testTextRepr(self): pass
+
+ def testWriteText(self): pass
+
+ def testDocumentElement(self): pass
+
+ def testTooManyDocumentElements(self):
+ doc = parseString("<doc/>")
+ elem = doc.createElement("extra")
+ # Should raise an exception when adding an extra document element.
+ self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
+ elem.unlink()
+ doc.unlink()
+
+ def testCreateElementNS(self): pass
+
+ def testCreateAttributeNS(self): pass
+
+ def testParse(self): pass
+
+ def testParseString(self): pass
+
+ def testComment(self): pass
+
+ def testAttrListItem(self): pass
+
+ def testAttrListItems(self): pass
+
+ def testAttrListItemNS(self): pass
+
+ def testAttrListKeys(self): pass
+
+ def testAttrListKeysNS(self): pass
+
+ def testRemoveNamedItem(self):
+ doc = parseString("<doc a=''/>")
+ e = doc.documentElement
+ attrs = e.attributes
+ a1 = e.getAttributeNode("a")
+ a2 = attrs.removeNamedItem("a")
+ self.confirm(a1.isSameNode(a2))
+ self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
+
+ def testRemoveNamedItemNS(self):
+ doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
+ e = doc.documentElement
+ attrs = e.attributes
+ a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
+ a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
+ self.confirm(a1.isSameNode(a2))
+ self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
+ "http://xml.python.org/", "b")
+
+ def testAttrListValues(self): pass
+
+ def testAttrListLength(self): pass
+
+ def testAttrList__getitem__(self): pass
+
+ def testAttrList__setitem__(self): pass
+
+ def testSetAttrValueandNodeValue(self): pass
+
+ def testParseElement(self): pass
+
+ def testParseAttributes(self): pass
+
+ def testParseElementNamespaces(self): pass
+
+ def testParseAttributeNamespaces(self): pass
+
+ def testParseProcessingInstructions(self): pass
+
+ def testChildNodes(self): pass
+
+ def testFirstChild(self): pass
+
+ def testHasChildNodes(self): pass
+
+ def _testCloneElementCopiesAttributes(self, e1, e2, test):
+ attrs1 = e1.attributes
+ attrs2 = e2.attributes
+ keys1 = list(attrs1.keys())
+ keys2 = list(attrs2.keys())
+ keys1.sort()
+ keys2.sort()
+ self.confirm(keys1 == keys2, "clone of element has same attribute keys")
+ for i in range(len(keys1)):
+ a1 = attrs1.item(i)
+ a2 = attrs2.item(i)
+ self.confirm(a1 is not a2
+ and a1.value == a2.value
+ and a1.nodeValue == a2.nodeValue
+ and a1.namespaceURI == a2.namespaceURI
+ and a1.localName == a2.localName
+ , "clone of attribute node has proper attribute values")
+ self.confirm(a2.ownerElement is e2,
+ "clone of attribute node correctly owned")
+
+ def _setupCloneElement(self, deep):
+ dom = parseString("<doc attr='value'><foo/></doc>")
+ root = dom.documentElement
+ clone = root.cloneNode(deep)
+ self._testCloneElementCopiesAttributes(
+ root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
+ # mutilate the original so shared data is detected
+ root.tagName = root.nodeName = "MODIFIED"
+ root.setAttribute("attr", "NEW VALUE")
+ root.setAttribute("added", "VALUE")
+ return dom, clone
+
+ def testCloneElementShallow(self):
+ dom, clone = self._setupCloneElement(0)
+ self.confirm(len(clone.childNodes) == 0
+ and clone.childNodes.length == 0
+ and clone.parentNode is None
+ and clone.toxml() == '<doc attr="value"/>'
+ , "testCloneElementShallow")
+ dom.unlink()
+
+ def testCloneElementDeep(self):
+ dom, clone = self._setupCloneElement(1)
+ self.confirm(len(clone.childNodes) == 1
+ and clone.childNodes.length == 1
+ and clone.parentNode is None
+ and clone.toxml() == '<doc attr="value"><foo/></doc>'
+ , "testCloneElementDeep")
+ dom.unlink()
+
+ def testCloneDocumentShallow(self):
+ doc = parseString("<?xml version='1.0'?>\n"
+ "<!-- comment -->"
+ "<!DOCTYPE doc [\n"
+ "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
+ "]>\n"
+ "<doc attr='value'/>")
+ doc2 = doc.cloneNode(0)
+ self.confirm(doc2 is None,
+ "testCloneDocumentShallow:"
+ " shallow cloning of documents makes no sense!")
+
+ def testCloneDocumentDeep(self):
+ doc = parseString("<?xml version='1.0'?>\n"
+ "<!-- comment -->"
+ "<!DOCTYPE doc [\n"
+ "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
+ "]>\n"
+ "<doc attr='value'/>")
+ doc2 = doc.cloneNode(1)
+ self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
+ "testCloneDocumentDeep: document objects not distinct")
+ self.confirm(len(doc.childNodes) == len(doc2.childNodes),
+ "testCloneDocumentDeep: wrong number of Document children")
+ self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
+ "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
+ self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
+ "testCloneDocumentDeep: documentElement owner is not new document")
+ self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
+ "testCloneDocumentDeep: documentElement should not be shared")
+ if doc.doctype is not None:
+ # check the doctype iff the original DOM maintained it
+ self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
+ "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
+ self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
+ self.confirm(not doc.doctype.isSameNode(doc2.doctype))
+
+ def testCloneDocumentTypeDeepOk(self):
+ doctype = create_nonempty_doctype()
+ clone = doctype.cloneNode(1)
+ self.confirm(clone is not None
+ and clone.nodeName == doctype.nodeName
+ and clone.name == doctype.name
+ and clone.publicId == doctype.publicId
+ and clone.systemId == doctype.systemId
+ and len(clone.entities) == len(doctype.entities)
+ and clone.entities.item(len(clone.entities)) is None
+ and len(clone.notations) == len(doctype.notations)
+ and clone.notations.item(len(clone.notations)) is None
+ and len(clone.childNodes) == 0)
+ for i in range(len(doctype.entities)):
+ se = doctype.entities.item(i)
+ ce = clone.entities.item(i)
+ self.confirm((not se.isSameNode(ce))
+ and (not ce.isSameNode(se))
+ and ce.nodeName == se.nodeName
+ and ce.notationName == se.notationName
+ and ce.publicId == se.publicId
+ and ce.systemId == se.systemId
+ and ce.encoding == se.encoding
+ and ce.actualEncoding == se.actualEncoding
+ and ce.version == se.version)
+ for i in range(len(doctype.notations)):
+ sn = doctype.notations.item(i)
+ cn = clone.notations.item(i)
+ self.confirm((not sn.isSameNode(cn))
+ and (not cn.isSameNode(sn))
+ and cn.nodeName == sn.nodeName
+ and cn.publicId == sn.publicId
+ and cn.systemId == sn.systemId)
+
+ def testCloneDocumentTypeDeepNotOk(self):
+ doc = create_doc_with_doctype()
+ clone = doc.doctype.cloneNode(1)
+ self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
+
+ def testCloneDocumentTypeShallowOk(self):
+ doctype = create_nonempty_doctype()
+ clone = doctype.cloneNode(0)
+ self.confirm(clone is not None
+ and clone.nodeName == doctype.nodeName
+ and clone.name == doctype.name
+ and clone.publicId == doctype.publicId
+ and clone.systemId == doctype.systemId
+ and len(clone.entities) == 0
+ and clone.entities.item(0) is None
+ and len(clone.notations) == 0
+ and clone.notations.item(0) is None
+ and len(clone.childNodes) == 0)
+
+ def testCloneDocumentTypeShallowNotOk(self):
+ doc = create_doc_with_doctype()
+ clone = doc.doctype.cloneNode(0)
+ self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
+
+ def check_import_document(self, deep, testName):
+ doc1 = parseString("<doc/>")
+ doc2 = parseString("<doc/>")
+ self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
+
+ def testImportDocumentShallow(self):
+ self.check_import_document(0, "testImportDocumentShallow")
+
+ def testImportDocumentDeep(self):
+ self.check_import_document(1, "testImportDocumentDeep")
+
+ def testImportDocumentTypeShallow(self):
+ src = create_doc_with_doctype()
+ target = create_doc_without_doctype()
+ self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
+ src.doctype, 0)
+
+ def testImportDocumentTypeDeep(self):
+ src = create_doc_with_doctype()
+ target = create_doc_without_doctype()
+ self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
+ src.doctype, 1)
+
+ # Testing attribute clones uses a helper, and should always be deep,
+ # even if the argument to cloneNode is false.
+ def check_clone_attribute(self, deep, testName):
+ doc = parseString("<doc attr='value'/>")
+ attr = doc.documentElement.getAttributeNode("attr")
+ self.failIfEqual(attr, None)
+ clone = attr.cloneNode(deep)
+ self.confirm(not clone.isSameNode(attr))
+ self.confirm(not attr.isSameNode(clone))
+ self.confirm(clone.ownerElement is None,
+ testName + ": ownerElement should be None")
+ self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
+ testName + ": ownerDocument does not match")
+ self.confirm(clone.specified,
+ testName + ": cloned attribute must have specified == True")
+
+ def testCloneAttributeShallow(self):
+ self.check_clone_attribute(0, "testCloneAttributeShallow")
+
+ def testCloneAttributeDeep(self):
+ self.check_clone_attribute(1, "testCloneAttributeDeep")
+
+ def check_clone_pi(self, deep, testName):
+ doc = parseString("<?target data?><doc/>")
+ pi = doc.firstChild
+ self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
+ clone = pi.cloneNode(deep)
+ self.confirm(clone.target == pi.target
+ and clone.data == pi.data)
+
+ def testClonePIShallow(self):
+ self.check_clone_pi(0, "testClonePIShallow")
+
+ def testClonePIDeep(self):
+ self.check_clone_pi(1, "testClonePIDeep")
+
+ def testNormalize(self):
+ doc = parseString("<doc/>")
+ root = doc.documentElement
+ root.appendChild(doc.createTextNode("first"))
+ root.appendChild(doc.createTextNode("second"))
+ self.confirm(len(root.childNodes) == 2
+ and root.childNodes.length == 2,
+ "testNormalize -- preparation")
+ doc.normalize()
+ self.confirm(len(root.childNodes) == 1
+ and root.childNodes.length == 1
+ and root.firstChild is root.lastChild
+ and root.firstChild.data == "firstsecond"
+ , "testNormalize -- result")
+ doc.unlink()
+
+ doc = parseString("<doc/>")
+ root = doc.documentElement
+ root.appendChild(doc.createTextNode(""))
+ doc.normalize()
+ self.confirm(len(root.childNodes) == 0
+ and root.childNodes.length == 0,
+ "testNormalize -- single empty node removed")
+ doc.unlink()
+
+ def testSiblings(self):
+ doc = parseString("<doc><?pi?>text?<elm/></doc>")
+ root = doc.documentElement
+ (pi, text, elm) = root.childNodes
+
+ self.confirm(pi.nextSibling is text and
+ pi.previousSibling is None and
+ text.nextSibling is elm and
+ text.previousSibling is pi and
+ elm.nextSibling is None and
+ elm.previousSibling is text, "testSiblings")
+
+ doc.unlink()
+
+ def testParents(self):
+ doc = parseString(
+ "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
+ root = doc.documentElement
+ elm1 = root.childNodes[0]
+ (elm2a, elm2b) = elm1.childNodes
+ elm3 = elm2b.childNodes[0]
+
+ self.confirm(root.parentNode is doc and
+ elm1.parentNode is root and
+ elm2a.parentNode is elm1 and
+ elm2b.parentNode is elm1 and
+ elm3.parentNode is elm2b, "testParents")
+ doc.unlink()
+
+ def testNodeListItem(self):
+ doc = parseString("<doc><e/><e/></doc>")
+ children = doc.childNodes
+ docelem = children[0]
+ self.confirm(children[0] is children.item(0)
+ and children.item(1) is None
+ and docelem.childNodes.item(0) is docelem.childNodes[0]
+ and docelem.childNodes.item(1) is docelem.childNodes[1]
+ and docelem.childNodes.item(0).childNodes.item(0) is None,
+ "test NodeList.item()")
+ doc.unlink()
+
+ def testSAX2DOM(self):
+ from xml.dom import pulldom
+
+ sax2dom = pulldom.SAX2DOM()
+ sax2dom.startDocument()
+ sax2dom.startElement("doc", {})
+ sax2dom.characters("text")
+ sax2dom.startElement("subelm", {})
+ sax2dom.characters("text")
+ sax2dom.endElement("subelm")
+ sax2dom.characters("text")
+ sax2dom.endElement("doc")
+ sax2dom.endDocument()
+
+ doc = sax2dom.document
+ root = doc.documentElement
+ (text1, elm1, text2) = root.childNodes
+ text3 = elm1.childNodes[0]
+
+ self.confirm(text1.previousSibling is None and
+ text1.nextSibling is elm1 and
+ elm1.previousSibling is text1 and
+ elm1.nextSibling is text2 and
+ text2.previousSibling is elm1 and
+ text2.nextSibling is None and
+ text3.previousSibling is None and
+ text3.nextSibling is None, "testSAX2DOM - siblings")
+
+ self.confirm(root.parentNode is doc and
+ text1.parentNode is root and
+ elm1.parentNode is root and
+ text2.parentNode is root and
+ text3.parentNode is elm1, "testSAX2DOM - parents")
+ doc.unlink()
+
+ def testEncodings(self):
+ doc = parseString('<foo>&#x20ac;</foo>')
+ self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
+ and doc.toxml('utf-8') ==
+ '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
+ and doc.toxml('iso-8859-15') ==
+ '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
+ "testEncodings - encoding EURO SIGN")
+
+ # Verify that character decoding errors throw exceptions instead
+ # of crashing
+ self.assertRaises(UnicodeDecodeError, parseString,
+ '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
+
+ doc.unlink()
+
+ class UserDataHandler:
+ called = 0
+ def handle(self, operation, key, data, src, dst):
+ dst.setUserData(key, data + 1, self)
+ src.setUserData(key, None, None)
+ self.called = 1
+
+ def testUserData(self):
+ dom = Document()
+ n = dom.createElement('e')
+ self.confirm(n.getUserData("foo") is None)
+ n.setUserData("foo", None, None)
+ self.confirm(n.getUserData("foo") is None)
+ n.setUserData("foo", 12, 12)
+ n.setUserData("bar", 13, 13)
+ self.confirm(n.getUserData("foo") == 12)
+ self.confirm(n.getUserData("bar") == 13)
+ n.setUserData("foo", None, None)
+ self.confirm(n.getUserData("foo") is None)
+ self.confirm(n.getUserData("bar") == 13)
+
+ handler = self.UserDataHandler()
+ n.setUserData("bar", 12, handler)
+ c = n.cloneNode(1)
+ self.confirm(handler.called
+ and n.getUserData("bar") is None
+ and c.getUserData("bar") == 13)
+ n.unlink()
+ c.unlink()
+ dom.unlink()
+
+ def checkRenameNodeSharedConstraints(self, doc, node):
+ # Make sure illegal NS usage is detected:
+ self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
+ "http://xml.python.org/ns", "xmlns:foo")
+ doc2 = parseString("<doc/>")
+ self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
+ xml.dom.EMPTY_NAMESPACE, "foo")
+
+ def testRenameAttribute(self):
+ doc = parseString("<doc a='v'/>")
+ elem = doc.documentElement
+ attrmap = elem.attributes
+ attr = elem.attributes['a']
+
+ # Simple renaming
+ attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
+ self.confirm(attr.name == "b"
+ and attr.nodeName == "b"
+ and attr.localName is None
+ and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
+ and attr.prefix is None
+ and attr.value == "v"
+ and elem.getAttributeNode("a") is None
+ and elem.getAttributeNode("b").isSameNode(attr)
+ and attrmap["b"].isSameNode(attr)
+ and attr.ownerDocument.isSameNode(doc)
+ and attr.ownerElement.isSameNode(elem))
+
+ # Rename to have a namespace, no prefix
+ attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
+ self.confirm(attr.name == "c"
+ and attr.nodeName == "c"
+ and attr.localName == "c"
+ and attr.namespaceURI == "http://xml.python.org/ns"
+ and attr.prefix is None
+ and attr.value == "v"
+ and elem.getAttributeNode("a") is None
+ and elem.getAttributeNode("b") is None
+ and elem.getAttributeNode("c").isSameNode(attr)
+ and elem.getAttributeNodeNS(
+ "http://xml.python.org/ns", "c").isSameNode(attr)
+ and attrmap["c"].isSameNode(attr)
+ and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
+
+ # Rename to have a namespace, with prefix
+ attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
+ self.confirm(attr.name == "p:d"
+ and attr.nodeName == "p:d"
+ and attr.localName == "d"
+ and attr.namespaceURI == "http://xml.python.org/ns2"
+ and attr.prefix == "p"
+ and attr.value == "v"
+ and elem.getAttributeNode("a") is None
+ and elem.getAttributeNode("b") is None
+ and elem.getAttributeNode("c") is None
+ and elem.getAttributeNodeNS(
+ "http://xml.python.org/ns", "c") is None
+ and elem.getAttributeNode("p:d").isSameNode(attr)
+ and elem.getAttributeNodeNS(
+ "http://xml.python.org/ns2", "d").isSameNode(attr)
+ and attrmap["p:d"].isSameNode(attr)
+ and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
+
+ # Rename back to a simple non-NS node
+ attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
+ self.confirm(attr.name == "e"
+ and attr.nodeName == "e"
+ and attr.localName is None
+ and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
+ and attr.prefix is None
+ and attr.value == "v"
+ and elem.getAttributeNode("a") is None
+ and elem.getAttributeNode("b") is None
+ and elem.getAttributeNode("c") is None
+ and elem.getAttributeNode("p:d") is None
+ and elem.getAttributeNodeNS(
+ "http://xml.python.org/ns", "c") is None
+ and elem.getAttributeNode("e").isSameNode(attr)
+ and attrmap["e"].isSameNode(attr))
+
+ self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
+ "http://xml.python.org/ns", "xmlns")
+ self.checkRenameNodeSharedConstraints(doc, attr)
+ doc.unlink()
+
+ def testRenameElement(self):
+ doc = parseString("<doc/>")
elem = doc.documentElement
- text1 = elem.firstChild
- text2 = elem.lastChild
- splitter = text1.nextSibling
- elem.insertBefore(doc.createTextNode("b"), splitter)
- elem.insertBefore(doc.createCDATASection("c"), text1)
- return doc, elem, text1, splitter, text2
-
- doc, elem, text1, splitter, text2 = setup()
- text = text1.replaceWholeText("new content")
- checkWholeText(text, "new content")
- checkWholeText(text2, "d")
- confirm(len(elem.childNodes) == 3)
-
- doc, elem, text1, splitter, text2 = setup()
- text = text2.replaceWholeText("new content")
- checkWholeText(text, "new content")
- checkWholeText(text1, "cab")
- confirm(len(elem.childNodes) == 5)
-
- doc, elem, text1, splitter, text2 = setup()
- text = text1.replaceWholeText("")
- checkWholeText(text2, "d")
- confirm(text is None
- and len(elem.childNodes) == 2)
-
-def testSchemaType():
- doc = parseString(
- "<!DOCTYPE doc [\n"
- " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
- " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
- " <!ATTLIST doc id ID #IMPLIED \n"
- " ref IDREF #IMPLIED \n"
- " refs IDREFS #IMPLIED \n"
- " enum (a|b) #IMPLIED \n"
- " ent ENTITY #IMPLIED \n"
- " ents ENTITIES #IMPLIED \n"
- " nm NMTOKEN #IMPLIED \n"
- " nms NMTOKENS #IMPLIED \n"
- " text CDATA #IMPLIED \n"
- " >\n"
- "]><doc id='name' notid='name' text='splat!' enum='b'"
- " ref='name' refs='name name' ent='e1' ents='e1 e2'"
- " nm='123' nms='123 abc' />")
- elem = doc.documentElement
- # We don't want to rely on any specific loader at this point, so
- # just make sure we can get to all the names, and that the
- # DTD-based namespace is right. The names can vary by loader
- # since each supports a different level of DTD information.
- t = elem.schemaType
- confirm(t.name is None
- and t.namespace == xml.dom.EMPTY_NAMESPACE)
- names = "id notid text enum ref refs ent ents nm nms".split()
- for name in names:
- a = elem.getAttributeNode(name)
- t = a.schemaType
- confirm(hasattr(t, "name")
- and t.namespace == xml.dom.EMPTY_NAMESPACE)
-def testSetIdAttribute():
- doc = parseString("<doc a1='v' a2='w'/>")
- e = doc.documentElement
- a1 = e.getAttributeNode("a1")
- a2 = e.getAttributeNode("a2")
- confirm(doc.getElementById("v") is None
- and not a1.isId
- and not a2.isId)
- e.setIdAttribute("a1")
- confirm(e.isSameNode(doc.getElementById("v"))
- and a1.isId
- and not a2.isId)
- e.setIdAttribute("a2")
- confirm(e.isSameNode(doc.getElementById("v"))
- and e.isSameNode(doc.getElementById("w"))
- and a1.isId
- and a2.isId)
- # replace the a1 node; the new node should *not* be an ID
- a3 = doc.createAttribute("a1")
- a3.value = "v"
- e.setAttributeNode(a3)
- confirm(doc.getElementById("v") is None
- and e.isSameNode(doc.getElementById("w"))
- and not a1.isId
- and a2.isId
- and not a3.isId)
- # renaming an attribute should not affect its ID-ness:
- doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
- confirm(e.isSameNode(doc.getElementById("w"))
- and a2.isId)
-
-def testSetIdAttributeNS():
- NS1 = "http://xml.python.org/ns1"
- NS2 = "http://xml.python.org/ns2"
- doc = parseString("<doc"
- " xmlns:ns1='" + NS1 + "'"
- " xmlns:ns2='" + NS2 + "'"
- " ns1:a1='v' ns2:a2='w'/>")
- e = doc.documentElement
- a1 = e.getAttributeNodeNS(NS1, "a1")
- a2 = e.getAttributeNodeNS(NS2, "a2")
- confirm(doc.getElementById("v") is None
- and not a1.isId
- and not a2.isId)
- e.setIdAttributeNS(NS1, "a1")
- confirm(e.isSameNode(doc.getElementById("v"))
- and a1.isId
- and not a2.isId)
- e.setIdAttributeNS(NS2, "a2")
- confirm(e.isSameNode(doc.getElementById("v"))
- and e.isSameNode(doc.getElementById("w"))
- and a1.isId
- and a2.isId)
- # replace the a1 node; the new node should *not* be an ID
- a3 = doc.createAttributeNS(NS1, "a1")
- a3.value = "v"
- e.setAttributeNode(a3)
- confirm(e.isSameNode(doc.getElementById("w")))
- confirm(not a1.isId)
- confirm(a2.isId)
- confirm(not a3.isId)
- confirm(doc.getElementById("v") is None)
- # renaming an attribute should not affect its ID-ness:
- doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
- confirm(e.isSameNode(doc.getElementById("w"))
- and a2.isId)
-
-def testSetIdAttributeNode():
- NS1 = "http://xml.python.org/ns1"
- NS2 = "http://xml.python.org/ns2"
- doc = parseString("<doc"
- " xmlns:ns1='" + NS1 + "'"
- " xmlns:ns2='" + NS2 + "'"
- " ns1:a1='v' ns2:a2='w'/>")
- e = doc.documentElement
- a1 = e.getAttributeNodeNS(NS1, "a1")
- a2 = e.getAttributeNodeNS(NS2, "a2")
- confirm(doc.getElementById("v") is None
- and not a1.isId
- and not a2.isId)
- e.setIdAttributeNode(a1)
- confirm(e.isSameNode(doc.getElementById("v"))
- and a1.isId
- and not a2.isId)
- e.setIdAttributeNode(a2)
- confirm(e.isSameNode(doc.getElementById("v"))
- and e.isSameNode(doc.getElementById("w"))
- and a1.isId
- and a2.isId)
- # replace the a1 node; the new node should *not* be an ID
- a3 = doc.createAttributeNS(NS1, "a1")
- a3.value = "v"
- e.setAttributeNode(a3)
- confirm(e.isSameNode(doc.getElementById("w")))
- confirm(not a1.isId)
- confirm(a2.isId)
- confirm(not a3.isId)
- confirm(doc.getElementById("v") is None)
- # renaming an attribute should not affect its ID-ness:
- doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
- confirm(e.isSameNode(doc.getElementById("w"))
- and a2.isId)
-
-def testPickledDocument():
- doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
- "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
- " 'http://xml.python.org/system' [\n"
- " <!ELEMENT e EMPTY>\n"
- " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
- "]><doc attr='value'> text\n"
- "<?pi sample?> <!-- comment --> <e/> </doc>")
- s = pickle.dumps(doc)
- doc2 = pickle.loads(s)
- stack = [(doc, doc2)]
- while stack:
- n1, n2 = stack.pop()
- confirm(n1.nodeType == n2.nodeType
- and len(n1.childNodes) == len(n2.childNodes)
- and n1.nodeName == n2.nodeName
- and not n1.isSameNode(n2)
- and not n2.isSameNode(n1))
- if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
- len(n1.entities)
- len(n2.entities)
- len(n1.notations)
- len(n2.notations)
- confirm(len(n1.entities) == len(n2.entities)
- and len(n1.notations) == len(n2.notations))
- for i in range(len(n1.notations)):
- no1 = n1.notations.item(i)
- no2 = n1.notations.item(i)
- confirm(no1.name == no2.name
- and no1.publicId == no2.publicId
- and no1.systemId == no2.systemId)
- statck.append((no1, no2))
- for i in range(len(n1.entities)):
- e1 = n1.entities.item(i)
- e2 = n2.entities.item(i)
- confirm(e1.notationName == e2.notationName
- and e1.publicId == e2.publicId
- and e1.systemId == e2.systemId)
- stack.append((e1, e2))
- if n1.nodeType != Node.DOCUMENT_NODE:
- confirm(n1.ownerDocument.isSameNode(doc)
- and n2.ownerDocument.isSameNode(doc2))
- for i in range(len(n1.childNodes)):
- stack.append((n1.childNodes[i], n2.childNodes[i]))
-
-
-# --- MAIN PROGRAM
-
-names = sorted(globals().keys())
-
-failed = []
-
-try:
- Node.allnodes
-except AttributeError:
- # We don't actually have the minidom from the standard library,
- # but are picking up the PyXML version from site-packages.
- def check_allnodes():
- pass
-else:
- def check_allnodes():
- confirm(len(Node.allnodes) == 0,
- "assertion: len(Node.allnodes) == 0")
- if len(Node.allnodes):
- print("Garbage left over:")
- if verbose:
- print(Node.allnodes.items()[0:10])
- else:
- # Don't print specific nodes if repeatable results
- # are needed
- print(len(Node.allnodes))
- Node.allnodes = {}
-
-for name in names:
- if name.startswith("test"):
- func = globals()[name]
- try:
- func()
- check_allnodes()
- except:
- failed.append(name)
- print("Test Failed: ", name)
- sys.stdout.flush()
- traceback.print_exception(*sys.exc_info())
- print(repr(sys.exc_info()[1]))
- Node.allnodes = {}
+ # Simple renaming
+ elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
+ self.confirm(elem.tagName == "a"
+ and elem.nodeName == "a"
+ and elem.localName is None
+ and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
+ and elem.prefix is None
+ and elem.ownerDocument.isSameNode(doc))
+
+ # Rename to have a namespace, no prefix
+ elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
+ self.confirm(elem.tagName == "b"
+ and elem.nodeName == "b"
+ and elem.localName == "b"
+ and elem.namespaceURI == "http://xml.python.org/ns"
+ and elem.prefix is None
+ and elem.ownerDocument.isSameNode(doc))
+
+ # Rename to have a namespace, with prefix
+ elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
+ self.confirm(elem.tagName == "p:c"
+ and elem.nodeName == "p:c"
+ and elem.localName == "c"
+ and elem.namespaceURI == "http://xml.python.org/ns2"
+ and elem.prefix == "p"
+ and elem.ownerDocument.isSameNode(doc))
+
+ # Rename back to a simple non-NS node
+ elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
+ self.confirm(elem.tagName == "d"
+ and elem.nodeName == "d"
+ and elem.localName is None
+ and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
+ and elem.prefix is None
+ and elem.ownerDocument.isSameNode(doc))
+
+ self.checkRenameNodeSharedConstraints(doc, elem)
+ doc.unlink()
+
+ def testRenameOther(self):
+ # We have to create a comment node explicitly since not all DOM
+ # builders used with minidom add comments to the DOM.
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(
+ xml.dom.EMPTY_NAMESPACE, "e", None)
+ node = doc.createComment("comment")
+ self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
+ xml.dom.EMPTY_NAMESPACE, "foo")
+ doc.unlink()
+
+ def testWholeText(self):
+ doc = parseString("<doc>a</doc>")
+ elem = doc.documentElement
+ text = elem.childNodes[0]
+ self.assertEquals(text.nodeType, Node.TEXT_NODE)
+
+ self.checkWholeText(text, "a")
+ elem.appendChild(doc.createTextNode("b"))
+ self.checkWholeText(text, "ab")
+ elem.insertBefore(doc.createCDATASection("c"), text)
+ self.checkWholeText(text, "cab")
+
+ # make sure we don't cross other nodes
+ splitter = doc.createComment("comment")
+ elem.appendChild(splitter)
+ text2 = doc.createTextNode("d")
+ elem.appendChild(text2)
+ self.checkWholeText(text, "cab")
+ self.checkWholeText(text2, "d")
+
+ x = doc.createElement("x")
+ elem.replaceChild(x, splitter)
+ splitter = x
+ self.checkWholeText(text, "cab")
+ self.checkWholeText(text2, "d")
+
+ x = doc.createProcessingInstruction("y", "z")
+ elem.replaceChild(x, splitter)
+ splitter = x
+ self.checkWholeText(text, "cab")
+ self.checkWholeText(text2, "d")
+
+ elem.removeChild(splitter)
+ self.checkWholeText(text, "cabd")
+ self.checkWholeText(text2, "cabd")
+
+ def testPatch1094164(self):
+ doc = parseString("<doc><e/></doc>")
+ elem = doc.documentElement
+ e = elem.firstChild
+ self.confirm(e.parentNode is elem, "Before replaceChild()")
+ # Check that replacing a child with itself leaves the tree unchanged
+ elem.replaceChild(e, e)
+ self.confirm(e.parentNode is elem, "After replaceChild()")
+
+ def testReplaceWholeText(self):
+ def setup():
+ doc = parseString("<doc>a<e/>d</doc>")
+ elem = doc.documentElement
+ text1 = elem.firstChild
+ text2 = elem.lastChild
+ splitter = text1.nextSibling
+ elem.insertBefore(doc.createTextNode("b"), splitter)
+ elem.insertBefore(doc.createCDATASection("c"), text1)
+ return doc, elem, text1, splitter, text2
+
+ doc, elem, text1, splitter, text2 = setup()
+ text = text1.replaceWholeText("new content")
+ self.checkWholeText(text, "new content")
+ self.checkWholeText(text2, "d")
+ self.confirm(len(elem.childNodes) == 3)
+
+ doc, elem, text1, splitter, text2 = setup()
+ text = text2.replaceWholeText("new content")
+ self.checkWholeText(text, "new content")
+ self.checkWholeText(text1, "cab")
+ self.confirm(len(elem.childNodes) == 5)
+
+ doc, elem, text1, splitter, text2 = setup()
+ text = text1.replaceWholeText("")
+ self.checkWholeText(text2, "d")
+ self.confirm(text is None
+ and len(elem.childNodes) == 2)
+
+ def testSchemaType(self):
+ doc = parseString(
+ "<!DOCTYPE doc [\n"
+ " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
+ " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
+ " <!ATTLIST doc id ID #IMPLIED \n"
+ " ref IDREF #IMPLIED \n"
+ " refs IDREFS #IMPLIED \n"
+ " enum (a|b) #IMPLIED \n"
+ " ent ENTITY #IMPLIED \n"
+ " ents ENTITIES #IMPLIED \n"
+ " nm NMTOKEN #IMPLIED \n"
+ " nms NMTOKENS #IMPLIED \n"
+ " text CDATA #IMPLIED \n"
+ " >\n"
+ "]><doc id='name' notid='name' text='splat!' enum='b'"
+ " ref='name' refs='name name' ent='e1' ents='e1 e2'"
+ " nm='123' nms='123 abc' />")
+ elem = doc.documentElement
+ # We don't want to rely on any specific loader at this point, so
+ # just make sure we can get to all the names, and that the
+ # DTD-based namespace is right. The names can vary by loader
+ # since each supports a different level of DTD information.
+ t = elem.schemaType
+ self.confirm(t.name is None
+ and t.namespace == xml.dom.EMPTY_NAMESPACE)
+ names = "id notid text enum ref refs ent ents nm nms".split()
+ for name in names:
+ a = elem.getAttributeNode(name)
+ t = a.schemaType
+ self.confirm(hasattr(t, "name")
+ and t.namespace == xml.dom.EMPTY_NAMESPACE)
+
+ def testSetIdAttribute(self):
+ doc = parseString("<doc a1='v' a2='w'/>")
+ e = doc.documentElement
+ a1 = e.getAttributeNode("a1")
+ a2 = e.getAttributeNode("a2")
+ self.confirm(doc.getElementById("v") is None
+ and not a1.isId
+ and not a2.isId)
+ e.setIdAttribute("a1")
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and a1.isId
+ and not a2.isId)
+ e.setIdAttribute("a2")
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and e.isSameNode(doc.getElementById("w"))
+ and a1.isId
+ and a2.isId)
+ # replace the a1 node; the new node should *not* be an ID
+ a3 = doc.createAttribute("a1")
+ a3.value = "v"
+ e.setAttributeNode(a3)
+ self.confirm(doc.getElementById("v") is None
+ and e.isSameNode(doc.getElementById("w"))
+ and not a1.isId
+ and a2.isId
+ and not a3.isId)
+ # renaming an attribute should not affect its ID-ness:
+ doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
+ self.confirm(e.isSameNode(doc.getElementById("w"))
+ and a2.isId)
+
+ def testSetIdAttributeNS(self):
+ NS1 = "http://xml.python.org/ns1"
+ NS2 = "http://xml.python.org/ns2"
+ doc = parseString("<doc"
+ " xmlns:ns1='" + NS1 + "'"
+ " xmlns:ns2='" + NS2 + "'"
+ " ns1:a1='v' ns2:a2='w'/>")
+ e = doc.documentElement
+ a1 = e.getAttributeNodeNS(NS1, "a1")
+ a2 = e.getAttributeNodeNS(NS2, "a2")
+ self.confirm(doc.getElementById("v") is None
+ and not a1.isId
+ and not a2.isId)
+ e.setIdAttributeNS(NS1, "a1")
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and a1.isId
+ and not a2.isId)
+ e.setIdAttributeNS(NS2, "a2")
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and e.isSameNode(doc.getElementById("w"))
+ and a1.isId
+ and a2.isId)
+ # replace the a1 node; the new node should *not* be an ID
+ a3 = doc.createAttributeNS(NS1, "a1")
+ a3.value = "v"
+ e.setAttributeNode(a3)
+ self.confirm(e.isSameNode(doc.getElementById("w")))
+ self.confirm(not a1.isId)
+ self.confirm(a2.isId)
+ self.confirm(not a3.isId)
+ self.confirm(doc.getElementById("v") is None)
+ # renaming an attribute should not affect its ID-ness:
+ doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
+ self.confirm(e.isSameNode(doc.getElementById("w"))
+ and a2.isId)
+
+ def testSetIdAttributeNode(self):
+ NS1 = "http://xml.python.org/ns1"
+ NS2 = "http://xml.python.org/ns2"
+ doc = parseString("<doc"
+ " xmlns:ns1='" + NS1 + "'"
+ " xmlns:ns2='" + NS2 + "'"
+ " ns1:a1='v' ns2:a2='w'/>")
+ e = doc.documentElement
+ a1 = e.getAttributeNodeNS(NS1, "a1")
+ a2 = e.getAttributeNodeNS(NS2, "a2")
+ self.confirm(doc.getElementById("v") is None
+ and not a1.isId
+ and not a2.isId)
+ e.setIdAttributeNode(a1)
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and a1.isId
+ and not a2.isId)
+ e.setIdAttributeNode(a2)
+ self.confirm(e.isSameNode(doc.getElementById("v"))
+ and e.isSameNode(doc.getElementById("w"))
+ and a1.isId
+ and a2.isId)
+ # replace the a1 node; the new node should *not* be an ID
+ a3 = doc.createAttributeNS(NS1, "a1")
+ a3.value = "v"
+ e.setAttributeNode(a3)
+ self.confirm(e.isSameNode(doc.getElementById("w")))
+ self.confirm(not a1.isId)
+ self.confirm(a2.isId)
+ self.confirm(not a3.isId)
+ self.confirm(doc.getElementById("v") is None)
+ # renaming an attribute should not affect its ID-ness:
+ doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
+ self.confirm(e.isSameNode(doc.getElementById("w"))
+ and a2.isId)
+
+ def testPickledDocument(self):
+ doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
+ "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
+ " 'http://xml.python.org/system' [\n"
+ " <!ELEMENT e EMPTY>\n"
+ " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
+ "]><doc attr='value'> text\n"
+ "<?pi sample?> <!-- comment --> <e/> </doc>")
+ s = pickle.dumps(doc)
+ doc2 = pickle.loads(s)
+ stack = [(doc, doc2)]
+ while stack:
+ n1, n2 = stack.pop()
+ self.confirm(n1.nodeType == n2.nodeType
+ and len(n1.childNodes) == len(n2.childNodes)
+ and n1.nodeName == n2.nodeName
+ and not n1.isSameNode(n2)
+ and not n2.isSameNode(n1))
+ if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
+ len(n1.entities)
+ len(n2.entities)
+ len(n1.notations)
+ len(n2.notations)
+ self.confirm(len(n1.entities) == len(n2.entities)
+ and len(n1.notations) == len(n2.notations))
+ for i in range(len(n1.notations)):
+ no1 = n1.notations.item(i)
+ no2 = n1.notations.item(i)
+ self.confirm(no1.name == no2.name
+ and no1.publicId == no2.publicId
+ and no1.systemId == no2.systemId)
+ statck.append((no1, no2))
+ for i in range(len(n1.entities)):
+ e1 = n1.entities.item(i)
+ e2 = n2.entities.item(i)
+ self.confirm(e1.notationName == e2.notationName
+ and e1.publicId == e2.publicId
+ and e1.systemId == e2.systemId)
+ stack.append((e1, e2))
+ if n1.nodeType != Node.DOCUMENT_NODE:
+ self.confirm(n1.ownerDocument.isSameNode(doc)
+ and n2.ownerDocument.isSameNode(doc2))
+ for i in range(len(n1.childNodes)):
+ stack.append((n1.childNodes[i], n2.childNodes[i]))
+
+def test_main():
+ run_unittest(MinidomTest)
-if failed:
- print("\n\n\n**** Check for failures in these tests:")
- for name in failed:
- print(" " + name)
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py
index 7911a0e..cc8b192 100644
--- a/Lib/test/test_module.py
+++ b/Lib/test/test_module.py
@@ -1,48 +1,61 @@
# Test the module type
-
-from test.test_support import verify, vereq, verbose, TestFailed
+import unittest
+from test.test_support import verbose, run_unittest
import sys
-module = type(sys)
-
-# An uninitialized module has no __dict__ or __name__, and __doc__ is None
-foo = module.__new__(module)
-verify(foo.__dict__ is None)
-try:
- s = foo.__name__
-except AttributeError:
- pass
-else:
- raise TestFailed, "__name__ = %s" % repr(s)
-vereq(foo.__doc__, module.__doc__)
-
-# Regularly initialized module, no docstring
-foo = module("foo")
-vereq(foo.__name__, "foo")
-vereq(foo.__doc__, None)
-vereq(foo.__dict__, {"__name__": "foo", "__doc__": None})
-
-# ASCII docstring
-foo = module("foo", "foodoc")
-vereq(foo.__name__, "foo")
-vereq(foo.__doc__, "foodoc")
-vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc"})
-
-# Unicode docstring
-foo = module("foo", u"foodoc\u1234")
-vereq(foo.__name__, "foo")
-vereq(foo.__doc__, u"foodoc\u1234")
-vereq(foo.__dict__, {"__name__": "foo", "__doc__": u"foodoc\u1234"})
-
-# Reinitialization should not replace the __dict__
-foo.bar = 42
-d = foo.__dict__
-foo.__init__("foo", "foodoc")
-vereq(foo.__name__, "foo")
-vereq(foo.__doc__, "foodoc")
-vereq(foo.bar, 42)
-vereq(foo.__dict__, {"__name__": "foo", "__doc__": "foodoc", "bar": 42})
-verify(foo.__dict__ is d)
-
-if verbose:
- print("All OK")
+ModuleType = type(sys)
+
+class ModuleTests(unittest.TestCase):
+ def test_uninitialized(self):
+ # An uninitialized module has no __dict__ or __name__,
+ # and __doc__ is None
+ foo = ModuleType.__new__(ModuleType)
+ self.failUnless(foo.__dict__ is None)
+ try:
+ s = foo.__name__
+ self.fail("__name__ = %s" % repr(s))
+ except AttributeError:
+ pass
+ self.assertEqual(foo.__doc__, ModuleType.__doc__)
+
+ def test_no_docstring(self):
+ # Regularly initialized module, no docstring
+ foo = ModuleType("foo")
+ self.assertEqual(foo.__name__, "foo")
+ self.assertEqual(foo.__doc__, None)
+ self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None})
+
+ def test_ascii_docstring(self):
+ # ASCII docstring
+ foo = ModuleType("foo", "foodoc")
+ self.assertEqual(foo.__name__, "foo")
+ self.assertEqual(foo.__doc__, "foodoc")
+ self.assertEqual(foo.__dict__,
+ {"__name__": "foo", "__doc__": "foodoc"})
+
+ def test_unicode_docstring(self):
+ # Unicode docstring
+ foo = ModuleType("foo", u"foodoc\u1234")
+ self.assertEqual(foo.__name__, "foo")
+ self.assertEqual(foo.__doc__, u"foodoc\u1234")
+ self.assertEqual(foo.__dict__,
+ {"__name__": "foo", "__doc__": u"foodoc\u1234"})
+
+ def test_reinit(self):
+ # Reinitialization should not replace the __dict__
+ foo = ModuleType("foo", u"foodoc\u1234")
+ foo.bar = 42
+ d = foo.__dict__
+ foo.__init__("foo", "foodoc")
+ self.assertEqual(foo.__name__, "foo")
+ self.assertEqual(foo.__doc__, "foodoc")
+ self.assertEqual(foo.bar, 42)
+ self.assertEqual(foo.__dict__,
+ {"__name__": "foo", "__doc__": "foodoc", "bar": 42})
+ self.failUnless(foo.__dict__ is d)
+
+def test_main():
+ run_unittest(ModuleTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py
index 2ac7061..c5615a8 100644
--- a/Lib/test/test_multibytecodec.py
+++ b/Lib/test/test_multibytecodec.py
@@ -219,13 +219,7 @@ class Test_ISO2022(unittest.TestCase):
myunichr(x).encode('iso_2022_jp', 'ignore')
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test_MultibyteCodec))
- suite.addTest(unittest.makeSuite(Test_IncrementalEncoder))
- suite.addTest(unittest.makeSuite(Test_IncrementalDecoder))
- suite.addTest(unittest.makeSuite(Test_StreamWriter))
- suite.addTest(unittest.makeSuite(Test_ISO2022))
- test_support.run_suite(suite)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_normalization.py b/Lib/test/test_normalization.py
index d890067..b571bdc 100644
--- a/Lib/test/test_normalization.py
+++ b/Lib/test/test_normalization.py
@@ -1,5 +1,6 @@
-from test.test_support import (verbose, TestFailed, TestSkipped, verify,
- open_urlresource)
+from test.test_support import run_unittest, open_urlresource
+import unittest
+
import sys
import os
from unicodedata import normalize
@@ -29,60 +30,67 @@ def unistr(data):
raise RangeError
return u"".join([unichr(x) for x in data])
-def test_main():
- part1_data = {}
- for line in open_urlresource(TESTDATAURL):
- if '#' in line:
- line = line.split('#')[0]
- line = line.strip()
- if not line:
- continue
- if line.startswith("@Part"):
- part = line.split()[0]
- continue
- if part == "@Part3":
- # XXX we don't support PRI #29 yet, so skip these tests for now
- continue
- try:
- c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]]
- except RangeError:
- # Skip unsupported characters;
- # try atleast adding c1 if we are in part1
+class NormalizationTest(unittest.TestCase):
+ def test_main(self):
+ part1_data = {}
+ for line in open_urlresource(TESTDATAURL):
+ if '#' in line:
+ line = line.split('#')[0]
+ line = line.strip()
+ if not line:
+ continue
+ if line.startswith("@Part"):
+ part = line.split()[0]
+ continue
+ if part == "@Part3":
+ # XXX we don't support PRI #29 yet, so skip these tests for now
+ continue
+ try:
+ c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]]
+ except RangeError:
+ # Skip unsupported characters;
+ # try atleast adding c1 if we are in part1
+ if part == "@Part1":
+ try:
+ c1 = unistr(line.split(';')[0])
+ except RangeError:
+ pass
+ else:
+ part1_data[c1] = 1
+ continue
+
+ # Perform tests
+ self.failUnless(c2 == NFC(c1) == NFC(c2) == NFC(c3), line)
+ self.failUnless(c4 == NFC(c4) == NFC(c5), line)
+ self.failUnless(c3 == NFD(c1) == NFD(c2) == NFD(c3), line)
+ self.failUnless(c5 == NFD(c4) == NFD(c5), line)
+ self.failUnless(c4 == NFKC(c1) == NFKC(c2) == \
+ NFKC(c3) == NFKC(c4) == NFKC(c5),
+ line)
+ self.failUnless(c5 == NFKD(c1) == NFKD(c2) == \
+ NFKD(c3) == NFKD(c4) == NFKD(c5),
+ line)
+
+ # Record part 1 data
if part == "@Part1":
- try:
- c1=unistr(line.split(';')[0])
- except RangeError:
- pass
- else:
- part1_data[c1] = 1
- continue
-
- if verbose:
- print(line)
-
- # Perform tests
- verify(c2 == NFC(c1) == NFC(c2) == NFC(c3), line)
- verify(c4 == NFC(c4) == NFC(c5), line)
- verify(c3 == NFD(c1) == NFD(c2) == NFD(c3), line)
- verify(c5 == NFD(c4) == NFD(c5), line)
- verify(c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5),
- line)
- verify(c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5),
- line)
-
- # Record part 1 data
- if part == "@Part1":
- part1_data[c1] = 1
-
- # Perform tests for all other data
- for c in range(sys.maxunicode+1):
- X = unichr(c)
- if X in part1_data:
- continue
- assert X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c
-
- # Check for bug 834676
- normalize('NFC',u'\ud55c\uae00')
+ part1_data[c1] = 1
+
+ # Perform tests for all other data
+ for c in range(sys.maxunicode+1):
+ X = unichr(c)
+ if X in part1_data:
+ continue
+ self.failUnless(X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c)
+
+ def test_bug_834676(self):
+ # Check for bug 834676
+ normalize('NFC', u'\ud55c\uae00')
+
+
+def test_main():
+ # Hit the exception early
+ open_urlresource(TESTDATAURL)
+ run_unittest(NormalizationTest)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py
index 939886d..c6dbf2e 100644
--- a/Lib/test/test_ntpath.py
+++ b/Lib/test/test_ntpath.py
@@ -18,13 +18,14 @@ def tester(fn, wantResult):
tester('ntpath.splitext("foo.ext")', ('foo', '.ext'))
tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext'))
-tester('ntpath.splitext(".ext")', ('', '.ext'))
+tester('ntpath.splitext(".ext")', ('.ext', ''))
tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', ''))
tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', ''))
tester('ntpath.splitext("")', ('', ''))
tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext'))
tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext'))
tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext'))
+tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d'))
tester('ntpath.splitdrive("c:\\foo\\bar")',
('c:', '\\foo\\bar'))
@@ -133,6 +134,13 @@ try:
tester('ntpath.expandvars("${{foo}}")', "baz1}")
tester('ntpath.expandvars("$foo$foo")', "barbar")
tester('ntpath.expandvars("$bar$bar")', "$bar$bar")
+ tester('ntpath.expandvars("%foo% bar")', "bar bar")
+ tester('ntpath.expandvars("%foo%bar")', "barbar")
+ tester('ntpath.expandvars("%foo%%foo%")', "barbar")
+ tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar")
+ tester('ntpath.expandvars("%?bar%")', "%?bar%")
+ tester('ntpath.expandvars("%foo%%bar")', "bar%bar")
+ tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar")
finally:
os.environ.clear()
os.environ.update(oldenv)
@@ -149,6 +157,16 @@ except ImportError:
else:
tester('ntpath.abspath("C:\\")', "C:\\")
+currentdir = os.path.split(os.getcwd())[-1]
+tester('ntpath.relpath("a")', 'a')
+tester('ntpath.relpath(os.path.abspath("a"))', 'a')
+tester('ntpath.relpath("a/b")', 'a\\b')
+tester('ntpath.relpath("../a/b")', '..\\a\\b')
+tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
+tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
+tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
+tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a')
+
if errors:
raise TestFailed(str(errors) + " errors.")
elif verbose:
diff --git a/Lib/test/test_operations.py b/Lib/test/test_operations.py
deleted file mode 100644
index e8b1ae8..0000000
--- a/Lib/test/test_operations.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Python test set -- part 3, built-in operations.
-
-
-print('3. Operations')
-print('XXX Mostly not yet implemented')
-
-
-print('3.1 Dictionary lookups fail if __cmp__() raises an exception')
-
-class BadDictKey:
-
- def __hash__(self):
- return hash(self.__class__)
-
- def __eq__(self, other):
- if isinstance(other, self.__class__):
- print("raising error")
- raise RuntimeError, "gotcha"
- return other
-
-d = {}
-x1 = BadDictKey()
-x2 = BadDictKey()
-d[x1] = 1
-for stmt in ['d[x2] = 2',
- 'z = d[x2]',
- 'x2 in d',
- 'd.get(x2)',
- 'd.setdefault(x2, 42)',
- 'd.pop(x2)',
- 'd.update({x2: 2})']:
- try:
- exec(stmt)
- except RuntimeError:
- print("%s: caught the RuntimeError outside" % (stmt,))
- else:
- print("%s: No exception passed through!" % (stmt,)) # old CPython behavior
-
-
-# Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
-# This version got an assert failure in debug build, infinite loop in
-# release build. Unfortunately, provoking this kind of stuff requires
-# a mix of inserts and deletes hitting exactly the right hash codes in
-# exactly the right order, and I can't think of a randomized approach
-# that would be *likely* to hit a failing case in reasonable time.
-
-d = {}
-for i in range(5):
- d[i] = i
-for i in range(5):
- del d[i]
-for i in range(5, 9): # i==8 was the problem
- d[i] = i
-
-
-# Another dict resizing bug (SF bug #1456209).
-# This caused Segmentation faults or Illegal instructions.
-
-class X(object):
- def __hash__(self):
- return 5
- def __eq__(self, other):
- if resizing:
- d.clear()
- return False
-d = {}
-resizing = False
-d[X()] = 1
-d[X()] = 2
-d[X()] = 3
-d[X()] = 4
-d[X()] = 5
-# now trigger a resize
-resizing = True
-d[9] = 6
-
-print('resize bugs not triggered.')
diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py
index f9519b2..8d70564 100644
--- a/Lib/test/test_operator.py
+++ b/Lib/test/test_operator.py
@@ -143,6 +143,8 @@ class OperatorTestCase(unittest.TestCase):
self.failUnlessRaises(TypeError, operator.delslice, a, None, None)
self.failUnless(operator.delslice(a, 2, 8) is None)
self.assert_(a == [0, 1, 8, 9])
+ operator.delslice(a, 0, test_support.MAX_Py_ssize_t)
+ self.assert_(a == [])
def test_floordiv(self):
self.failUnlessRaises(TypeError, operator.floordiv, 5)
@@ -165,6 +167,8 @@ class OperatorTestCase(unittest.TestCase):
self.failUnlessRaises(TypeError, operator.getslice)
self.failUnlessRaises(TypeError, operator.getslice, a, None, None)
self.failUnless(operator.getslice(a, 4, 6) == [4, 5])
+ b = operator.getslice(a, 0, test_support.MAX_Py_ssize_t)
+ self.assert_(b == a)
def test_indexOf(self):
self.failUnlessRaises(TypeError, operator.indexOf)
@@ -300,6 +304,8 @@ class OperatorTestCase(unittest.TestCase):
self.failUnlessRaises(TypeError, operator.setslice, a, None, None, None)
self.failUnless(operator.setslice(a, 1, 3, [2, 1]) is None)
self.assert_(a == [0, 2, 1, 3])
+ operator.setslice(a, 0, test_support.MAX_Py_ssize_t, [])
+ self.assert_(a == [])
def test_sub(self):
self.failUnlessRaises(TypeError, operator.sub)
diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py
index 6ec2902..88e3a1f 100644
--- a/Lib/test/test_optparse.py
+++ b/Lib/test/test_optparse.py
@@ -1631,18 +1631,8 @@ class TestParseNumber(BaseTest):
"option -l: invalid integer value: '0x12x'")
-def _testclasses():
- mod = sys.modules[__name__]
- return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]
-
-def suite():
- suite = unittest.TestSuite()
- for testclass in _testclasses():
- suite.addTest(unittest.makeSuite(testclass))
- return suite
-
def test_main():
- test_support.run_suite(suite())
+ test_support.run_unittest(__name__)
if __name__ == '__main__':
- unittest.main()
+ test_main()
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index a7fc1da..ed044f6 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -240,6 +240,15 @@ class StatAttributeTests(unittest.TestCase):
os.utime(self.fname, (t1, t1))
self.assertEquals(os.stat(self.fname).st_mtime, t1)
+ def test_1686475(self):
+ # Verify that an open file can be stat'ed
+ try:
+ os.stat(r"c:\pagefile.sys")
+ except WindowsError as e:
+ if e == 2: # file does not exist; cannot run test
+ return
+ self.fail("Could not stat pagefile.sys")
+
from test import mapping_tests
class EnvironTests(mapping_tests.BasicTestMappingProtocol):
@@ -272,75 +281,104 @@ class WalkTests(unittest.TestCase):
from os.path import join
# Build:
- # TESTFN/ a file kid and two directory kids
+ # TESTFN/
+ # TEST1/ a file kid and two directory kids
# tmp1
# SUB1/ a file kid and a directory kid
- # tmp2
- # SUB11/ no kids
- # SUB2/ just a file kid
- # tmp3
- sub1_path = join(test_support.TESTFN, "SUB1")
+ # tmp2
+ # SUB11/ no kids
+ # SUB2/ a file kid and a dirsymlink kid
+ # tmp3
+ # link/ a symlink to TESTFN.2
+ # TEST2/
+ # tmp4 a lone file
+ walk_path = join(test_support.TESTFN, "TEST1")
+ sub1_path = join(walk_path, "SUB1")
sub11_path = join(sub1_path, "SUB11")
- sub2_path = join(test_support.TESTFN, "SUB2")
- tmp1_path = join(test_support.TESTFN, "tmp1")
+ sub2_path = join(walk_path, "SUB2")
+ tmp1_path = join(walk_path, "tmp1")
tmp2_path = join(sub1_path, "tmp2")
tmp3_path = join(sub2_path, "tmp3")
+ link_path = join(sub2_path, "link")
+ t2_path = join(test_support.TESTFN, "TEST2")
+ tmp4_path = join(test_support.TESTFN, "TEST2", "tmp4")
# Create stuff.
os.makedirs(sub11_path)
os.makedirs(sub2_path)
- for path in tmp1_path, tmp2_path, tmp3_path:
+ os.makedirs(t2_path)
+ for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
f = open(path, "w")
f.write("I'm " + path + " and proud of it. Blame test_os.\n")
f.close()
+ if hasattr(os, "symlink"):
+ os.symlink(os.path.abspath(t2_path), link_path)
+ sub2_tree = (sub2_path, ["link"], ["tmp3"])
+ else:
+ sub2_tree = (sub2_path, [], ["tmp3"])
# Walk top-down.
- all = list(os.walk(test_support.TESTFN))
+ all = list(os.walk(walk_path))
self.assertEqual(len(all), 4)
# We can't know which order SUB1 and SUB2 will appear in.
# Not flipped: TESTFN, SUB1, SUB11, SUB2
# flipped: TESTFN, SUB2, SUB1, SUB11
flipped = all[0][1][0] != "SUB1"
all[0][1].sort()
- self.assertEqual(all[0], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"]))
+ self.assertEqual(all[0], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"]))
self.assertEqual(all[2 + flipped], (sub11_path, [], []))
- self.assertEqual(all[3 - 2 * flipped], (sub2_path, [], ["tmp3"]))
+ self.assertEqual(all[3 - 2 * flipped], sub2_tree)
# Prune the search.
all = []
- for root, dirs, files in os.walk(test_support.TESTFN):
+ for root, dirs, files in os.walk(walk_path):
all.append((root, dirs, files))
# Don't descend into SUB1.
if 'SUB1' in dirs:
# Note that this also mutates the dirs we appended to all!
dirs.remove('SUB1')
self.assertEqual(len(all), 2)
- self.assertEqual(all[0], (test_support.TESTFN, ["SUB2"], ["tmp1"]))
- self.assertEqual(all[1], (sub2_path, [], ["tmp3"]))
+ self.assertEqual(all[0], (walk_path, ["SUB2"], ["tmp1"]))
+ self.assertEqual(all[1], sub2_tree)
# Walk bottom-up.
- all = list(os.walk(test_support.TESTFN, topdown=False))
+ all = list(os.walk(walk_path, topdown=False))
self.assertEqual(len(all), 4)
# We can't know which order SUB1 and SUB2 will appear in.
# Not flipped: SUB11, SUB1, SUB2, TESTFN
# flipped: SUB2, SUB11, SUB1, TESTFN
flipped = all[3][1][0] != "SUB1"
all[3][1].sort()
- self.assertEqual(all[3], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"]))
+ self.assertEqual(all[3], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
self.assertEqual(all[flipped], (sub11_path, [], []))
self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"]))
- self.assertEqual(all[2 - 2 * flipped], (sub2_path, [], ["tmp3"]))
+ self.assertEqual(all[2 - 2 * flipped], sub2_tree)
+
+ if hasattr(os, "symlink"):
+ # Walk, following symlinks.
+ for root, dirs, files in os.walk(walk_path, followlinks=True):
+ if root == link_path:
+ self.assertEqual(dirs, [])
+ self.assertEqual(files, ["tmp4"])
+ break
+ else:
+ self.fail("Didn't follow symlink with followlinks=True")
+ def tearDown(self):
# Tear everything down. This is a decent use for bottom-up on
# Windows, which doesn't have a recursive delete command. The
# (not so) subtlety is that rmdir will fail unless the dir's
# kids are removed first, so bottom up is essential.
for root, dirs, files in os.walk(test_support.TESTFN, topdown=False):
for name in files:
- os.remove(join(root, name))
+ os.remove(os.path.join(root, name))
for name in dirs:
- os.rmdir(join(root, name))
+ dirname = os.path.join(root, name)
+ if not os.path.islink(dirname):
+ os.rmdir(dirname)
+ else:
+ os.remove(dirname)
os.rmdir(test_support.TESTFN)
class MakedirTests (unittest.TestCase):
diff --git a/Lib/test/test_ossaudiodev.py b/Lib/test/test_ossaudiodev.py
index 6ca1f74..eb15e88 100644
--- a/Lib/test/test_ossaudiodev.py
+++ b/Lib/test/test_ossaudiodev.py
@@ -1,7 +1,7 @@
from test import test_support
test_support.requires('audio')
-from test.test_support import verbose, findfile, TestFailed, TestSkipped
+from test.test_support import verbose, findfile, TestSkipped
import errno
import fcntl
@@ -12,6 +12,7 @@ import select
import sunaudio
import time
import audioop
+import unittest
# Arggh, AFMT_S16_NE not defined on all platforms -- seems to be a
# fairly recent addition to OSS.
@@ -33,131 +34,143 @@ def read_sound_file(path):
fp.close()
if enc != SND_FORMAT_MULAW_8:
- print("Expect .au file with 8-bit mu-law samples")
- return
+ raise RuntimeError("Expect .au file with 8-bit mu-law samples")
# Convert the data to 16-bit signed.
data = audioop.ulaw2lin(data, 2)
return (data, rate, 16, nchannels)
-# version of assert that still works with -O
-def _assert(expr, message=None):
- if not expr:
- raise AssertionError(message or "assertion failed")
+class OSSAudioDevTests(unittest.TestCase):
-def play_sound_file(data, rate, ssize, nchannels):
- try:
- dsp = ossaudiodev.open('w')
- except IOError as msg:
- if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY):
- raise TestSkipped, msg
- raise TestFailed, msg
-
- # at least check that these methods can be invoked
- dsp.bufsize()
- dsp.obufcount()
- dsp.obuffree()
- dsp.getptr()
- dsp.fileno()
-
- # Make sure the read-only attributes work.
- _assert(dsp.closed is False, "dsp.closed is not False")
- _assert(dsp.name == "/dev/dsp")
- _assert(dsp.mode == 'w', "bad dsp.mode: %r" % dsp.mode)
-
- # And make sure they're really read-only.
- for attr in ('closed', 'name', 'mode'):
+ def play_sound_file(self, data, rate, ssize, nchannels):
try:
- setattr(dsp, attr, 42)
- raise RuntimeError("dsp.%s not read-only" % attr)
- except TypeError:
- pass
-
- # Compute expected running time of sound sample (in seconds).
- expected_time = float(len(data)) / (ssize/8) / nchannels / rate
-
- # set parameters based on .au file headers
- dsp.setparameters(AFMT_S16_NE, nchannels, rate)
- print(("playing test sound file (expected running time: %.2f sec)"
- % expected_time))
- t1 = time.time()
- dsp.write(data)
- dsp.close()
- t2 = time.time()
- elapsed_time = t2 - t1
-
- percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100
- _assert(percent_diff <= 10.0, \
- ("elapsed time (%.2f sec) > 10%% off of expected time (%.2f sec)"
- % (elapsed_time, expected_time)))
-
-def test_setparameters(dsp):
- # Two configurations for testing:
- # config1 (8-bit, mono, 8 kHz) should work on even the most
- # ancient and crufty sound card, but maybe not on special-
- # purpose high-end hardware
- # config2 (16-bit, stereo, 44.1kHz) should work on all but the
- # most ancient and crufty hardware
- config1 = (ossaudiodev.AFMT_U8, 1, 8000)
- config2 = (AFMT_S16_NE, 2, 44100)
-
- for config in [config1, config2]:
- (fmt, channels, rate) = config
- if (dsp.setfmt(fmt) == fmt and
- dsp.channels(channels) == channels and
- dsp.speed(rate) == rate):
- break
- else:
- raise RuntimeError("unable to set audio sampling parameters: "
- "you must have really weird audio hardware")
-
- # setparameters() should be able to set this configuration in
- # either strict or non-strict mode.
- result = dsp.setparameters(fmt, channels, rate, False)
- _assert(result == (fmt, channels, rate),
- "setparameters%r: returned %r" % (config, result))
- result = dsp.setparameters(fmt, channels, rate, True)
- _assert(result == (fmt, channels, rate),
- "setparameters%r: returned %r" % (config, result))
-
-def test_bad_setparameters(dsp):
-
- # Now try some configurations that are presumably bogus: eg. 300
- # channels currently exceeds even Hollywood's ambitions, and
- # negative sampling rate is utter nonsense. setparameters() should
- # accept these in non-strict mode, returning something other than
- # was requested, but should barf in strict mode.
- fmt = AFMT_S16_NE
- rate = 44100
- channels = 2
- for config in [(fmt, 300, rate), # ridiculous nchannels
- (fmt, -5, rate), # impossible nchannels
- (fmt, channels, -50), # impossible rate
- ]:
- (fmt, channels, rate) = config
+ dsp = ossaudiodev.open('w')
+ except IOError as msg:
+ if msg.args[0] in (errno.EACCES, errno.ENOENT,
+ errno.ENODEV, errno.EBUSY):
+ raise TestSkipped(msg)
+ raise
+
+ # at least check that these methods can be invoked
+ dsp.bufsize()
+ dsp.obufcount()
+ dsp.obuffree()
+ dsp.getptr()
+ dsp.fileno()
+
+ # Make sure the read-only attributes work.
+ self.failUnless(dsp.close)
+ self.assertEqual(dsp.name, "/dev/dsp")
+ self.assertEqual(dsp.mode, "w", "bad dsp.mode: %r" % dsp.mode)
+
+ # And make sure they're really read-only.
+ for attr in ('closed', 'name', 'mode'):
+ try:
+ setattr(dsp, attr, 42)
+ except TypeError:
+ pass
+ else:
+ self.fail("dsp.%s not read-only" % attr)
+
+ # Compute expected running time of sound sample (in seconds).
+ expected_time = float(len(data)) / (ssize/8) / nchannels / rate
+
+ # set parameters based on .au file headers
+ dsp.setparameters(AFMT_S16_NE, nchannels, rate)
+ print ("playing test sound file (expected running time: %.2f sec)"
+ % expected_time)
+ t1 = time.time()
+ dsp.write(data)
+ dsp.close()
+ t2 = time.time()
+ elapsed_time = t2 - t1
+
+ percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100
+ self.failUnless(percent_diff <= 10.0,
+ "elapsed time > 10% off of expected time")
+
+ def set_parameters(self, dsp):
+ # Two configurations for testing:
+ # config1 (8-bit, mono, 8 kHz) should work on even the most
+ # ancient and crufty sound card, but maybe not on special-
+ # purpose high-end hardware
+ # config2 (16-bit, stereo, 44.1kHz) should work on all but the
+ # most ancient and crufty hardware
+ config1 = (ossaudiodev.AFMT_U8, 1, 8000)
+ config2 = (AFMT_S16_NE, 2, 44100)
+
+ for config in [config1, config2]:
+ (fmt, channels, rate) = config
+ if (dsp.setfmt(fmt) == fmt and
+ dsp.channels(channels) == channels and
+ dsp.speed(rate) == rate):
+ break
+ else:
+ raise RuntimeError("unable to set audio sampling parameters: "
+ "you must have really weird audio hardware")
+
+ # setparameters() should be able to set this configuration in
+ # either strict or non-strict mode.
result = dsp.setparameters(fmt, channels, rate, False)
- _assert(result != config,
- "setparameters: unexpectedly got requested configuration")
-
+ self.assertEqual(result, (fmt, channels, rate),
+ "setparameters%r: returned %r" % (config, result))
+
+ result = dsp.setparameters(fmt, channels, rate, True)
+ self.assertEqual(result, (fmt, channels, rate),
+ "setparameters%r: returned %r" % (config, result))
+
+ def set_bad_parameters(self, dsp):
+
+ # Now try some configurations that are presumably bogus: eg. 300
+ # channels currently exceeds even Hollywood's ambitions, and
+ # negative sampling rate is utter nonsense. setparameters() should
+ # accept these in non-strict mode, returning something other than
+ # was requested, but should barf in strict mode.
+ fmt = AFMT_S16_NE
+ rate = 44100
+ channels = 2
+ for config in [(fmt, 300, rate), # ridiculous nchannels
+ (fmt, -5, rate), # impossible nchannels
+ (fmt, channels, -50), # impossible rate
+ ]:
+ (fmt, channels, rate) = config
+ result = dsp.setparameters(fmt, channels, rate, False)
+ self.failIfEqual(result, config,
+ "unexpectedly got requested configuration")
+
+ try:
+ result = dsp.setparameters(fmt, channels, rate, True)
+ except ossaudiodev.OSSAudioError as err:
+ pass
+ else:
+ self.fail("expected OSSAudioError")
+
+ def test_playback(self):
+ sound_info = read_sound_file(findfile('audiotest.au'))
+ self.play_sound_file(*sound_info)
+
+ def test_set_parameters(self):
+ dsp = ossaudiodev.open("w")
try:
- result = dsp.setparameters(fmt, channels, rate, True)
- raise AssertionError("setparameters: expected OSSAudioError")
- except ossaudiodev.OSSAudioError as err:
- print("setparameters: got OSSAudioError as expected")
+ self.set_parameters(dsp)
-def test():
- (data, rate, ssize, nchannels) = read_sound_file(findfile('audiotest.au'))
- play_sound_file(data, rate, ssize, nchannels)
+ # Disabled because it fails under Linux 2.6 with ALSA's OSS
+ # emulation layer.
+ #self.set_bad_parameters(dsp)
+ finally:
+ dsp.close()
+ self.failUnless(dsp.closed)
- dsp = ossaudiodev.open("w")
- try:
- test_setparameters(dsp)
-
- # Disabled because it fails under Linux 2.6 with ALSA's OSS
- # emulation layer.
- #test_bad_setparameters(dsp)
- finally:
- dsp.close()
- _assert(dsp.closed is True, "dsp.closed is not True")
-test()
+def test_main():
+ try:
+ dsp = ossaudiodev.open('w')
+ except IOError as msg:
+ if msg.args[0] in (errno.EACCES, errno.ENOENT,
+ errno.ENODEV, errno.EBUSY):
+ raise TestSkipped(msg)
+ raise
+ test_support.run_unittest(__name__)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index 9ed814a..1611e39 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -49,6 +49,11 @@ class TestTranforms(unittest.TestCase):
self.assert_(elem not in asm)
for elem in ('LOAD_CONST', '(None)'):
self.assert_(elem in asm)
+ def f():
+ 'Adding a docstring made this test fail in Py2.5.0'
+ return None
+ self.assert_('LOAD_CONST' in disassemble(f))
+ self.assert_('LOAD_GLOBAL' not in disassemble(f))
def test_while_one(self):
# Skip over: LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP
@@ -195,14 +200,14 @@ class TestTranforms(unittest.TestCase):
# There should be one jump for the while loop.
self.assertEqual(asm.split().count('JUMP_ABSOLUTE'), 1)
self.assertEqual(asm.split().count('RETURN_VALUE'), 2)
-
+
def test_make_function_doesnt_bail(self):
def f():
- def g()->1+1:
+ def g()->1+1:
pass
return g
asm = disassemble(f)
- self.assert_('BINARY_ADD' not in asm)
+ self.assert_('BINARY_ADD' not in asm)
def test_main(verbose=None):
diff --git a/Lib/test/test_popen2.py b/Lib/test/test_popen2.py
index 008a67a..31f22d6 100644
--- a/Lib/test/test_popen2.py
+++ b/Lib/test/test_popen2.py
@@ -1,78 +1,92 @@
#! /usr/bin/env python
-"""Test script for popen2.py
- Christian Tismer
-"""
+"""Test script for popen2.py"""
import os
import sys
-from test.test_support import TestSkipped, reap_children
-
-# popen2 contains its own testing routine
-# which is especially useful to see if open files
-# like stdin can be read successfully by a forked
-# subprocess.
-
-def main():
- print("Test popen2 module:")
- if (sys.platform[:4] == 'beos' or sys.platform[:6] == 'atheos') \
- and __name__ != '__main__':
- # Locks get messed up or something. Generally we're supposed
- # to avoid mixing "posix" fork & exec with native threads, and
- # they may be right about that after all.
- raise TestSkipped, "popen2() doesn't work during import on " + sys.platform
- try:
- from os import popen
- except ImportError:
- # if we don't have os.popen, check that
- # we have os.fork. if not, skip the test
- # (by raising an ImportError)
- from os import fork
- import popen2
- popen2._test()
-
-
-def _test():
- # same test as popen2._test(), but using the os.popen*() API
- print("Testing os module:")
- import popen2
- # When the test runs, there shouldn't be any open pipes
- popen2._cleanup()
- assert not popen2._active, "Active pipes when test starts " + repr([c.cmd for c in popen2._active])
- cmd = "cat"
- teststr = "ab cd\n"
+import unittest
+import popen2
+
+from test.test_support import TestSkipped, run_unittest, reap_children
+
+if sys.platform[:4] == 'beos' or sys.platform[:6] == 'atheos':
+ # Locks get messed up or something. Generally we're supposed
+ # to avoid mixing "posix" fork & exec with native threads, and
+ # they may be right about that after all.
+ raise TestSkipped("popen2() doesn't work on " + sys.platform)
+
+# if we don't have os.popen, check that
+# we have os.fork. if not, skip the test
+# (by raising an ImportError)
+try:
+ from os import popen
+ del popen
+except ImportError:
+ from os import fork
+ del fork
+
+class Popen2Test(unittest.TestCase):
+ cmd = "cat"
if os.name == "nt":
cmd = "more"
+ teststr = "ab cd\n"
# "more" doesn't act the same way across Windows flavors,
# sometimes adding an extra newline at the start or the
# end. So we strip whitespace off both ends for comparison.
expected = teststr.strip()
- print("testing popen2...")
- w, r = os.popen2(cmd)
- w.write(teststr)
- w.close()
- got = r.read()
- if got.strip() != expected:
- raise ValueError("wrote %r read %r" % (teststr, got))
- print("testing popen3...")
- try:
- w, r, e = os.popen3([cmd])
- except:
- w, r, e = os.popen3(cmd)
- w.write(teststr)
- w.close()
- got = r.read()
- if got.strip() != expected:
- raise ValueError("wrote %r read %r" % (teststr, got))
- got = e.read()
- if got:
- raise ValueError("unexpected %r on stderr" % (got,))
- for inst in popen2._active[:]:
- inst.wait()
- popen2._cleanup()
- if popen2._active:
- raise ValueError("_active not empty")
- print("All OK")
-
-main()
-_test()
-reap_children()
+
+ def setUp(self):
+ popen2._cleanup()
+ # When the test runs, there shouldn't be any open pipes
+ self.assertFalse(popen2._active, "Active pipes when test starts" +
+ repr([c.cmd for c in popen2._active]))
+
+ def tearDown(self):
+ for inst in popen2._active:
+ inst.wait()
+ popen2._cleanup()
+ self.assertFalse(popen2._active, "_active not empty")
+ reap_children()
+
+ def validate_output(self, teststr, expected_out, r, w, e=None):
+ w.write(teststr)
+ w.close()
+ got = r.read()
+ self.assertEquals(expected_out, got.strip(), "wrote %r read %r" %
+ (teststr, got))
+
+ if e is not None:
+ got = e.read()
+ self.assertFalse(got, "unexpected %r on stderr" % got)
+
+ def test_popen2(self):
+ r, w = popen2.popen2(self.cmd)
+ self.validate_output(self.teststr, self.expected, r, w)
+
+ def test_popen3(self):
+ if os.name == 'posix':
+ r, w, e = popen2.popen3([self.cmd])
+ self.validate_output(self.teststr, self.expected, r, w, e)
+
+ r, w, e = popen2.popen3(self.cmd)
+ self.validate_output(self.teststr, self.expected, r, w, e)
+
+ def test_os_popen2(self):
+ # same test as test_popen2(), but using the os.popen*() API
+ w, r = os.popen2(self.cmd)
+ self.validate_output(self.teststr, self.expected, r, w)
+
+ def test_os_popen3(self):
+ # same test as test_popen3(), but using the os.popen*() API
+ if os.name == 'posix':
+ w, r, e = os.popen3([self.cmd])
+ self.validate_output(self.teststr, self.expected, r, w, e)
+
+ w, r, e = os.popen3(self.cmd)
+ self.validate_output(self.teststr, self.expected, r, w, e)
+
+
+def test_main():
+ run_unittest(Popen2Test)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py
new file mode 100644
index 0000000..35ff636
--- /dev/null
+++ b/Lib/test/test_poplib.py
@@ -0,0 +1,71 @@
+import socket
+import threading
+import poplib
+import time
+
+from unittest import TestCase
+from test import test_support
+
+
+def server(evt):
+ serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ serv.settimeout(3)
+ serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ serv.bind(("", 9091))
+ serv.listen(5)
+ try:
+ conn, addr = serv.accept()
+ except socket.timeout:
+ pass
+ else:
+ conn.send("+ Hola mundo\n")
+ conn.close()
+ finally:
+ serv.close()
+ evt.set()
+
+class GeneralTests(TestCase):
+
+ def setUp(self):
+ self.evt = threading.Event()
+ threading.Thread(target=server, args=(self.evt,)).start()
+ time.sleep(.1)
+
+ def tearDown(self):
+ self.evt.wait()
+
+ def testBasic(self):
+ # connects
+ pop = poplib.POP3("localhost", 9091)
+ pop.sock.close()
+
+ def testTimeoutDefault(self):
+ # default
+ pop = poplib.POP3("localhost", 9091)
+ self.assertTrue(pop.sock.gettimeout() is None)
+ pop.sock.close()
+
+ def testTimeoutValue(self):
+ # a value
+ pop = poplib.POP3("localhost", 9091, timeout=30)
+ self.assertEqual(pop.sock.gettimeout(), 30)
+ pop.sock.close()
+
+ def testTimeoutNone(self):
+ # None, having other default
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ pop = poplib.POP3("localhost", 9091, timeout=None)
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(pop.sock.gettimeout(), 30)
+ pop.sock.close()
+
+
+
+def test_main(verbose=None):
+ test_support.run_unittest(GeneralTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py
index 20a1fc5..0abf464 100644
--- a/Lib/test/test_posixpath.py
+++ b/Lib/test/test_posixpath.py
@@ -2,15 +2,29 @@ import unittest
from test import test_support
import posixpath, os
-from posixpath import realpath, abspath, join, dirname, basename
+from posixpath import realpath, abspath, join, dirname, basename, relpath
# An absolute path to a temporary filename for testing. We can't rely on TESTFN
# being an absolute path, so we need this.
ABSTFN = abspath(test_support.TESTFN)
+def safe_rmdir(dirname):
+ try:
+ os.rmdir(dirname)
+ except OSError:
+ pass
+
class PosixPathTest(unittest.TestCase):
+ def setUp(self):
+ self.tearDown()
+
+ def tearDown(self):
+ for suffix in ["", "1", "2"]:
+ test_support.unlink(test_support.TESTFN + suffix)
+ safe_rmdir(test_support.TESTFN + suffix)
+
def assertIs(self, a, b):
self.assert_(a is b)
@@ -43,15 +57,27 @@ class PosixPathTest(unittest.TestCase):
self.assertRaises(TypeError, posixpath.split)
- def test_splitext(self):
- self.assertEqual(posixpath.splitext("foo.ext"), ("foo", ".ext"))
- self.assertEqual(posixpath.splitext("/foo/foo.ext"), ("/foo/foo", ".ext"))
- self.assertEqual(posixpath.splitext(".ext"), ("", ".ext"))
- self.assertEqual(posixpath.splitext("/foo.ext/foo"), ("/foo.ext/foo", ""))
- self.assertEqual(posixpath.splitext("foo.ext/"), ("foo.ext/", ""))
- self.assertEqual(posixpath.splitext(""), ("", ""))
- self.assertEqual(posixpath.splitext("foo.bar.ext"), ("foo.bar", ".ext"))
+ def splitextTest(self, path, filename, ext):
+ self.assertEqual(posixpath.splitext(path), (filename, ext))
+ self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
+ self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext))
+ self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext))
+ self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext))
+ self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", ""))
+ def test_splitext(self):
+ self.splitextTest("foo.bar", "foo", ".bar")
+ self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
+ self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
+ self.splitextTest(".csh.rc", ".csh", ".rc")
+ self.splitextTest("nodots", "nodots", "")
+ self.splitextTest(".cshrc", ".cshrc", "")
+ self.splitextTest("...manydots", "...manydots", "")
+ self.splitextTest("...manydots.ext", "...manydots", ".ext")
+ self.splitextTest(".", ".", "")
+ self.splitextTest("..", "..", "")
+ self.splitextTest("........", "........", "")
+ self.splitextTest("", "", "")
self.assertRaises(TypeError, posixpath.splitext)
def test_isabs(self):
@@ -113,7 +139,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.closed:
f.close()
- os.remove(test_support.TESTFN)
def test_time(self):
f = open(test_support.TESTFN, "wb")
@@ -135,7 +160,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.closed:
f.close()
- os.remove(test_support.TESTFN)
def test_islink(self):
self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
@@ -154,14 +178,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.close():
f.close()
- try:
- os.remove(test_support.TESTFN + "1")
- except os.error:
- pass
- try:
- os.remove(test_support.TESTFN + "2")
- except os.error:
- pass
self.assertRaises(TypeError, posixpath.islink)
@@ -176,10 +192,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.close():
f.close()
- try:
- os.remove(test_support.TESTFN)
- except os.error:
- pass
self.assertRaises(TypeError, posixpath.exists)
@@ -197,14 +209,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.close():
f.close()
- try:
- os.remove(test_support.TESTFN)
- except os.error:
- pass
- try:
- os.rmdir(test_support.TESTFN)
- except os.error:
- pass
self.assertRaises(TypeError, posixpath.isdir)
@@ -222,67 +226,51 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.close():
f.close()
- try:
- os.remove(test_support.TESTFN)
- except os.error:
- pass
- try:
- os.rmdir(test_support.TESTFN)
- except os.error:
- pass
self.assertRaises(TypeError, posixpath.isdir)
- def test_samefile(self):
- f = open(test_support.TESTFN + "1", "wb")
- try:
- f.write("foo")
- f.close()
+ def test_samefile(self):
+ f = open(test_support.TESTFN + "1", "wb")
+ try:
+ f.write("foo")
+ f.close()
+ self.assertIs(
+ posixpath.samefile(
+ test_support.TESTFN + "1",
+ test_support.TESTFN + "1"
+ ),
+ True
+ )
+ # If we don't have links, assume that os.stat doesn't return resonable
+ # inode information and thus, that samefile() doesn't work
+ if hasattr(os, "symlink"):
+ os.symlink(
+ test_support.TESTFN + "1",
+ test_support.TESTFN + "2"
+ )
self.assertIs(
posixpath.samefile(
test_support.TESTFN + "1",
- test_support.TESTFN + "1"
+ test_support.TESTFN + "2"
),
True
)
- # If we don't have links, assume that os.stat doesn't return resonable
- # inode information and thus, that samefile() doesn't work
- if hasattr(os, "symlink"):
- os.symlink(
+ os.remove(test_support.TESTFN + "2")
+ f = open(test_support.TESTFN + "2", "wb")
+ f.write("bar")
+ f.close()
+ self.assertIs(
+ posixpath.samefile(
test_support.TESTFN + "1",
test_support.TESTFN + "2"
- )
- self.assertIs(
- posixpath.samefile(
- test_support.TESTFN + "1",
- test_support.TESTFN + "2"
- ),
- True
- )
- os.remove(test_support.TESTFN + "2")
- f = open(test_support.TESTFN + "2", "wb")
- f.write("bar")
- f.close()
- self.assertIs(
- posixpath.samefile(
- test_support.TESTFN + "1",
- test_support.TESTFN + "2"
- ),
- False
- )
- finally:
- if not f.close():
- f.close()
- try:
- os.remove(test_support.TESTFN + "1")
- except os.error:
- pass
- try:
- os.remove(test_support.TESTFN + "2")
- except os.error:
- pass
+ ),
+ False
+ )
+ finally:
+ if not f.close():
+ f.close()
- self.assertRaises(TypeError, posixpath.samefile)
+ self.assertRaises(TypeError, posixpath.samefile)
def test_samestat(self):
f = open(test_support.TESTFN + "1", "wb")
@@ -322,14 +310,6 @@ class PosixPathTest(unittest.TestCase):
finally:
if not f.close():
f.close()
- try:
- os.remove(test_support.TESTFN + "1")
- except os.error:
- pass
- try:
- os.remove(test_support.TESTFN + "2")
- except os.error:
- pass
self.assertRaises(TypeError, posixpath.samestat)
@@ -409,7 +389,7 @@ class PosixPathTest(unittest.TestCase):
os.symlink(ABSTFN+"1", ABSTFN)
self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
finally:
- self.safe_remove(ABSTFN)
+ test_support.unlink(ABSTFN)
def test_realpath_symlink_loops(self):
# Bug #930024, return the path unchanged if we get into an infinite
@@ -429,9 +409,9 @@ class PosixPathTest(unittest.TestCase):
self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
finally:
os.chdir(old_path)
- self.safe_remove(ABSTFN)
- self.safe_remove(ABSTFN+"1")
- self.safe_remove(ABSTFN+"2")
+ test_support.unlink(ABSTFN)
+ test_support.unlink(ABSTFN+"1")
+ test_support.unlink(ABSTFN+"2")
def test_realpath_resolve_parents(self):
# We also need to resolve any symlinks in the parents of a relative
@@ -448,9 +428,9 @@ class PosixPathTest(unittest.TestCase):
self.assertEqual(realpath("a"), ABSTFN + "/y/a")
finally:
os.chdir(old_path)
- self.safe_remove(ABSTFN + "/k")
- self.safe_rmdir(ABSTFN + "/y")
- self.safe_rmdir(ABSTFN)
+ test_support.unlink(ABSTFN + "/k")
+ safe_rmdir(ABSTFN + "/y")
+ safe_rmdir(ABSTFN)
def test_realpath_resolve_before_normalizing(self):
# Bug #990669: Symbolic links should be resolved before we
@@ -474,10 +454,10 @@ class PosixPathTest(unittest.TestCase):
self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), ABSTFN + "/k")
finally:
os.chdir(old_path)
- self.safe_remove(ABSTFN + "/link-y")
- self.safe_rmdir(ABSTFN + "/k/y")
- self.safe_rmdir(ABSTFN + "/k")
- self.safe_rmdir(ABSTFN)
+ test_support.unlink(ABSTFN + "/link-y")
+ safe_rmdir(ABSTFN + "/k/y")
+ safe_rmdir(ABSTFN + "/k")
+ safe_rmdir(ABSTFN)
def test_realpath_resolve_first(self):
# Bug #1213894: The first component of the path, if not absolute,
@@ -495,20 +475,24 @@ class PosixPathTest(unittest.TestCase):
self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
finally:
os.chdir(old_path)
- self.safe_remove(ABSTFN + "link")
- self.safe_rmdir(ABSTFN + "/k")
- self.safe_rmdir(ABSTFN)
-
- # Convenience functions for removing temporary files.
- def pass_os_error(self, func, filename):
- try: func(filename)
- except OSError: pass
+ test_support.unlink(ABSTFN + "link")
+ safe_rmdir(ABSTFN + "/k")
+ safe_rmdir(ABSTFN)
- def safe_remove(self, filename):
- self.pass_os_error(os.remove, filename)
-
- def safe_rmdir(self, dirname):
- self.pass_os_error(os.rmdir, dirname)
+ def test_relpath(self):
+ (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
+ try:
+ curdir = os.path.split(os.getcwd())[-1]
+ self.assertRaises(ValueError, posixpath.relpath, "")
+ self.assertEqual(posixpath.relpath("a"), "a")
+ self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
+ self.assertEqual(posixpath.relpath("a/b"), "a/b")
+ self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
+ self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
+ self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+curdir+"/a/b")
+ self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
+ finally:
+ os.getcwd = real_getcwd
def test_main():
test_support.run_unittest(PosixPathTest)
diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py
index 123c3f8..5ce387b 100644
--- a/Lib/test/test_pty.py
+++ b/Lib/test/test_pty.py
@@ -1,5 +1,9 @@
-import pty, os, sys, signal
-from test.test_support import verbose, TestFailed, TestSkipped
+import pty
+import os
+import sys
+import signal
+from test.test_support import verbose, TestSkipped, run_unittest
+import unittest
TEST_STRING_1 = "I wish to buy a fish license.\n"
TEST_STRING_2 = "For my pet fish, Eric.\n"
@@ -11,6 +15,7 @@ else:
def debug(msg):
pass
+
def normalize_output(data):
# Some operating systems do conversions on newline. We could possibly
# fix that by doing the appropriate termios.tcsetattr()s. I couldn't
@@ -32,116 +37,141 @@ def normalize_output(data):
return data
+
# Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
# because pty code is not too portable.
-
-def test_basic_pty():
- try:
- debug("Calling master_open()")
- master_fd, slave_name = pty.master_open()
- debug("Got master_fd '%d', slave_name '%s'"%(master_fd, slave_name))
- debug("Calling slave_open(%r)"%(slave_name,))
- slave_fd = pty.slave_open(slave_name)
- debug("Got slave_fd '%d'"%slave_fd)
- except OSError:
- # " An optional feature could not be imported " ... ?
- raise TestSkipped, "Pseudo-terminals (seemingly) not functional."
-
- if not os.isatty(slave_fd):
- raise TestFailed, "slave_fd is not a tty"
-
- debug("Writing to slave_fd")
- os.write(slave_fd, TEST_STRING_1)
- s1 = os.read(master_fd, 1024)
- sys.stdout.write(normalize_output(s1))
-
- debug("Writing chunked output")
- os.write(slave_fd, TEST_STRING_2[:5])
- os.write(slave_fd, TEST_STRING_2[5:])
- s2 = os.read(master_fd, 1024)
- sys.stdout.write(normalize_output(s2))
-
- os.close(slave_fd)
- os.close(master_fd)
-
-def handle_sig(sig, frame):
- raise TestFailed, "isatty hung"
-
-# isatty() and close() can hang on some platforms
-# set an alarm before running the test to make sure we don't hang forever
-old_alarm = signal.signal(signal.SIGALRM, handle_sig)
-signal.alarm(10)
-
-try:
- test_basic_pty()
-finally:
- # remove alarm, restore old alarm handler
- signal.alarm(0)
- signal.signal(signal.SIGALRM, old_alarm)
-
-# basic pty passed.
-
-debug("calling pty.fork()")
-pid, master_fd = pty.fork()
-if pid == pty.CHILD:
- # stdout should be connected to a tty.
- if not os.isatty(1):
- debug("Child's fd 1 is not a tty?!")
- os._exit(3)
-
- # After pty.fork(), the child should already be a session leader.
- # (on those systems that have that concept.)
- debug("In child, calling os.setsid()")
- try:
- os.setsid()
- except OSError:
- # Good, we already were session leader
- debug("Good: OSError was raised.")
- pass
- except AttributeError:
- # Have pty, but not setsid() ?
- debug("No setsid() available ?")
- pass
- except:
- # We don't want this error to propagate, escaping the call to
- # os._exit() and causing very peculiar behavior in the calling
- # regrtest.py !
- # Note: could add traceback printing here.
- debug("An unexpected error was raised.")
- os._exit(1)
- else:
- debug("os.setsid() succeeded! (bad!)")
- os._exit(2)
- os._exit(4)
-else:
- debug("Waiting for child (%d) to finish."%pid)
- ##line = os.read(master_fd, 80)
- ##lines = line.replace('\r\n', '\n').split('\n')
- ##if False and lines != ['In child, calling os.setsid()',
- ## 'Good: OSError was raised.', '']:
- ## raise TestFailed("Unexpected output from child: %r" % line)
-
- (pid, status) = os.waitpid(pid, 0)
- res = status >> 8
- debug("Child (%d) exited with status %d (%d)."%(pid, res, status))
- if res == 1:
- raise TestFailed, "Child raised an unexpected exception in os.setsid()"
- elif res == 2:
- raise TestFailed, "pty.fork() failed to make child a session leader."
- elif res == 3:
- raise TestFailed, "Child spawned by pty.fork() did not have a tty as stdout"
- elif res != 4:
- raise TestFailed, "pty.fork() failed for unknown reasons."
-
- ##debug("Reading from master_fd now that the child has exited")
- ##try:
- ## s1 = os.read(master_fd, 1024)
- ##except os.error:
- ## pass
- ##else:
- ## raise TestFailed("Read from master_fd did not raise exception")
-
-
-os.close(master_fd)
-
-# pty.fork() passed.
+class PtyTest(unittest.TestCase):
+ def setUp(self):
+ # isatty() and close() can hang on some platforms. Set an alarm
+ # before running the test to make sure we don't hang forever.
+ self.old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
+ signal.alarm(10)
+
+ def tearDown(self):
+ # remove alarm, restore old alarm handler
+ signal.alarm(0)
+ signal.signal(signal.SIGALRM, self.old_alarm)
+
+ def handle_sig(self, sig, frame):
+ self.fail("isatty hung")
+
+ def test_basic(self):
+ try:
+ debug("Calling master_open()")
+ master_fd, slave_name = pty.master_open()
+ debug("Got master_fd '%d', slave_name '%s'" %
+ (master_fd, slave_name))
+ debug("Calling slave_open(%r)" % (slave_name,))
+ slave_fd = pty.slave_open(slave_name)
+ debug("Got slave_fd '%d'" % slave_fd)
+ except OSError:
+ # " An optional feature could not be imported " ... ?
+ raise TestSkipped, "Pseudo-terminals (seemingly) not functional."
+
+ self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty')
+
+ debug("Writing to slave_fd")
+ os.write(slave_fd, TEST_STRING_1)
+ s1 = os.read(master_fd, 1024)
+ self.assertEquals('I wish to buy a fish license.\n',
+ normalize_output(s1))
+
+ debug("Writing chunked output")
+ os.write(slave_fd, TEST_STRING_2[:5])
+ os.write(slave_fd, TEST_STRING_2[5:])
+ s2 = os.read(master_fd, 1024)
+ self.assertEquals('For my pet fish, Eric.\n', normalize_output(s2))
+
+ os.close(slave_fd)
+ os.close(master_fd)
+
+
+ def test_fork(self):
+ debug("calling pty.fork()")
+ pid, master_fd = pty.fork()
+ if pid == pty.CHILD:
+ # stdout should be connected to a tty.
+ if not os.isatty(1):
+ debug("Child's fd 1 is not a tty?!")
+ os._exit(3)
+
+ # After pty.fork(), the child should already be a session leader.
+ # (on those systems that have that concept.)
+ debug("In child, calling os.setsid()")
+ try:
+ os.setsid()
+ except OSError:
+ # Good, we already were session leader
+ debug("Good: OSError was raised.")
+ pass
+ except AttributeError:
+ # Have pty, but not setsid()?
+ debug("No setsid() available?")
+ pass
+ except:
+ # We don't want this error to propagate, escaping the call to
+ # os._exit() and causing very peculiar behavior in the calling
+ # regrtest.py !
+ # Note: could add traceback printing here.
+ debug("An unexpected error was raised.")
+ os._exit(1)
+ else:
+ debug("os.setsid() succeeded! (bad!)")
+ os._exit(2)
+ os._exit(4)
+ else:
+ debug("Waiting for child (%d) to finish." % pid)
+ # In verbose mode, we have to consume the debug output from the
+ # child or the child will block, causing this test to hang in the
+ # parent's waitpid() call. The child blocks after a
+ # platform-dependent amount of data is written to its fd. On
+ # Linux 2.6, it's 4000 bytes and the child won't block, but on OS
+ # X even the small writes in the child above will block it. Also
+ # on Linux, the read() will throw an OSError (input/output error)
+ # when it tries to read past the end of the buffer but the child's
+ # already exited, so catch and discard those exceptions. It's not
+ # worth checking for EIO.
+ while True:
+ try:
+ data = os.read(master_fd, 80)
+ except OSError:
+ break
+ if not data:
+ break
+ sys.stdout.write(data.replace('\r\n', '\n'))
+
+ ##line = os.read(master_fd, 80)
+ ##lines = line.replace('\r\n', '\n').split('\n')
+ ##if False and lines != ['In child, calling os.setsid()',
+ ## 'Good: OSError was raised.', '']:
+ ## raise TestFailed("Unexpected output from child: %r" % line)
+
+ (pid, status) = os.waitpid(pid, 0)
+ res = status >> 8
+ debug("Child (%d) exited with status %d (%d)." % (pid, res, status))
+ if res == 1:
+ self.fail("Child raised an unexpected exception in os.setsid()")
+ elif res == 2:
+ self.fail("pty.fork() failed to make child a session leader.")
+ elif res == 3:
+ self.fail("Child spawned by pty.fork() did not have a tty as stdout")
+ elif res != 4:
+ self.fail("pty.fork() failed for unknown reasons.")
+
+ ##debug("Reading from master_fd now that the child has exited")
+ ##try:
+ ## s1 = os.read(master_fd, 1024)
+ ##except os.error:
+ ## pass
+ ##else:
+ ## raise TestFailed("Read from master_fd did not raise exception")
+
+ os.close(master_fd)
+
+ # pty.fork() passed.
+
+def test_main(verbose=None):
+ run_unittest(PtyTest)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
index 9772a00..0900d1e 100644
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -1,108 +1,40 @@
-# Very simple test - Parse a file and print what happens
-
# XXX TypeErrors on calling handlers, or on bad return values from a
# handler, are obscure and unhelpful.
+import StringIO
+import unittest
+
import pyexpat
from xml.parsers import expat
-from test.test_support import sortdict, TestFailed
+from test.test_support import sortdict, run_unittest
-class Outputter:
- def StartElementHandler(self, name, attrs):
- print('Start element:\n\t' + repr(name), sortdict(attrs))
- def EndElementHandler(self, name):
- print('End element:\n\t' + repr(name))
-
- def CharacterDataHandler(self, data):
- data = data.strip()
- if data:
- print('Character data:')
- print('\t' + repr(data))
-
- def ProcessingInstructionHandler(self, target, data):
- print('PI:\n\t' + repr(target), repr(data))
-
- def StartNamespaceDeclHandler(self, prefix, uri):
- print('NS decl:\n\t' + repr(prefix), repr(uri))
-
- def EndNamespaceDeclHandler(self, prefix):
- print('End of NS decl:\n\t' + repr(prefix))
-
- def StartCdataSectionHandler(self):
- print('Start of CDATA section')
-
- def EndCdataSectionHandler(self):
- print('End of CDATA section')
-
- def CommentHandler(self, text):
- print('Comment:\n\t' + repr(text))
-
- def NotationDeclHandler(self, *args):
- name, base, sysid, pubid = args
- print('Notation declared:', args)
-
- def UnparsedEntityDeclHandler(self, *args):
- entityName, base, systemId, publicId, notationName = args
- print('Unparsed entity decl:\n\t' + str(args))
-
- def NotStandaloneHandler(self, userData):
- print('Not standalone')
- return 1
-
- def ExternalEntityRefHandler(self, *args):
- context, base, sysId, pubId = args
- print('External entity ref:', args[1:])
- return 1
-
- def DefaultHandler(self, userData):
- pass
-
- def DefaultHandlerExpand(self, userData):
- pass
-
-
-def confirm(ok):
- if ok:
- print("OK.")
- else:
- print("Not OK.")
-
-out = Outputter()
-parser = expat.ParserCreate(namespace_separator='!')
-
-# Test getting/setting returns_unicode
-parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
-parser.returns_unicode = 1; confirm(parser.returns_unicode == 1)
-parser.returns_unicode = 2; confirm(parser.returns_unicode == 1)
-parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
-
-# Test getting/setting ordered_attributes
-parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
-parser.ordered_attributes = 1; confirm(parser.ordered_attributes == 1)
-parser.ordered_attributes = 2; confirm(parser.ordered_attributes == 1)
-parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
-
-# Test getting/setting specified_attributes
-parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
-parser.specified_attributes = 1; confirm(parser.specified_attributes == 1)
-parser.specified_attributes = 2; confirm(parser.specified_attributes == 1)
-parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
-
-HANDLER_NAMES = [
- 'StartElementHandler', 'EndElementHandler',
- 'CharacterDataHandler', 'ProcessingInstructionHandler',
- 'UnparsedEntityDeclHandler', 'NotationDeclHandler',
- 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler',
- 'CommentHandler', 'StartCdataSectionHandler',
- 'EndCdataSectionHandler',
- 'DefaultHandler', 'DefaultHandlerExpand',
- #'NotStandaloneHandler',
- 'ExternalEntityRefHandler'
- ]
-for name in HANDLER_NAMES:
- setattr(parser, name, getattr(out, name))
+class SetAttributeTest(unittest.TestCase):
+ def setUp(self):
+ self.parser = expat.ParserCreate(namespace_separator='!')
+ self.set_get_pairs = [
+ [0, 0],
+ [1, 1],
+ [2, 1],
+ [0, 0],
+ ]
+
+ def test_returns_unicode(self):
+ for x, y in self.set_get_pairs:
+ self.parser.returns_unicode = x
+ self.assertEquals(self.parser.returns_unicode, y)
+
+ def test_ordered_attributes(self):
+ for x, y in self.set_get_pairs:
+ self.parser.ordered_attributes = x
+ self.assertEquals(self.parser.ordered_attributes, y)
+
+ def test_specified_attributes(self):
+ for x, y in self.set_get_pairs:
+ self.parser.specified_attributes = x
+ self.assertEquals(self.parser.specified_attributes, y)
+
data = '''\
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
@@ -126,108 +58,228 @@ data = '''\
</root>
'''
+
# Produce UTF-8 output
-parser.returns_unicode = 0
-try:
- parser.Parse(data, 1)
-except expat.error:
- print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode))
- print('** Line', parser.ErrorLineNumber)
- print('** Column', parser.ErrorColumnNumber)
- print('** Byte', parser.ErrorByteIndex)
-
-# Try the parse again, this time producing Unicode output
-parser = expat.ParserCreate(namespace_separator='!')
-parser.returns_unicode = 1
-
-for name in HANDLER_NAMES:
- setattr(parser, name, getattr(out, name))
-try:
- parser.Parse(data, 1)
-except expat.error:
- print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode))
- print('** Line', parser.ErrorLineNumber)
- print('** Column', parser.ErrorColumnNumber)
- print('** Byte', parser.ErrorByteIndex)
-
-# Try parsing a file
-parser = expat.ParserCreate(namespace_separator='!')
-parser.returns_unicode = 1
-
-for name in HANDLER_NAMES:
- setattr(parser, name, getattr(out, name))
-import StringIO
-file = StringIO.StringIO(data)
-try:
- parser.ParseFile(file)
-except expat.error:
- print('** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode))
- print('** Line', parser.ErrorLineNumber)
- print('** Column', parser.ErrorColumnNumber)
- print('** Byte', parser.ErrorByteIndex)
-
-
-# Tests that make sure we get errors when the namespace_separator value
-# is illegal, and that we don't for good values:
-print()
-print("Testing constructor for proper handling of namespace_separator values:")
-expat.ParserCreate()
-expat.ParserCreate(namespace_separator=None)
-expat.ParserCreate(namespace_separator=' ')
-print("Legal values tested o.k.")
-try:
- expat.ParserCreate(namespace_separator=42)
-except TypeError as e:
- print("Caught expected TypeError:")
- print(e)
-else:
- print("Failed to catch expected TypeError.")
-
-try:
- expat.ParserCreate(namespace_separator='too long')
-except ValueError as e:
- print("Caught expected ValueError:")
- print(e)
-else:
- print("Failed to catch expected ValueError.")
-
-# ParserCreate() needs to accept a namespace_separator of zero length
-# to satisfy the requirements of RDF applications that are required
-# to simply glue together the namespace URI and the localname. Though
-# considered a wart of the RDF specifications, it needs to be supported.
-#
-# See XML-SIG mailing list thread starting with
-# http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
-#
-expat.ParserCreate(namespace_separator='') # too short
-
-# Test the interning machinery.
-p = expat.ParserCreate()
-L = []
-def collector(name, *args):
- L.append(name)
-p.StartElementHandler = collector
-p.EndElementHandler = collector
-p.Parse("<e> <e/> <e></e> </e>", 1)
-tag = L[0]
-if len(L) != 6:
- print("L should only contain 6 entries; found", len(L))
-for entry in L:
- if tag is not entry:
- print("expected L to contain many references to the same string", end=' ')
- print("(it didn't)")
- print("L =", repr(L))
- break
-
-# Tests of the buffer_text attribute.
-import sys
-
-class TextCollector:
- def __init__(self, parser):
+class ParseTest(unittest.TestCase):
+ class Outputter:
+ def __init__(self):
+ self.out = []
+
+ def StartElementHandler(self, name, attrs):
+ self.out.append('Start element: ' + repr(name) + ' ' +
+ sortdict(attrs))
+
+ def EndElementHandler(self, name):
+ self.out.append('End element: ' + repr(name))
+
+ def CharacterDataHandler(self, data):
+ data = data.strip()
+ if data:
+ self.out.append('Character data: ' + repr(data))
+
+ def ProcessingInstructionHandler(self, target, data):
+ self.out.append('PI: ' + repr(target) + ' ' + repr(data))
+
+ def StartNamespaceDeclHandler(self, prefix, uri):
+ self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri))
+
+ def EndNamespaceDeclHandler(self, prefix):
+ self.out.append('End of NS decl: ' + repr(prefix))
+
+ def StartCdataSectionHandler(self):
+ self.out.append('Start of CDATA section')
+
+ def EndCdataSectionHandler(self):
+ self.out.append('End of CDATA section')
+
+ def CommentHandler(self, text):
+ self.out.append('Comment: ' + repr(text))
+
+ def NotationDeclHandler(self, *args):
+ name, base, sysid, pubid = args
+ self.out.append('Notation declared: %s' %(args,))
+
+ def UnparsedEntityDeclHandler(self, *args):
+ entityName, base, systemId, publicId, notationName = args
+ self.out.append('Unparsed entity decl: %s' %(args,))
+
+ def NotStandaloneHandler(self, userData):
+ self.out.append('Not standalone')
+ return 1
+
+ def ExternalEntityRefHandler(self, *args):
+ context, base, sysId, pubId = args
+ self.out.append('External entity ref: %s' %(args[1:],))
+ return 1
+
+ def DefaultHandler(self, userData):
+ pass
+
+ def DefaultHandlerExpand(self, userData):
+ pass
+
+ handler_names = [
+ 'StartElementHandler', 'EndElementHandler',
+ 'CharacterDataHandler', 'ProcessingInstructionHandler',
+ 'UnparsedEntityDeclHandler', 'NotationDeclHandler',
+ 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler',
+ 'CommentHandler', 'StartCdataSectionHandler',
+ 'EndCdataSectionHandler',
+ 'DefaultHandler', 'DefaultHandlerExpand',
+ #'NotStandaloneHandler',
+ 'ExternalEntityRefHandler'
+ ]
+
+ def test_utf8(self):
+
+ out = self.Outputter()
+ parser = expat.ParserCreate(namespace_separator='!')
+ for name in self.handler_names:
+ setattr(parser, name, getattr(out, name))
+ parser.returns_unicode = 0
+ parser.Parse(data, 1)
+
+ # Verify output
+ op = out.out
+ self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'')
+ self.assertEquals(op[1], "Comment: ' comment data '")
+ self.assertEquals(op[2], "Notation declared: ('notation', None, 'notation.jpeg', None)")
+ self.assertEquals(op[3], "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')")
+ self.assertEquals(op[4], "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}")
+ self.assertEquals(op[5], "NS decl: 'myns' 'http://www.python.org/namespace'")
+ self.assertEquals(op[6], "Start element: 'http://www.python.org/namespace!subelement' {}")
+ self.assertEquals(op[7], "Character data: 'Contents of subelements'")
+ self.assertEquals(op[8], "End element: 'http://www.python.org/namespace!subelement'")
+ self.assertEquals(op[9], "End of NS decl: 'myns'")
+ self.assertEquals(op[10], "Start element: 'sub2' {}")
+ self.assertEquals(op[11], 'Start of CDATA section')
+ self.assertEquals(op[12], "Character data: 'contents of CDATA section'")
+ self.assertEquals(op[13], 'End of CDATA section')
+ self.assertEquals(op[14], "End element: 'sub2'")
+ self.assertEquals(op[15], "External entity ref: (None, 'entity.file', None)")
+ self.assertEquals(op[16], "End element: 'root'")
+
+ def test_unicode(self):
+ # Try the parse again, this time producing Unicode output
+ out = self.Outputter()
+ parser = expat.ParserCreate(namespace_separator='!')
+ parser.returns_unicode = 1
+ for name in self.handler_names:
+ setattr(parser, name, getattr(out, name))
+
+ parser.Parse(data, 1)
+
+ op = out.out
+ self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
+ self.assertEquals(op[1], "Comment: u' comment data '")
+ self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
+ self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
+ self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
+ self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
+ self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
+ self.assertEquals(op[7], "Character data: u'Contents of subelements'")
+ self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
+ self.assertEquals(op[9], "End of NS decl: u'myns'")
+ self.assertEquals(op[10], "Start element: u'sub2' {}")
+ self.assertEquals(op[11], 'Start of CDATA section')
+ self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
+ self.assertEquals(op[13], 'End of CDATA section')
+ self.assertEquals(op[14], "End element: u'sub2'")
+ self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
+ self.assertEquals(op[16], "End element: u'root'")
+
+ def test_parse_file(self):
+ # Try parsing a file
+ out = self.Outputter()
+ parser = expat.ParserCreate(namespace_separator='!')
+ parser.returns_unicode = 1
+ for name in self.handler_names:
+ setattr(parser, name, getattr(out, name))
+ file = StringIO.StringIO(data)
+
+ parser.ParseFile(file)
+
+ op = out.out
+ self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
+ self.assertEquals(op[1], "Comment: u' comment data '")
+ self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
+ self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
+ self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
+ self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
+ self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
+ self.assertEquals(op[7], "Character data: u'Contents of subelements'")
+ self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
+ self.assertEquals(op[9], "End of NS decl: u'myns'")
+ self.assertEquals(op[10], "Start element: u'sub2' {}")
+ self.assertEquals(op[11], 'Start of CDATA section')
+ self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
+ self.assertEquals(op[13], 'End of CDATA section')
+ self.assertEquals(op[14], "End element: u'sub2'")
+ self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
+ self.assertEquals(op[16], "End element: u'root'")
+
+
+class NamespaceSeparatorTest(unittest.TestCase):
+ def test_legal(self):
+ # Tests that make sure we get errors when the namespace_separator value
+ # is illegal, and that we don't for good values:
+ expat.ParserCreate()
+ expat.ParserCreate(namespace_separator=None)
+ expat.ParserCreate(namespace_separator=' ')
+
+ def test_illegal(self):
+ try:
+ expat.ParserCreate(namespace_separator=42)
+ self.fail()
+ except TypeError as e:
+ self.assertEquals(str(e),
+ 'ParserCreate() argument 2 must be string or None, not int')
+
+ try:
+ expat.ParserCreate(namespace_separator='too long')
+ self.fail()
+ except ValueError as e:
+ self.assertEquals(str(e),
+ 'namespace_separator must be at most one character, omitted, or None')
+
+ def test_zero_length(self):
+ # ParserCreate() needs to accept a namespace_separator of zero length
+ # to satisfy the requirements of RDF applications that are required
+ # to simply glue together the namespace URI and the localname. Though
+ # considered a wart of the RDF specifications, it needs to be supported.
+ #
+ # See XML-SIG mailing list thread starting with
+ # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
+ #
+ expat.ParserCreate(namespace_separator='') # too short
+
+
+class InterningTest(unittest.TestCase):
+ def test(self):
+ # Test the interning machinery.
+ p = expat.ParserCreate()
+ L = []
+ def collector(name, *args):
+ L.append(name)
+ p.StartElementHandler = collector
+ p.EndElementHandler = collector
+ p.Parse("<e> <e/> <e></e> </e>", 1)
+ tag = L[0]
+ self.assertEquals(len(L), 6)
+ for entry in L:
+ # L should have the same string repeated over and over.
+ self.assertTrue(tag is entry)
+
+
+class BufferTextTest(unittest.TestCase):
+ def setUp(self):
self.stuff = []
+ self.parser = expat.ParserCreate()
+ self.parser.buffer_text = 1
+ self.parser.CharacterDataHandler = self.CharacterDataHandler
def check(self, expected, label):
- require(self.stuff == expected,
+ self.assertEquals(self.stuff, expected,
"%s\nstuff = %r\nexpected = %r"
% (label, self.stuff, map(unicode, expected)))
@@ -238,9 +290,9 @@ class TextCollector:
self.stuff.append("<%s>" % name)
bt = attrs.get("buffer-text")
if bt == "yes":
- parser.buffer_text = 1
+ self.parser.buffer_text = 1
elif bt == "no":
- parser.buffer_text = 0
+ self.parser.buffer_text = 0
def EndElementHandler(self, name):
self.stuff.append("</%s>" % name)
@@ -248,95 +300,91 @@ class TextCollector:
def CommentHandler(self, data):
self.stuff.append("<!--%s-->" % data)
-def require(cond, label):
- # similar to confirm(), but no extraneous output
- if not cond:
- raise TestFailed(label)
-
-def setup(handlers=[]):
- parser = expat.ParserCreate()
- require(not parser.buffer_text,
- "buffer_text not disabled by default")
- parser.buffer_text = 1
- handler = TextCollector(parser)
- parser.CharacterDataHandler = handler.CharacterDataHandler
- for name in handlers:
- setattr(parser, name, getattr(handler, name))
- return parser, handler
-
-parser, handler = setup()
-require(parser.buffer_text,
- "text buffering either not acknowledged or not enabled")
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["123"],
- "buffered text not properly collapsed")
-
-# XXX This test exposes more detail of Expat's text chunking than we
-# XXX like, but it tests what we need to concisely.
-parser, handler = setup(["StartElementHandler"])
-parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
-handler.check(["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
- "buffering control not reacting as expected")
-
-parser, handler = setup()
-parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1)
-handler.check(["1<2> \n 3"],
- "buffered text not properly collapsed")
-
-parser, handler = setup(["StartElementHandler"])
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["<a>", "1", "<b>", "2", "<c>", "3"],
- "buffered text not properly split")
-
-parser, handler = setup(["StartElementHandler", "EndElementHandler"])
-parser.CharacterDataHandler = None
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"],
- "huh?")
-
-parser, handler = setup(["StartElementHandler", "EndElementHandler"])
-parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"],
- "huh?")
-
-parser, handler = setup(["CommentHandler", "EndElementHandler",
- "StartElementHandler"])
-parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"],
- "buffered text not properly split")
-
-parser, handler = setup(["CommentHandler", "EndElementHandler",
- "StartElementHandler"])
-parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
- "<!--abc-->", "4", "<!--def-->", "5", "</a>"],
- "buffered text not properly split")
+ def setHandlers(self, handlers=[]):
+ for name in handlers:
+ setattr(self.parser, name, getattr(self, name))
+
+ def test_default_to_disabled(self):
+ parser = expat.ParserCreate()
+ self.assertFalse(parser.buffer_text)
+
+ def test_buffering_enabled(self):
+ # Make sure buffering is turned on
+ self.assertTrue(self.parser.buffer_text)
+ self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+ self.assertEquals(self.stuff, ['123'],
+ "buffered text not properly collapsed")
+
+ def test1(self):
+ # XXX This test exposes more detail of Expat's text chunking than we
+ # XXX like, but it tests what we need to concisely.
+ self.setHandlers(["StartElementHandler"])
+ self.parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
+ self.assertEquals(self.stuff,
+ ["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
+ "buffering control not reacting as expected")
+
+ def test2(self):
+ self.parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1)
+ self.assertEquals(self.stuff, ["1<2> \n 3"],
+ "buffered text not properly collapsed")
+
+ def test3(self):
+ self.setHandlers(["StartElementHandler"])
+ self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+ self.assertEquals(self.stuff, ["<a>", "1", "<b>", "2", "<c>", "3"],
+ "buffered text not properly split")
+
+ def test4(self):
+ self.setHandlers(["StartElementHandler", "EndElementHandler"])
+ self.parser.CharacterDataHandler = None
+ self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+ self.assertEquals(self.stuff,
+ ["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"])
+
+ def test5(self):
+ self.setHandlers(["StartElementHandler", "EndElementHandler"])
+ self.parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
+ self.assertEquals(self.stuff,
+ ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"])
+
+ def test6(self):
+ self.setHandlers(["CommentHandler", "EndElementHandler",
+ "StartElementHandler"])
+ self.parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
+ self.assertEquals(self.stuff,
+ ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"],
+ "buffered text not properly split")
+
+ def test7(self):
+ self.setHandlers(["CommentHandler", "EndElementHandler",
+ "StartElementHandler"])
+ self.parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
+ self.assertEquals(self.stuff,
+ ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
+ "<!--abc-->", "4", "<!--def-->", "5", "</a>"],
+ "buffered text not properly split")
+
# Test handling of exception from callback:
-def StartElementHandler(name, attrs):
- raise RuntimeError(name)
+class HandlerExceptionTest(unittest.TestCase):
+ def StartElementHandler(self, name, attrs):
+ raise RuntimeError(name)
-parser = expat.ParserCreate()
-parser.StartElementHandler = StartElementHandler
+ def test(self):
+ parser = expat.ParserCreate()
+ parser.StartElementHandler = self.StartElementHandler
+ try:
+ parser.Parse("<a><b><c/></b></a>", 1)
+ self.fail()
+ except RuntimeError as e:
+ self.assertEquals(e.args[0], 'a',
+ "Expected RuntimeError for element 'a', but" + \
+ " found %r" % e.args[0])
-try:
- parser.Parse("<a><b><c/></b></a>", 1)
-except RuntimeError as e:
- if e.args[0] != "a":
- print("Expected RuntimeError for element 'a'; found %r" % e.args[0])
-else:
- print("Expected RuntimeError for 'a'")
# Test Current* members:
-class PositionTest:
-
- def __init__(self, expected_list, parser):
- self.parser = parser
- self.parser.StartElementHandler = self.StartElementHandler
- self.parser.EndElementHandler = self.EndElementHandler
- self.expected_list = expected_list
- self.upto = 0
-
+class PositionTest(unittest.TestCase):
def StartElementHandler(self, name, attrs):
self.check_pos('s')
@@ -348,41 +396,54 @@ class PositionTest:
self.parser.CurrentByteIndex,
self.parser.CurrentLineNumber,
self.parser.CurrentColumnNumber)
- require(self.upto < len(self.expected_list),
- 'too many parser events')
+ self.assertTrue(self.upto < len(self.expected_list),
+ 'too many parser events')
expected = self.expected_list[self.upto]
- require(pos == expected,
- 'expected position %s, got %s' % (expected, pos))
+ self.assertEquals(pos, expected,
+ 'Expected position %s, got position %s' %(pos, expected))
self.upto += 1
+ def test(self):
+ self.parser = expat.ParserCreate()
+ self.parser.StartElementHandler = self.StartElementHandler
+ self.parser.EndElementHandler = self.EndElementHandler
+ self.upto = 0
+ self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
+ ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)]
+
+ xml = '<a>\n <b>\n <c/>\n </b>\n</a>'
+ self.parser.Parse(xml, 1)
+
+
+class sf1296433Test(unittest.TestCase):
+ def test_parse_only_xml_data(self):
+ # http://python.org/sf/1296433
+ #
+ xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
+ # this one doesn't crash
+ #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
-parser = expat.ParserCreate()
-handler = PositionTest([('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
- ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)],
- parser)
-parser.Parse('''<a>
- <b>
- <c/>
- </b>
-</a>''', 1)
+ class SpecificException(Exception):
+ pass
+ def handler(text):
+ raise SpecificException
-def test_parse_only_xml_data():
- # http://python.org/sf/1296433
- #
- xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
- # this one doesn't crash
- #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = handler
- def handler(text):
- raise Exception
+ self.assertRaises(Exception, parser.Parse, xml)
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = handler
- try:
- parser.Parse(xml)
- except:
- pass
+def test_main():
+ run_unittest(SetAttributeTest,
+ ParseTest,
+ NamespaceSeparatorTest,
+ InterningTest,
+ BufferTextTest,
+ HandlerExceptionTest,
+ PositionTest,
+ sf1296433Test)
-test_parse_only_xml_data()
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index bca2ecf..13fa413 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1,7 +1,7 @@
import sys
sys.path = ['.'] + sys.path
-from test.test_support import verbose, run_unittest
+from test.test_support import verbose, run_unittest, guard_warnings_filter
import re
from re import Scanner
import sys, os, traceback
@@ -418,6 +418,12 @@ class ReTests(unittest.TestCase):
pass # cPickle not found -- skip it
else:
self.pickle_test(cPickle)
+ # old pickles expect the _compile() reconstructor in sre module
+ import warnings
+ with guard_warnings_filter():
+ warnings.filterwarnings("ignore", "The sre module is deprecated",
+ DeprecationWarning)
+ from sre import _compile
def pickle_test(self, pickle):
oldpat = re.compile('a(?:b|(c|e){1,2}?|d)+?(.)')
@@ -599,6 +605,13 @@ class ReTests(unittest.TestCase):
self.assertEqual(next(iter).span(), (4, 4))
self.assertRaises(StopIteration, next, iter)
+ def test_empty_array(self):
+ # SF buf 1647541
+ import array
+ for typecode in 'cbBuhHiIlLfd':
+ a = array.array(typecode)
+ self.assertEqual(re.compile("bla").match(a), None)
+ self.assertEqual(re.compile("").match(a).groups(), ())
def run_re_tests():
from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR
diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py
index 6a23b22..666d00a 100644
--- a/Lib/test/test_robotparser.py
+++ b/Lib/test/test_robotparser.py
@@ -135,8 +135,8 @@ bad = [] # Bug report says "/" should be denied, but that is not in the RFC
RobotTest(7, doc, good, bad)
def test_main():
- test_support.run_suite(tests)
+ test_support.run_unittest(tests)
if __name__=='__main__':
test_support.Verbose = 1
- test_support.run_suite(tests)
+ test_main()
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 5b071dd..0d76cbb 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -13,26 +13,66 @@ from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
from xml.sax.expatreader import create_parser
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
from cStringIO import StringIO
-from test.test_support import verify, verbose, TestFailed, findfile
+from test.test_support import findfile, run_unittest
+import unittest
import os
-# ===== Utilities
-
-tests = 0
-failures = []
-
-def confirm(outcome, name):
- global tests
-
- tests = tests + 1
- if outcome:
- if verbose:
- print("Passed", name)
- else:
- failures.append(name)
+ns_uri = "http://www.python.org/xml-ns/saxtest/"
-def test_make_parser2():
- try:
+class XmlTestBase(unittest.TestCase):
+ def verify_empty_attrs(self, attrs):
+ self.assertRaises(KeyError, attrs.getValue, "attr")
+ self.assertRaises(KeyError, attrs.getValueByQName, "attr")
+ self.assertRaises(KeyError, attrs.getNameByQName, "attr")
+ self.assertRaises(KeyError, attrs.getQNameByName, "attr")
+ self.assertRaises(KeyError, attrs.__getitem__, "attr")
+ self.assertEquals(attrs.getLength(), 0)
+ self.assertEquals(attrs.getNames(), [])
+ self.assertEquals(attrs.getQNames(), [])
+ self.assertEquals(len(attrs), 0)
+ self.assertFalse("attr" in attrs)
+ self.assertEquals(list(attrs.keys()), [])
+ self.assertEquals(attrs.get("attrs"), None)
+ self.assertEquals(attrs.get("attrs", 25), 25)
+ self.assertEquals(list(attrs.items()), [])
+ self.assertEquals(list(attrs.values()), [])
+
+ def verify_empty_nsattrs(self, attrs):
+ self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
+ self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
+ self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
+ self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
+ self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
+ self.assertEquals(attrs.getLength(), 0)
+ self.assertEquals(attrs.getNames(), [])
+ self.assertEquals(attrs.getQNames(), [])
+ self.assertEquals(len(attrs), 0)
+ self.assertFalse((ns_uri, "attr") in attrs)
+ self.assertEquals(list(attrs.keys()), [])
+ self.assertEquals(attrs.get((ns_uri, "attr")), None)
+ self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25)
+ self.assertEquals(list(attrs.items()), [])
+ self.assertEquals(list(attrs.values()), [])
+
+ def verify_attrs_wattr(self, attrs):
+ self.assertEquals(attrs.getLength(), 1)
+ self.assertEquals(attrs.getNames(), ["attr"])
+ self.assertEquals(attrs.getQNames(), ["attr"])
+ self.assertEquals(len(attrs), 1)
+ self.assertTrue("attr" in attrs)
+ self.assertEquals(list(attrs.keys()), ["attr"])
+ self.assertEquals(attrs.get("attr"), "val")
+ self.assertEquals(attrs.get("attr", 25), "val")
+ self.assertEquals(list(attrs.items()), [("attr", "val")])
+ self.assertEquals(list(attrs.values()), ["val"])
+ self.assertEquals(attrs.getValue("attr"), "val")
+ self.assertEquals(attrs.getValueByQName("attr"), "val")
+ self.assertEquals(attrs.getNameByQName("attr"), "attr")
+ self.assertEquals(attrs["attr"], "val")
+ self.assertEquals(attrs.getQNameByName("attr"), "attr")
+
+class MakeParserTest(unittest.TestCase):
+ def test_make_parser2(self):
# Creating parsers several times in a row should succeed.
# Testing this because there have been failures of this kind
# before.
@@ -48,10 +88,6 @@ def test_make_parser2():
p = make_parser()
from xml.sax import make_parser
p = make_parser()
- except:
- return 0
- else:
- return p
# ===========================================================================
@@ -60,215 +96,214 @@ def test_make_parser2():
#
# ===========================================================================
-# ===== escape
-
-def test_escape_basic():
- return escape("Donald Duck & Co") == "Donald Duck &amp; Co"
+class SaxutilsTest(unittest.TestCase):
+ # ===== escape
+ def test_escape_basic(self):
+ self.assertEquals(escape("Donald Duck & Co"), "Donald Duck &amp; Co")
-def test_escape_all():
- return escape("<Donald Duck & Co>") == "&lt;Donald Duck &amp; Co&gt;"
+ def test_escape_all(self):
+ self.assertEquals(escape("<Donald Duck & Co>"),
+ "&lt;Donald Duck &amp; Co&gt;")
-def test_escape_extra():
- return escape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
+ def test_escape_extra(self):
+ self.assertEquals(escape("Hei på deg", {"å" : "&aring;"}),
+ "Hei p&aring; deg")
-# ===== unescape
+ # ===== unescape
+ def test_unescape_basic(self):
+ self.assertEquals(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
-def test_unescape_basic():
- return unescape("Donald Duck &amp; Co") == "Donald Duck & Co"
+ def test_unescape_all(self):
+ self.assertEquals(unescape("&lt;Donald Duck &amp; Co&gt;"),
+ "<Donald Duck & Co>")
-def test_unescape_all():
- return unescape("&lt;Donald Duck &amp; Co&gt;") == "<Donald Duck & Co>"
+ def test_unescape_extra(self):
+ self.assertEquals(unescape("Hei på deg", {"å" : "&aring;"}),
+ "Hei p&aring; deg")
-def test_unescape_extra():
- return unescape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
+ def test_unescape_amp_extra(self):
+ self.assertEquals(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
-def test_unescape_amp_extra():
- return unescape("&amp;foo;", {"&foo;": "splat"}) == "&foo;"
+ # ===== quoteattr
+ def test_quoteattr_basic(self):
+ self.assertEquals(quoteattr("Donald Duck & Co"),
+ '"Donald Duck &amp; Co"')
-# ===== quoteattr
+ def test_single_quoteattr(self):
+ self.assertEquals(quoteattr('Includes "double" quotes'),
+ '\'Includes "double" quotes\'')
-def test_quoteattr_basic():
- return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"'
+ def test_double_quoteattr(self):
+ self.assertEquals(quoteattr("Includes 'single' quotes"),
+ "\"Includes 'single' quotes\"")
-def test_single_quoteattr():
- return (quoteattr('Includes "double" quotes')
- == '\'Includes "double" quotes\'')
+ def test_single_double_quoteattr(self):
+ self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"),
+ "\"Includes 'single' and &quot;double&quot; quotes\"")
-def test_double_quoteattr():
- return (quoteattr("Includes 'single' quotes")
- == "\"Includes 'single' quotes\"")
-
-def test_single_double_quoteattr():
- return (quoteattr("Includes 'single' and \"double\" quotes")
- == "\"Includes 'single' and &quot;double&quot; quotes\"")
-
-# ===== make_parser
-
-def test_make_parser():
- try:
+ # ===== make_parser
+ def test_make_parser(self):
# Creating a parser should succeed - it should fall back
# to the expatreader
p = make_parser(['xml.parsers.no_such_parser'])
- except:
- return 0
- else:
- return p
# ===== XMLGenerator
start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
-def test_xmlgen_basic():
- result = StringIO()
- gen = XMLGenerator(result)
- gen.startDocument()
- gen.startElement("doc", {})
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + "<doc></doc>"
-
-def test_xmlgen_content():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startElement("doc", {})
- gen.characters("huhei")
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + "<doc>huhei</doc>"
-
-def test_xmlgen_pi():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.processingInstruction("test", "data")
- gen.startElement("doc", {})
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + "<?test data?><doc></doc>"
-
-def test_xmlgen_content_escape():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startElement("doc", {})
- gen.characters("<huhei&")
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + "<doc>&lt;huhei&amp;</doc>"
-
-def test_xmlgen_attr_escape():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startElement("doc", {"a": '"'})
- gen.startElement("e", {"a": "'"})
- gen.endElement("e")
- gen.startElement("e", {"a": "'\""})
- gen.endElement("e")
- gen.startElement("e", {"a": "\n\r\t"})
- gen.endElement("e")
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + ("<doc a='\"'><e a=\"'\"></e>"
- "<e a=\"'&quot;\"></e>"
- "<e a=\"&#10;&#13;&#9;\"></e></doc>")
-
-def test_xmlgen_ignorable():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startElement("doc", {})
- gen.ignorableWhitespace(" ")
- gen.endElement("doc")
- gen.endDocument()
-
- return result.getvalue() == start + "<doc> </doc>"
+class XmlgenTest(unittest.TestCase):
+ def test_xmlgen_basic(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start + "<doc></doc>")
+
+ def test_xmlgen_content(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.characters("huhei")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start + "<doc>huhei</doc>")
+
+ def test_xmlgen_pi(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.processingInstruction("test", "data")
+ gen.startElement("doc", {})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start + "<?test data?><doc></doc>")
+
+ def test_xmlgen_content_escape(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.characters("<huhei&")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(),
+ start + "<doc>&lt;huhei&amp;</doc>")
+
+ def test_xmlgen_attr_escape(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {"a": '"'})
+ gen.startElement("e", {"a": "'"})
+ gen.endElement("e")
+ gen.startElement("e", {"a": "'\""})
+ gen.endElement("e")
+ gen.startElement("e", {"a": "\n\r\t"})
+ gen.endElement("e")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start +
+ ("<doc a='\"'><e a=\"'\"></e>"
+ "<e a=\"'&quot;\"></e>"
+ "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
+
+ def test_xmlgen_ignorable(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.ignorableWhitespace(" ")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start + "<doc> </doc>")
+
+ def test_xmlgen_ns(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startPrefixMapping("ns1", ns_uri)
+ gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
+ # add an unqualified name
+ gen.startElementNS((None, "udoc"), None, {})
+ gen.endElementNS((None, "udoc"), None)
+ gen.endElementNS((ns_uri, "doc"), "ns1:doc")
+ gen.endPrefixMapping("ns1")
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start + \
+ ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
+ ns_uri))
-ns_uri = "http://www.python.org/xml-ns/saxtest/"
+ def test_1463026_1(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
-def test_xmlgen_ns():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startPrefixMapping("ns1", ns_uri)
- gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
- # add an unqualified name
- gen.startElementNS((None, "udoc"), None, {})
- gen.endElementNS((None, "udoc"), None)
- gen.endElementNS((ns_uri, "doc"), "ns1:doc")
- gen.endPrefixMapping("ns1")
- gen.endDocument()
-
- return result.getvalue() == start + \
- ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
- ns_uri)
-
-def test_1463026_1():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
- gen.endElementNS((None, 'a'), 'a')
- gen.endDocument()
-
- return result.getvalue() == start+'<a b="c"></a>'
-
-def test_1463026_2():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startPrefixMapping(None, 'qux')
- gen.startElementNS(('qux', 'a'), 'a', {})
- gen.endElementNS(('qux', 'a'), 'a')
- gen.endPrefixMapping(None)
- gen.endDocument()
-
- return result.getvalue() == start+'<a xmlns="qux"></a>'
-
-def test_1463026_3():
- result = StringIO()
- gen = XMLGenerator(result)
-
- gen.startDocument()
- gen.startPrefixMapping('my', 'qux')
- gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
- gen.endElementNS(('qux', 'a'), 'a')
- gen.endPrefixMapping('my')
- gen.endDocument()
-
- return result.getvalue() == start+'<my:a xmlns:my="qux" b="c"></my:a>'
-
-# ===== Xmlfilterbase
-
-def test_filter_basic():
- result = StringIO()
- gen = XMLGenerator(result)
- filter = XMLFilterBase()
- filter.setContentHandler(gen)
-
- filter.startDocument()
- filter.startElement("doc", {})
- filter.characters("content")
- filter.ignorableWhitespace(" ")
- filter.endElement("doc")
- filter.endDocument()
-
- return result.getvalue() == start + "<doc>content </doc>"
+ gen.startDocument()
+ gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
+ gen.endElementNS((None, 'a'), 'a')
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start+'<a b="c"></a>')
+
+ def test_1463026_2(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startPrefixMapping(None, 'qux')
+ gen.startElementNS(('qux', 'a'), 'a', {})
+ gen.endElementNS(('qux', 'a'), 'a')
+ gen.endPrefixMapping(None)
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(), start+'<a xmlns="qux"></a>')
+
+ def test_1463026_3(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startPrefixMapping('my', 'qux')
+ gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
+ gen.endElementNS(('qux', 'a'), 'a')
+ gen.endPrefixMapping('my')
+ gen.endDocument()
+
+ self.assertEquals(result.getvalue(),
+ start+'<my:a xmlns:my="qux" b="c"></my:a>')
+
+
+class XMLFilterBaseTest(unittest.TestCase):
+ def test_filter_basic(self):
+ result = StringIO()
+ gen = XMLGenerator(result)
+ filter = XMLFilterBase()
+ filter.setContentHandler(gen)
+
+ filter.startDocument()
+ filter.startElement("doc", {})
+ filter.characters("content")
+ filter.ignorableWhitespace(" ")
+ filter.endElement("doc")
+ filter.endDocument()
+
+ self.assertEquals(result.getvalue(), start + "<doc>content </doc>")
# ===========================================================================
#
@@ -276,229 +311,233 @@ def test_filter_basic():
#
# ===========================================================================
-# ===== XMLReader support
+xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
-def test_expat_file():
- parser = create_parser()
- result = StringIO()
- xmlgen = XMLGenerator(result)
+class ExpatReaderTest(XmlTestBase):
- parser.setContentHandler(xmlgen)
- parser.parse(open(findfile("test"+os.extsep+"xml")))
+ # ===== XMLReader support
- return result.getvalue() == xml_test_out
+ def test_expat_file(self):
+ parser = create_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
-# ===== DTDHandler support
+ parser.setContentHandler(xmlgen)
+ parser.parse(open(findfile("test"+os.extsep+"xml")))
-class TestDTDHandler:
+ self.assertEquals(result.getvalue(), xml_test_out)
- def __init__(self):
- self._notations = []
- self._entities = []
+ # ===== DTDHandler support
- def notationDecl(self, name, publicId, systemId):
- self._notations.append((name, publicId, systemId))
+ class TestDTDHandler:
- def unparsedEntityDecl(self, name, publicId, systemId, ndata):
- self._entities.append((name, publicId, systemId, ndata))
+ def __init__(self):
+ self._notations = []
+ self._entities = []
-def test_expat_dtdhandler():
- parser = create_parser()
- handler = TestDTDHandler()
- parser.setDTDHandler(handler)
+ def notationDecl(self, name, publicId, systemId):
+ self._notations.append((name, publicId, systemId))
- parser.feed('<!DOCTYPE doc [\n')
- parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
- parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
- parser.feed(']>\n')
- parser.feed('<doc></doc>')
- parser.close()
+ def unparsedEntityDecl(self, name, publicId, systemId, ndata):
+ self._entities.append((name, publicId, systemId, ndata))
- return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
- handler._entities == [("img", None, "expat.gif", "GIF")]
+ def test_expat_dtdhandler(self):
+ parser = create_parser()
+ handler = self.TestDTDHandler()
+ parser.setDTDHandler(handler)
-# ===== EntityResolver support
+ parser.feed('<!DOCTYPE doc [\n')
+ parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
+ parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
+ parser.feed(']>\n')
+ parser.feed('<doc></doc>')
+ parser.close()
-class TestEntityResolver:
+ self.assertEquals(handler._notations,
+ [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
+ self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")])
- def resolveEntity(self, publicId, systemId):
- inpsrc = InputSource()
- inpsrc.setByteStream(StringIO("<entity/>"))
- return inpsrc
+ # ===== EntityResolver support
-def test_expat_entityresolver():
- parser = create_parser()
- parser.setEntityResolver(TestEntityResolver())
- result = StringIO()
- parser.setContentHandler(XMLGenerator(result))
+ class TestEntityResolver:
- parser.feed('<!DOCTYPE doc [\n')
- parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
- parser.feed(']>\n')
- parser.feed('<doc>&test;</doc>')
- parser.close()
+ def resolveEntity(self, publicId, systemId):
+ inpsrc = InputSource()
+ inpsrc.setByteStream(StringIO("<entity/>"))
+ return inpsrc
- return result.getvalue() == start + "<doc><entity></entity></doc>"
+ def test_expat_entityresolver(self):
+ parser = create_parser()
+ parser.setEntityResolver(self.TestEntityResolver())
+ result = StringIO()
+ parser.setContentHandler(XMLGenerator(result))
-# ===== Attributes support
+ parser.feed('<!DOCTYPE doc [\n')
+ parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
+ parser.feed(']>\n')
+ parser.feed('<doc>&test;</doc>')
+ parser.close()
-class AttrGatherer(ContentHandler):
+ self.assertEquals(result.getvalue(), start +
+ "<doc><entity></entity></doc>")
- def startElement(self, name, attrs):
- self._attrs = attrs
+ # ===== Attributes support
- def startElementNS(self, name, qname, attrs):
- self._attrs = attrs
+ class AttrGatherer(ContentHandler):
-def test_expat_attrs_empty():
- parser = create_parser()
- gather = AttrGatherer()
- parser.setContentHandler(gather)
+ def startElement(self, name, attrs):
+ self._attrs = attrs
- parser.feed("<doc/>")
- parser.close()
+ def startElementNS(self, name, qname, attrs):
+ self._attrs = attrs
- return verify_empty_attrs(gather._attrs)
+ def test_expat_attrs_empty(self):
+ parser = create_parser()
+ gather = self.AttrGatherer()
+ parser.setContentHandler(gather)
-def test_expat_attrs_wattr():
- parser = create_parser()
- gather = AttrGatherer()
- parser.setContentHandler(gather)
+ parser.feed("<doc/>")
+ parser.close()
- parser.feed("<doc attr='val'/>")
- parser.close()
+ self.verify_empty_attrs(gather._attrs)
- return verify_attrs_wattr(gather._attrs)
+ def test_expat_attrs_wattr(self):
+ parser = create_parser()
+ gather = self.AttrGatherer()
+ parser.setContentHandler(gather)
-def test_expat_nsattrs_empty():
- parser = create_parser(1)
- gather = AttrGatherer()
- parser.setContentHandler(gather)
+ parser.feed("<doc attr='val'/>")
+ parser.close()
- parser.feed("<doc/>")
- parser.close()
+ self.verify_attrs_wattr(gather._attrs)
- return verify_empty_nsattrs(gather._attrs)
+ def test_expat_nsattrs_empty(self):
+ parser = create_parser(1)
+ gather = self.AttrGatherer()
+ parser.setContentHandler(gather)
-def test_expat_nsattrs_wattr():
- parser = create_parser(1)
- gather = AttrGatherer()
- parser.setContentHandler(gather)
+ parser.feed("<doc/>")
+ parser.close()
- parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
- parser.close()
+ self.verify_empty_nsattrs(gather._attrs)
- attrs = gather._attrs
+ def test_expat_nsattrs_wattr(self):
+ parser = create_parser(1)
+ gather = self.AttrGatherer()
+ parser.setContentHandler(gather)
- return attrs.getLength() == 1 and \
- attrs.getNames() == [(ns_uri, "attr")] and \
- (attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"]) and \
- len(attrs) == 1 and \
- (ns_uri, "attr") in attrs and \
- list(attrs.keys()) == [(ns_uri, "attr")] and \
- attrs.get((ns_uri, "attr")) == "val" and \
- attrs.get((ns_uri, "attr"), 25) == "val" and \
- list(attrs.items()) == [((ns_uri, "attr"), "val")] and \
- list(attrs.values()) == ["val"] and \
- attrs.getValue((ns_uri, "attr")) == "val" and \
- attrs[(ns_uri, "attr")] == "val"
+ parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
+ parser.close()
-# ===== InputSource support
+ attrs = gather._attrs
-xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
+ self.assertEquals(attrs.getLength(), 1)
+ self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
+ self.assertTrue((attrs.getQNames() == [] or
+ attrs.getQNames() == ["ns:attr"]))
+ self.assertEquals(len(attrs), 1)
+ self.assertTrue((ns_uri, "attr") in attrs)
+ self.assertEquals(attrs.get((ns_uri, "attr")), "val")
+ self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
+ self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")])
+ self.assertEquals(list(attrs.values()), ["val"])
+ self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
+ self.assertEquals(attrs[(ns_uri, "attr")], "val")
-def test_expat_inpsource_filename():
- parser = create_parser()
- result = StringIO()
- xmlgen = XMLGenerator(result)
+ # ===== InputSource support
- parser.setContentHandler(xmlgen)
- parser.parse(findfile("test"+os.extsep+"xml"))
+ def test_expat_inpsource_filename(self):
+ parser = create_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
- return result.getvalue() == xml_test_out
+ parser.setContentHandler(xmlgen)
+ parser.parse(findfile("test"+os.extsep+"xml"))
-def test_expat_inpsource_sysid():
- parser = create_parser()
- result = StringIO()
- xmlgen = XMLGenerator(result)
+ self.assertEquals(result.getvalue(), xml_test_out)
- parser.setContentHandler(xmlgen)
- parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
+ def test_expat_inpsource_sysid(self):
+ parser = create_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
- return result.getvalue() == xml_test_out
+ parser.setContentHandler(xmlgen)
+ parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
-def test_expat_inpsource_stream():
- parser = create_parser()
- result = StringIO()
- xmlgen = XMLGenerator(result)
+ self.assertEquals(result.getvalue(), xml_test_out)
- parser.setContentHandler(xmlgen)
- inpsrc = InputSource()
- inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
- parser.parse(inpsrc)
+ def test_expat_inpsource_stream(self):
+ parser = create_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
- return result.getvalue() == xml_test_out
+ parser.setContentHandler(xmlgen)
+ inpsrc = InputSource()
+ inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
+ parser.parse(inpsrc)
-# ===== IncrementalParser support
+ self.assertEquals(result.getvalue(), xml_test_out)
-def test_expat_incremental():
- result = StringIO()
- xmlgen = XMLGenerator(result)
- parser = create_parser()
- parser.setContentHandler(xmlgen)
+ # ===== IncrementalParser support
- parser.feed("<doc>")
- parser.feed("</doc>")
- parser.close()
+ def test_expat_incremental(self):
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+ parser = create_parser()
+ parser.setContentHandler(xmlgen)
- return result.getvalue() == start + "<doc></doc>"
+ parser.feed("<doc>")
+ parser.feed("</doc>")
+ parser.close()
-def test_expat_incremental_reset():
- result = StringIO()
- xmlgen = XMLGenerator(result)
- parser = create_parser()
- parser.setContentHandler(xmlgen)
+ self.assertEquals(result.getvalue(), start + "<doc></doc>")
- parser.feed("<doc>")
- parser.feed("text")
+ def test_expat_incremental_reset(self):
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+ parser = create_parser()
+ parser.setContentHandler(xmlgen)
- result = StringIO()
- xmlgen = XMLGenerator(result)
- parser.setContentHandler(xmlgen)
- parser.reset()
+ parser.feed("<doc>")
+ parser.feed("text")
- parser.feed("<doc>")
- parser.feed("text")
- parser.feed("</doc>")
- parser.close()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+ parser.setContentHandler(xmlgen)
+ parser.reset()
- return result.getvalue() == start + "<doc>text</doc>"
+ parser.feed("<doc>")
+ parser.feed("text")
+ parser.feed("</doc>")
+ parser.close()
-# ===== Locator support
+ self.assertEquals(result.getvalue(), start + "<doc>text</doc>")
-def test_expat_locator_noinfo():
- result = StringIO()
- xmlgen = XMLGenerator(result)
- parser = create_parser()
- parser.setContentHandler(xmlgen)
+ # ===== Locator support
- parser.feed("<doc>")
- parser.feed("</doc>")
- parser.close()
+ def test_expat_locator_noinfo(self):
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+ parser = create_parser()
+ parser.setContentHandler(xmlgen)
- return parser.getSystemId() is None and \
- parser.getPublicId() is None and \
- parser.getLineNumber() == 1
+ parser.feed("<doc>")
+ parser.feed("</doc>")
+ parser.close()
-def test_expat_locator_withinfo():
- result = StringIO()
- xmlgen = XMLGenerator(result)
- parser = create_parser()
- parser.setContentHandler(xmlgen)
- parser.parse(findfile("test.xml"))
+ self.assertEquals(parser.getSystemId(), None)
+ self.assertEquals(parser.getPublicId(), None)
+ self.assertEquals(parser.getLineNumber(), 1)
- return parser.getSystemId() == findfile("test.xml") and \
- parser.getPublicId() is None
+ def test_expat_locator_withinfo(self):
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+ parser = create_parser()
+ parser.setContentHandler(xmlgen)
+ parser.parse(findfile("test.xml"))
+
+ self.assertEquals(parser.getSystemId(), findfile("test.xml"))
+ self.assertEquals(parser.getPublicId(), None)
# ===========================================================================
@@ -507,63 +546,59 @@ def test_expat_locator_withinfo():
#
# ===========================================================================
-def test_expat_inpsource_location():
- parser = create_parser()
- parser.setContentHandler(ContentHandler()) # do nothing
- source = InputSource()
- source.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
- name = "a file name"
- source.setSystemId(name)
- try:
- parser.parse(source)
- except SAXException as e:
- return e.getSystemId() == name
-
-def test_expat_incomplete():
- parser = create_parser()
- parser.setContentHandler(ContentHandler()) # do nothing
- try:
- parser.parse(StringIO("<foo>"))
- except SAXParseException:
- return 1 # ok, error found
- else:
- return 0
-
-def test_sax_parse_exception_str():
- # pass various values from a locator to the SAXParseException to
- # make sure that the __str__() doesn't fall apart when None is
- # passed instead of an integer line and column number
- #
- # use "normal" values for the locator:
- str(SAXParseException("message", None,
- DummyLocator(1, 1)))
- # use None for the line number:
- str(SAXParseException("message", None,
- DummyLocator(None, 1)))
- # use None for the column number:
- str(SAXParseException("message", None,
- DummyLocator(1, None)))
- # use None for both:
- str(SAXParseException("message", None,
- DummyLocator(None, None)))
- return 1
-
-class DummyLocator:
- def __init__(self, lineno, colno):
- self._lineno = lineno
- self._colno = colno
-
- def getPublicId(self):
- return "pubid"
-
- def getSystemId(self):
- return "sysid"
-
- def getLineNumber(self):
- return self._lineno
-
- def getColumnNumber(self):
- return self._colno
+class ErrorReportingTest(unittest.TestCase):
+ def test_expat_inpsource_location(self):
+ parser = create_parser()
+ parser.setContentHandler(ContentHandler()) # do nothing
+ source = InputSource()
+ source.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
+ name = "a file name"
+ source.setSystemId(name)
+ try:
+ parser.parse(source)
+ self.fail()
+ except SAXException as e:
+ self.assertEquals(e.getSystemId(), name)
+
+ def test_expat_incomplete(self):
+ parser = create_parser()
+ parser.setContentHandler(ContentHandler()) # do nothing
+ self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
+
+ def test_sax_parse_exception_str(self):
+ # pass various values from a locator to the SAXParseException to
+ # make sure that the __str__() doesn't fall apart when None is
+ # passed instead of an integer line and column number
+ #
+ # use "normal" values for the locator:
+ str(SAXParseException("message", None,
+ self.DummyLocator(1, 1)))
+ # use None for the line number:
+ str(SAXParseException("message", None,
+ self.DummyLocator(None, 1)))
+ # use None for the column number:
+ str(SAXParseException("message", None,
+ self.DummyLocator(1, None)))
+ # use None for both:
+ str(SAXParseException("message", None,
+ self.DummyLocator(None, None)))
+
+ class DummyLocator:
+ def __init__(self, lineno, colno):
+ self._lineno = lineno
+ self._colno = colno
+
+ def getPublicId(self):
+ return "pubid"
+
+ def getSystemId(self):
+ return "sysid"
+
+ def getLineNumber(self):
+ return self._lineno
+
+ def getColumnNumber(self):
+ return self._colno
# ===========================================================================
#
@@ -571,217 +606,91 @@ class DummyLocator:
#
# ===========================================================================
-# ===== AttributesImpl
-
-def verify_empty_attrs(attrs):
- try:
- attrs.getValue("attr")
- gvk = 0
- except KeyError:
- gvk = 1
-
- try:
- attrs.getValueByQName("attr")
- gvqk = 0
- except KeyError:
- gvqk = 1
-
- try:
- attrs.getNameByQName("attr")
- gnqk = 0
- except KeyError:
- gnqk = 1
-
- try:
- attrs.getQNameByName("attr")
- gqnk = 0
- except KeyError:
- gqnk = 1
-
- try:
- attrs["attr"]
- gik = 0
- except KeyError:
- gik = 1
-
- return attrs.getLength() == 0 and \
- attrs.getNames() == [] and \
- attrs.getQNames() == [] and \
- len(attrs) == 0 and \
- "attr" not in attrs and \
- attrs.keys() == [] and \
- attrs.get("attrs") is None and \
- attrs.get("attrs", 25) == 25 and \
- attrs.items() == [] and \
- attrs.values() == [] and \
- gvk and gvqk and gnqk and gik and gqnk
-
-def verify_attrs_wattr(attrs):
- return attrs.getLength() == 1 and \
- attrs.getNames() == ["attr"] and \
- attrs.getQNames() == ["attr"] and \
- len(attrs) == 1 and \
- "attr" in attrs and \
- attrs.keys() == ["attr"] and \
- attrs.get("attr") == "val" and \
- attrs.get("attr", 25) == "val" and \
- attrs.items() == [("attr", "val")] and \
- attrs.values() == ["val"] and \
- attrs.getValue("attr") == "val" and \
- attrs.getValueByQName("attr") == "val" and \
- attrs.getNameByQName("attr") == "attr" and \
- attrs["attr"] == "val" and \
- attrs.getQNameByName("attr") == "attr"
-
-def test_attrs_empty():
- return verify_empty_attrs(AttributesImpl({}))
-
-def test_attrs_wattr():
- return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
-
-# ===== AttributesImpl
-
-def verify_empty_nsattrs(attrs):
- try:
- attrs.getValue((ns_uri, "attr"))
- gvk = 0
- except KeyError:
- gvk = 1
-
- try:
- attrs.getValueByQName("ns:attr")
- gvqk = 0
- except KeyError:
- gvqk = 1
-
- try:
- attrs.getNameByQName("ns:attr")
- gnqk = 0
- except KeyError:
- gnqk = 1
-
- try:
- attrs.getQNameByName((ns_uri, "attr"))
- gqnk = 0
- except KeyError:
- gqnk = 1
-
- try:
- attrs[(ns_uri, "attr")]
- gik = 0
- except KeyError:
- gik = 1
-
- return attrs.getLength() == 0 and \
- attrs.getNames() == [] and \
- attrs.getQNames() == [] and \
- len(attrs) == 0 and \
- (ns_uri, "attr") not in attrs and \
- attrs.keys() == [] and \
- attrs.get((ns_uri, "attr")) is None and \
- attrs.get((ns_uri, "attr"), 25) == 25 and \
- attrs.items() == [] and \
- attrs.values() == [] and \
- gvk and gvqk and gnqk and gik and gqnk
-
-def test_nsattrs_empty():
- return verify_empty_nsattrs(AttributesNSImpl({}, {}))
-
-def test_nsattrs_wattr():
- attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
- {(ns_uri, "attr") : "ns:attr"})
-
- return attrs.getLength() == 1 and \
- attrs.getNames() == [(ns_uri, "attr")] and \
- attrs.getQNames() == ["ns:attr"] and \
- len(attrs) == 1 and \
- (ns_uri, "attr") in attrs and \
- attrs.keys() == [(ns_uri, "attr")] and \
- attrs.get((ns_uri, "attr")) == "val" and \
- attrs.get((ns_uri, "attr"), 25) == "val" and \
- attrs.items() == [((ns_uri, "attr"), "val")] and \
- attrs.values() == ["val"] and \
- attrs.getValue((ns_uri, "attr")) == "val" and \
- attrs.getValueByQName("ns:attr") == "val" and \
- attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
- attrs[(ns_uri, "attr")] == "val" and \
- attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
-
-
-# During the development of Python 2.5, an attempt to move the "xml"
-# package implementation to a new package ("xmlcore") proved painful.
-# The goal of this change was to allow applications to be able to
-# obtain and rely on behavior in the standard library implementation
-# of the XML support without needing to be concerned about the
-# availability of the PyXML implementation.
-#
-# While the existing import hackery in Lib/xml/__init__.py can cause
-# PyXML's _xmlpus package to supplant the "xml" package, that only
-# works because either implementation uses the "xml" package name for
-# imports.
-#
-# The move resulted in a number of problems related to the fact that
-# the import machinery's "package context" is based on the name that's
-# being imported rather than the __name__ of the actual package
-# containment; it wasn't possible for the "xml" package to be replaced
-# by a simple module that indirected imports to the "xmlcore" package.
-#
-# The following two tests exercised bugs that were introduced in that
-# attempt. Keeping these tests around will help detect problems with
-# other attempts to provide reliable access to the standard library's
-# implementation of the XML support.
-
-def test_sf_1511497():
- # Bug report: http://www.python.org/sf/1511497
- import sys
- old_modules = sys.modules.copy()
- for modname in list(sys.modules.keys()):
- if modname.startswith("xml."):
- del sys.modules[modname]
- try:
- import xml.sax.expatreader
- module = xml.sax.expatreader
- return module.__name__ == "xml.sax.expatreader"
- finally:
- sys.modules.update(old_modules)
-
-def test_sf_1513611():
- # Bug report: http://www.python.org/sf/1513611
- sio = StringIO("invalid")
- parser = make_parser()
- from xml.sax import SAXParseException
- try:
- parser.parse(sio)
- except SAXParseException:
- return True
- else:
- return False
-
-# ===== Main program
-
-def make_test_output():
- parser = create_parser()
- result = StringIO()
- xmlgen = XMLGenerator(result)
-
- parser.setContentHandler(xmlgen)
- parser.parse(findfile("test"+os.extsep+"xml"))
-
- outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w")
- outf.write(result.getvalue())
- outf.close()
-
-items = sorted(locals().items())
-for (name, value) in items:
- if name[ : 5] == "test_":
- confirm(value(), name)
-# We delete the items variable so that the assignment to items above
-# doesn't pick up the old value of items (which messes with attempts
-# to find reference leaks).
-del items
-
-if verbose:
- print("%d tests, %d failures" % (tests, len(failures)))
-if failures:
- raise TestFailed("%d of %d tests failed: %s"
- % (len(failures), tests, ", ".join(failures)))
+class XmlReaderTest(XmlTestBase):
+
+ # ===== AttributesImpl
+ def test_attrs_empty(self):
+ self.verify_empty_attrs(AttributesImpl({}))
+
+ def test_attrs_wattr(self):
+ self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
+
+ def test_nsattrs_empty(self):
+ self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
+
+ def test_nsattrs_wattr(self):
+ attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
+ {(ns_uri, "attr") : "ns:attr"})
+
+ self.assertEquals(attrs.getLength(), 1)
+ self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
+ self.assertEquals(attrs.getQNames(), ["ns:attr"])
+ self.assertEquals(len(attrs), 1)
+ self.assertTrue((ns_uri, "attr") in attrs)
+ self.assertEquals(list(attrs.keys()), [(ns_uri, "attr")])
+ self.assertEquals(attrs.get((ns_uri, "attr")), "val")
+ self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
+ self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")])
+ self.assertEquals(list(attrs.values()), ["val"])
+ self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
+ self.assertEquals(attrs.getValueByQName("ns:attr"), "val")
+ self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
+ self.assertEquals(attrs[(ns_uri, "attr")], "val")
+ self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
+
+
+ # During the development of Python 2.5, an attempt to move the "xml"
+ # package implementation to a new package ("xmlcore") proved painful.
+ # The goal of this change was to allow applications to be able to
+ # obtain and rely on behavior in the standard library implementation
+ # of the XML support without needing to be concerned about the
+ # availability of the PyXML implementation.
+ #
+ # While the existing import hackery in Lib/xml/__init__.py can cause
+ # PyXML's _xmlpus package to supplant the "xml" package, that only
+ # works because either implementation uses the "xml" package name for
+ # imports.
+ #
+ # The move resulted in a number of problems related to the fact that
+ # the import machinery's "package context" is based on the name that's
+ # being imported rather than the __name__ of the actual package
+ # containment; it wasn't possible for the "xml" package to be replaced
+ # by a simple module that indirected imports to the "xmlcore" package.
+ #
+ # The following two tests exercised bugs that were introduced in that
+ # attempt. Keeping these tests around will help detect problems with
+ # other attempts to provide reliable access to the standard library's
+ # implementation of the XML support.
+
+ def test_sf_1511497(self):
+ # Bug report: http://www.python.org/sf/1511497
+ import sys
+ old_modules = sys.modules.copy()
+ for modname in list(sys.modules.keys()):
+ if modname.startswith("xml."):
+ del sys.modules[modname]
+ try:
+ import xml.sax.expatreader
+ module = xml.sax.expatreader
+ self.assertEquals(module.__name__, "xml.sax.expatreader")
+ finally:
+ sys.modules.update(old_modules)
+
+ def test_sf_1513611(self):
+ # Bug report: http://www.python.org/sf/1513611
+ sio = StringIO("invalid")
+ parser = make_parser()
+ from xml.sax import SAXParseException
+ self.assertRaises(SAXParseException, parser.parse, sio)
+
+
+def unittest_main():
+ run_unittest(MakeParserTest,
+ SaxutilsTest,
+ XmlgenTest,
+ ExpatReaderTest,
+ ErrorReportingTest,
+ XmlReaderTest)
+
+if __name__ == "__main__":
+ unittest_main()
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index f52ab91..f5c1462 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -477,6 +477,39 @@ self.assert_(X.passed)
del d['h']
self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6})
+ def testLocalsClass(self):
+ # This test verifies that calling locals() does not pollute
+ # the local namespace of the class with free variables. Old
+ # versions of Python had a bug, where a free variable being
+ # passed through a class namespace would be inserted into
+ # locals() by locals() or exec or a trace function.
+ #
+ # The real bug lies in frame code that copies variables
+ # between fast locals and the locals dict, e.g. when executing
+ # a trace function.
+
+ def f(x):
+ class C:
+ x = 12
+ def m(self):
+ return x
+ locals()
+ return C
+
+ self.assertEqual(f(1).x, 12)
+
+ def f(x):
+ class C:
+ y = x
+ def m(self):
+ return x
+ z = list(locals())
+ return C
+
+ varnames = f(1).z
+ self.assert_("x" not in varnames)
+ self.assert_("y" in varnames)
+
def testBoundAndFree(self):
# var is bound and free in class
@@ -607,7 +640,7 @@ self.assert_(X.passed)
c = f(0)
self.assertEqual(c.get(), 1)
self.assert_("x" not in c.__class__.__dict__)
-
+
def testNonLocalGenerator(self):
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index 997e17f..45bf32c 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -288,10 +288,17 @@ class TestJointOps(unittest.TestCase):
s = self.thetype(d)
self.assertEqual(sum(elem.hash_count for elem in d), n)
s.difference(d)
- self.assertEqual(sum(elem.hash_count for elem in d), n)
+ self.assertEqual(sum(elem.hash_count for elem in d), n)
if hasattr(s, 'symmetric_difference_update'):
s.symmetric_difference_update(d)
- self.assertEqual(sum(elem.hash_count for elem in d), n)
+ self.assertEqual(sum(elem.hash_count for elem in d), n)
+ d2 = dict.fromkeys(set(d))
+ self.assertEqual(sum(elem.hash_count for elem in d), n)
+ d3 = dict.fromkeys(frozenset(d))
+ self.assertEqual(sum(elem.hash_count for elem in d), n)
+ d3 = dict.fromkeys(frozenset(d), 123)
+ self.assertEqual(sum(elem.hash_count for elem in d), n)
+ self.assertEqual(d3, dict.fromkeys(d, 123))
class TestSet(TestJointOps):
thetype = set
diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py
index f22f619..977b28a 100644
--- a/Lib/test/test_slice.py
+++ b/Lib/test/test_slice.py
@@ -2,6 +2,7 @@
import unittest
from test import test_support
+from cPickle import loads, dumps
import sys
@@ -92,6 +93,24 @@ class SliceTest(unittest.TestCase):
self.assertRaises(OverflowError, slice(None).indices, 1<<100)
+ def test_setslice_without_getslice(self):
+ tmp = []
+ class X(object):
+ def __setslice__(self, i, j, k):
+ tmp.append((i, j, k))
+
+ x = X()
+ x[1:2] = 42
+ self.assertEquals(tmp, [(1, 2, 42)])
+
+ def test_pickle(self):
+ s = slice(10, 20, 3)
+ for protocol in (0,1,2):
+ t = loads(dumps(s, protocol))
+ self.assertEqual(s, t)
+ self.assertEqual(s.indices(15), t.indices(15))
+ self.assertNotEqual(id(s), id(t))
+
def test_main():
test_support.run_unittest(SliceTest)
diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
new file mode 100644
index 0000000..3542ddb
--- /dev/null
+++ b/Lib/test/test_smtplib.py
@@ -0,0 +1,71 @@
+import socket
+import threading
+import smtplib
+import time
+
+from unittest import TestCase
+from test import test_support
+
+
+def server(evt):
+ serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ serv.settimeout(3)
+ serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ serv.bind(("", 9091))
+ serv.listen(5)
+ try:
+ conn, addr = serv.accept()
+ except socket.timeout:
+ pass
+ else:
+ conn.send("220 Hola mundo\n")
+ conn.close()
+ finally:
+ serv.close()
+ evt.set()
+
+class GeneralTests(TestCase):
+
+ def setUp(self):
+ self.evt = threading.Event()
+ threading.Thread(target=server, args=(self.evt,)).start()
+ time.sleep(.1)
+
+ def tearDown(self):
+ self.evt.wait()
+
+ def testBasic(self):
+ # connects
+ smtp = smtplib.SMTP("localhost", 9091)
+ smtp.sock.close()
+
+ def testTimeoutDefault(self):
+ # default
+ smtp = smtplib.SMTP("localhost", 9091)
+ self.assertTrue(smtp.sock.gettimeout() is None)
+ smtp.sock.close()
+
+ def testTimeoutValue(self):
+ # a value
+ smtp = smtplib.SMTP("localhost", 9091, timeout=30)
+ self.assertEqual(smtp.sock.gettimeout(), 30)
+ smtp.sock.close()
+
+ def testTimeoutNone(self):
+ # None, having other default
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ smtp = smtplib.SMTP("localhost", 9091, timeout=None)
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(smtp.sock.gettimeout(), 30)
+ smtp.sock.close()
+
+
+
+def test_main(verbose=None):
+ test_support.run_unittest(GeneralTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 4f74186..ead3e4f 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -75,7 +75,7 @@ class ThreadableTest:
Note, the server setup function cannot call any blocking
functions that rely on the client thread during setup,
- unless serverExplicityReady() is called just before
+ unless serverExplicitReady() is called just before
the blocking call (such as in setting up a client/server
connection and performing the accept() in setUp().
"""
@@ -597,6 +597,13 @@ class BasicUDPTest(ThreadedUDPSocketTest):
def _testRecvFrom(self):
self.cli.sendto(MSG, 0, (HOST, PORT))
+ def testRecvFromNegative(self):
+ # Negative lengths passed to recvfrom should give ValueError.
+ self.assertRaises(ValueError, self.serv.recvfrom, -1)
+
+ def _testRecvFromNegative(self):
+ self.cli.sendto(MSG, 0, (HOST, PORT))
+
class TCPCloserTest(ThreadedTCPSocketTest):
def testClose(self):
@@ -810,6 +817,98 @@ class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase):
bufsize = 2 # Exercise the buffering code
+class NetworkConnectionTest(object):
+ """Prove network connection."""
+ def clientSetUp(self):
+ self.cli = socket.create_connection((HOST, PORT))
+ self.serv_conn = self.cli
+
+class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest):
+ """Tests that NetworkConnection does not break existing TCP functionality.
+ """
+
+class NetworkConnectionNoServer(unittest.TestCase):
+ def testWithoutServer(self):
+ self.failUnlessRaises(socket.error, lambda: socket.create_connection((HOST, PORT)))
+
+class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
+
+ def __init__(self, methodName='runTest'):
+ SocketTCPTest.__init__(self, methodName=methodName)
+ ThreadableTest.__init__(self)
+
+ def clientSetUp(self):
+ pass
+
+ def clientTearDown(self):
+ self.cli.close()
+ self.cli = None
+ ThreadableTest.clientTearDown(self)
+
+ def _justAccept(self):
+ conn, addr = self.serv.accept()
+
+ testFamily = _justAccept
+ def _testFamily(self):
+ self.cli = socket.create_connection((HOST, PORT), timeout=30)
+ self.assertEqual(self.cli.family, 2)
+
+ testTimeoutDefault = _justAccept
+ def _testTimeoutDefault(self):
+ self.cli = socket.create_connection((HOST, PORT))
+ self.assertTrue(self.cli.gettimeout() is None)
+
+ testTimeoutValueNamed = _justAccept
+ def _testTimeoutValueNamed(self):
+ self.cli = socket.create_connection((HOST, PORT), timeout=30)
+ self.assertEqual(self.cli.gettimeout(), 30)
+
+ testTimeoutValueNonamed = _justAccept
+ def _testTimeoutValueNonamed(self):
+ self.cli = socket.create_connection((HOST, PORT), 30)
+ self.assertEqual(self.cli.gettimeout(), 30)
+
+ testTimeoutNone = _justAccept
+ def _testTimeoutNone(self):
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ self.cli = socket.create_connection((HOST, PORT), timeout=None)
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(self.cli.gettimeout(), 30)
+
+
+class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest):
+
+ def __init__(self, methodName='runTest'):
+ SocketTCPTest.__init__(self, methodName=methodName)
+ ThreadableTest.__init__(self)
+
+ def clientSetUp(self):
+ pass
+
+ def clientTearDown(self):
+ self.cli.close()
+ self.cli = None
+ ThreadableTest.clientTearDown(self)
+
+ def testInsideTimeout(self):
+ conn, addr = self.serv.accept()
+ time.sleep(3)
+ conn.send("done!")
+ testOutsideTimeout = testInsideTimeout
+
+ def _testInsideTimeout(self):
+ self.cli = sock = socket.create_connection((HOST, PORT))
+ data = sock.recv(5)
+ self.assertEqual(data, "done!")
+
+ def _testOutsideTimeout(self):
+ self.cli = sock = socket.create_connection((HOST, PORT), timeout=1)
+ self.failUnlessRaises(socket.timeout, lambda: sock.recv(5))
+
+
class Urllib2FileobjectTest(unittest.TestCase):
# urllib2.HTTPHandler has "borrowed" socket._fileobject, and requires that
@@ -977,7 +1076,7 @@ class BufferIOTest(SocketConnectedTest):
def test_main():
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
- TestExceptions, BufferIOTest]
+ TestExceptions, BufferIOTest, BasicTCPTest2]
if sys.platform != 'mac':
tests.extend([ BasicUDPTest, UDPTimeoutTest ])
@@ -988,6 +1087,9 @@ def test_main():
LineBufferedFileObjectClassTestCase,
SmallBufferedFileObjectClassTestCase,
Urllib2FileobjectTest,
+ NetworkConnectionNoServer,
+ NetworkConnectionAttributesTest,
+ NetworkConnectionBehaviourTest,
])
if hasattr(socket, "socketpair"):
tests.append(BasicSocketPairTest)
diff --git a/Lib/test/test_socket_ssl.py b/Lib/test/test_socket_ssl.py
index b04effe..42efb6e 100644
--- a/Lib/test/test_socket_ssl.py
+++ b/Lib/test/test_socket_ssl.py
@@ -1,128 +1,221 @@
# Test just the SSL support in the socket module, in a moderately bogus way.
import sys
+import unittest
from test import test_support
import socket
import errno
+import threading
+import subprocess
+import time
+import os
+import urllib
-# Optionally test SSL support. This requires the 'network' resource as given
-# on the regrtest command line.
-skip_expected = not (test_support.is_resource_enabled('network') and
- hasattr(socket, "ssl"))
+# Optionally test SSL support, if we have it in the tested platform
+skip_expected = not hasattr(socket, "ssl")
-def test_basic():
- test_support.requires('network')
+class ConnectedTests(unittest.TestCase):
- import urllib
-
- if test_support.verbose:
- print("test_basic ...")
-
- socket.RAND_status()
- try:
- socket.RAND_egd(1)
- except TypeError:
- pass
- else:
- print("didn't raise TypeError")
- socket.RAND_add("this is a random string", 75.0)
-
- f = urllib.urlopen('https://sf.net')
- buf = f.read()
- f.close()
-
-def test_timeout():
- test_support.requires('network')
-
- def error_msg(extra_msg):
- print("""\
- WARNING: an attempt to connect to %r %s, in
- test_timeout. That may be legitimate, but is not the outcome we hoped
- for. If this message is seen often, test_timeout should be changed to
- use a more reliable address.""" % (ADDR, extra_msg), file=sys.stderr)
-
- if test_support.verbose:
- print("test_timeout ...")
-
- # A service which issues a welcome banner (without need to write
- # anything).
- # XXX ("gmail.org", 995) has been unreliable so far, from time to time
- # XXX non-responsive for hours on end (& across all buildbot slaves,
- # XXX so that's not just a local thing).
- ADDR = "gmail.org", 995
-
- s = socket.socket()
- s.settimeout(30.0)
- try:
- s.connect(ADDR)
- except socket.timeout:
- error_msg('timed out')
- return
- except socket.error as exc: # In case connection is refused.
- if exc.args[0] == errno.ECONNREFUSED:
- error_msg('was refused')
- return
+ def testBasic(self):
+ socket.RAND_status()
+ try:
+ socket.RAND_egd(1)
+ except TypeError:
+ pass
else:
- raise
+ print("didn't raise TypeError")
+ socket.RAND_add("this is a random string", 75.0)
+
+ with test_support.transient_internet():
+ f = urllib.urlopen('https://sf.net')
+ buf = f.read()
+ f.close()
+
+ def testTimeout(self):
+ def error_msg(extra_msg):
+ print("""\
+ WARNING: an attempt to connect to %r %s, in
+ test_timeout. That may be legitimate, but is not the outcome we
+ hoped for. If this message is seen often, test_timeout should be
+ changed to use a more reliable address.""" % (ADDR, extra_msg), file=sys.stderr)
+
+ # A service which issues a welcome banner (without need to write
+ # anything).
+ # XXX ("gmail.org", 995) has been unreliable so far, from time to
+ # XXX time non-responsive for hours on end (& across all buildbot
+ # XXX slaves, so that's not just a local thing).
+ ADDR = "gmail.org", 995
- ss = socket.ssl(s)
- # Read part of return welcome banner twice.
- ss.read(1)
- ss.read(1)
- s.close()
-
-def test_rude_shutdown():
- if test_support.verbose:
- print("test_rude_shutdown ...")
-
- try:
- import threading
- except ImportError:
- return
+ s = socket.socket()
+ s.settimeout(30.0)
+ try:
+ s.connect(ADDR)
+ except socket.timeout:
+ error_msg('timed out')
+ return
+ except socket.error as exc: # In case connection is refused.
+ if exc.args[0] == errno.ECONNREFUSED:
+ error_msg('was refused')
+ return
+ else:
+ raise
+
+ ss = socket.ssl(s)
+ # Read part of return welcome banner twice.
+ ss.read(1)
+ ss.read(1)
+ s.close()
+
+class BasicTests(unittest.TestCase):
+
+ def testRudeShutdown(self):
+ # Some random port to connect to.
+ PORT = [9934]
+
+ listener_ready = threading.Event()
+ listener_gone = threading.Event()
+
+ # `listener` runs in a thread. It opens a socket listening on
+ # PORT, and sits in an accept() until the main thread connects.
+ # Then it rudely closes the socket, and sets Event `listener_gone`
+ # to let the main thread know the socket is gone.
+ def listener():
+ s = socket.socket()
+ PORT[0] = test_support.bind_port(s, '', PORT[0])
+ s.listen(5)
+ listener_ready.set()
+ s.accept()
+ s = None # reclaim the socket object, which also closes it
+ listener_gone.set()
+
+ def connector():
+ listener_ready.wait()
+ s = socket.socket()
+ s.connect(('localhost', PORT[0]))
+ listener_gone.wait()
+ try:
+ ssl_sock = socket.ssl(s)
+ except socket.sslerror:
+ pass
+ else:
+ raise test_support.TestFailed(
+ 'connecting to closed SSL socket should have failed')
- # Some random port to connect to.
- PORT = [9934]
+ t = threading.Thread(target=listener)
+ t.start()
+ connector()
+ t.join()
- listener_ready = threading.Event()
- listener_gone = threading.Event()
+class OpenSSLTests(unittest.TestCase):
- # `listener` runs in a thread. It opens a socket listening on PORT, and
- # sits in an accept() until the main thread connects. Then it rudely
- # closes the socket, and sets Event `listener_gone` to let the main thread
- # know the socket is gone.
- def listener():
+ def testBasic(self):
s = socket.socket()
- PORT[0] = test_support.bind_port(s, '', PORT[0])
- s.listen(5)
- listener_ready.set()
- s.accept()
- s = None # reclaim the socket object, which also closes it
- listener_gone.set()
-
- def connector():
- listener_ready.wait()
+ s.connect(("localhost", 4433))
+ ss = socket.ssl(s)
+ ss.write("Foo\n")
+ i = ss.read(4)
+ self.assertEqual(i, "Foo\n")
+ s.close()
+
+ def testMethods(self):
+ # read & write is already tried in the Basic test
+ # now we'll try to get the server info about certificates
+ # this came from the certificate I used, one I found in /usr/share/openssl
+ info = "/C=PT/ST=Queensland/L=Lisboa/O=Neuronio, Lda./OU=Desenvolvimento/CN=brutus.neuronio.pt/emailAddress=sampo@iki.fi"
+
s = socket.socket()
- s.connect(('localhost', PORT[0]))
- listener_gone.wait()
+ s.connect(("localhost", 4433))
+ ss = socket.ssl(s)
+ cert = ss.server()
+ self.assertEqual(cert, info)
+ cert = ss.issuer()
+ self.assertEqual(cert, info)
+ s.close()
+
+
+class OpenSSLServer(threading.Thread):
+ def __init__(self):
+ self.s = None
+ self.keepServing = True
+ self._external()
+ if self.haveServer:
+ threading.Thread.__init__(self)
+
+ def _external(self):
+ # let's find the .pem files
+ curdir = os.path.dirname(__file__) or os.curdir
+ cert_file = os.path.join(curdir, "ssl_cert.pem")
+ if not os.access(cert_file, os.F_OK):
+ raise ValueError("No cert file found! (tried %r)" % cert_file)
+ key_file = os.path.join(curdir, "ssl_key.pem")
+ if not os.access(key_file, os.F_OK):
+ raise ValueError("No key file found! (tried %r)" % key_file)
+
try:
- ssl_sock = socket.ssl(s)
- except socket.sslerror:
- pass
+ cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file)
+ self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ time.sleep(1)
+ except:
+ self.haveServer = False
else:
- raise test_support.TestFailed(
- 'connecting to closed SSL socket should have failed')
-
- t = threading.Thread(target=listener)
- t.start()
- connector()
- t.join()
+ # let's try if it is actually up
+ try:
+ s = socket.socket()
+ s.connect(("localhost", 4433))
+ s.close()
+ if self.s.stdout.readline() != "ERROR\n":
+ raise ValueError
+ except:
+ self.haveServer = False
+ else:
+ self.haveServer = True
+
+ def run(self):
+ while self.keepServing:
+ time.sleep(.5)
+ l = self.s.stdout.readline()
+ self.s.stdin.write(l)
+
+ def shutdown(self):
+ self.keepServing = False
+ if not self.s:
+ return
+ if sys.platform == "win32":
+ subprocess.TerminateProcess(int(self.s._handle), -1)
+ else:
+ os.kill(self.s.pid, 15)
def test_main():
if not hasattr(socket, "ssl"):
raise test_support.TestSkipped("socket module has no ssl support")
- test_rude_shutdown()
- test_basic()
- test_timeout()
+
+ tests = [BasicTests]
+
+ if test_support.is_resource_enabled('network'):
+ tests.append(ConnectedTests)
+
+ # in these platforms we can kill the openssl process
+ if sys.platform in ("sunos5", "darwin", "linux1",
+ "linux2", "win32", "hp-ux11"):
+
+ server = OpenSSLServer()
+ if server.haveServer:
+ tests.append(OpenSSLTests)
+ server.start()
+ else:
+ server = None
+
+ thread_info = test_support.threading_setup()
+
+ try:
+ test_support.run_unittest(*tests)
+ finally:
+ if server is not None and server.haveServer:
+ server.shutdown()
+
+ test_support.threading_cleanup(*thread_info)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py
index 062be65..da936a4 100644
--- a/Lib/test/test_socketserver.py
+++ b/Lib/test/test_socketserver.py
@@ -74,6 +74,7 @@ class ServerThread(threading.Thread):
self.__addr = addr
self.__svrcls = svrcls
self.__hdlrcls = hdlrcls
+ self.ready = threading.Event()
def run(self):
class svrcls(MyMixinServer, self.__svrcls):
pass
@@ -81,9 +82,13 @@ class ServerThread(threading.Thread):
svr = svrcls(self.__addr, self.__hdlrcls)
# pull the address out of the server in case it changed
# this can happen if another process is using the port
- addr = getattr(svr, 'server_address')
+ addr = svr.server_address
if addr:
self.__addr = addr
+ if self.__addr != svr.socket.getsockname():
+ raise RuntimeError('server_address was %s, expected %s' %
+ (self.__addr, svr.socket.getsockname()))
+ self.ready.set()
if verbose: print("thread: serving three times")
svr.serve_a_few()
if verbose: print("thread: done")
@@ -136,7 +141,9 @@ def testloop(proto, servers, hdlrcls, testfunc):
t.start()
if verbose: print("server running")
for i in range(NREQ):
- time.sleep(DELAY)
+ t.ready.wait(10*DELAY)
+ if not t.ready.isSet():
+ raise RuntimeError("Server not ready within a reasonable time")
if verbose: print("test client", i)
testfunc(proto, addr)
if verbose: print("waiting for server")
diff --git a/Lib/test/test_stringprep.py b/Lib/test/test_stringprep.py
index 2baf4a5..60425dd 100644
--- a/Lib/test/test_stringprep.py
+++ b/Lib/test/test_stringprep.py
@@ -1,88 +1,96 @@
# To fully test this module, we would need a copy of the stringprep tables.
# Since we don't have them, this test checks only a few codepoints.
-from test.test_support import verify, vereq
+import unittest
+from test import test_support
-import stringprep
from stringprep import *
-verify(in_table_a1(u"\u0221"))
-verify(not in_table_a1(u"\u0222"))
+class StringprepTests(unittest.TestCase):
+ def test(self):
+ self.failUnless(in_table_a1(u"\u0221"))
+ self.failIf(in_table_a1(u"\u0222"))
-verify(in_table_b1(u"\u00ad"))
-verify(not in_table_b1(u"\u00ae"))
+ self.failUnless(in_table_b1(u"\u00ad"))
+ self.failIf(in_table_b1(u"\u00ae"))
-verify(map_table_b2(u"\u0041"), u"\u0061")
-verify(map_table_b2(u"\u0061"), u"\u0061")
+ self.failUnless(map_table_b2(u"\u0041"), u"\u0061")
+ self.failUnless(map_table_b2(u"\u0061"), u"\u0061")
-verify(map_table_b3(u"\u0041"), u"\u0061")
-verify(map_table_b3(u"\u0061"), u"\u0061")
+ self.failUnless(map_table_b3(u"\u0041"), u"\u0061")
+ self.failUnless(map_table_b3(u"\u0061"), u"\u0061")
-verify(in_table_c11(u"\u0020"))
-verify(not in_table_c11(u"\u0021"))
+ self.failUnless(in_table_c11(u"\u0020"))
+ self.failIf(in_table_c11(u"\u0021"))
-verify(in_table_c12(u"\u00a0"))
-verify(not in_table_c12(u"\u00a1"))
+ self.failUnless(in_table_c12(u"\u00a0"))
+ self.failIf(in_table_c12(u"\u00a1"))
-verify(in_table_c12(u"\u00a0"))
-verify(not in_table_c12(u"\u00a1"))
+ self.failUnless(in_table_c12(u"\u00a0"))
+ self.failIf(in_table_c12(u"\u00a1"))
-verify(in_table_c11_c12(u"\u00a0"))
-verify(not in_table_c11_c12(u"\u00a1"))
+ self.failUnless(in_table_c11_c12(u"\u00a0"))
+ self.failIf(in_table_c11_c12(u"\u00a1"))
-verify(in_table_c21(u"\u001f"))
-verify(not in_table_c21(u"\u0020"))
+ self.failUnless(in_table_c21(u"\u001f"))
+ self.failIf(in_table_c21(u"\u0020"))
-verify(in_table_c22(u"\u009f"))
-verify(not in_table_c22(u"\u00a0"))
+ self.failUnless(in_table_c22(u"\u009f"))
+ self.failIf(in_table_c22(u"\u00a0"))
-verify(in_table_c21_c22(u"\u009f"))
-verify(not in_table_c21_c22(u"\u00a0"))
+ self.failUnless(in_table_c21_c22(u"\u009f"))
+ self.failIf(in_table_c21_c22(u"\u00a0"))
-verify(in_table_c3(u"\ue000"))
-verify(not in_table_c3(u"\uf900"))
+ self.failUnless(in_table_c3(u"\ue000"))
+ self.failIf(in_table_c3(u"\uf900"))
-verify(in_table_c4(u"\uffff"))
-verify(not in_table_c4(u"\u0000"))
+ self.failUnless(in_table_c4(u"\uffff"))
+ self.failIf(in_table_c4(u"\u0000"))
-verify(in_table_c5(u"\ud800"))
-verify(not in_table_c5(u"\ud7ff"))
+ self.failUnless(in_table_c5(u"\ud800"))
+ self.failIf(in_table_c5(u"\ud7ff"))
-verify(in_table_c6(u"\ufff9"))
-verify(not in_table_c6(u"\ufffe"))
+ self.failUnless(in_table_c6(u"\ufff9"))
+ self.failIf(in_table_c6(u"\ufffe"))
-verify(in_table_c7(u"\u2ff0"))
-verify(not in_table_c7(u"\u2ffc"))
+ self.failUnless(in_table_c7(u"\u2ff0"))
+ self.failIf(in_table_c7(u"\u2ffc"))
-verify(in_table_c8(u"\u0340"))
-verify(not in_table_c8(u"\u0342"))
+ self.failUnless(in_table_c8(u"\u0340"))
+ self.failIf(in_table_c8(u"\u0342"))
-# C.9 is not in the bmp
-# verify(in_table_c9(u"\U000E0001"))
-# verify(not in_table_c8(u"\U000E0002"))
+ # C.9 is not in the bmp
+ # self.failUnless(in_table_c9(u"\U000E0001"))
+ # self.failIf(in_table_c8(u"\U000E0002"))
-verify(in_table_d1(u"\u05be"))
-verify(not in_table_d1(u"\u05bf"))
+ self.failUnless(in_table_d1(u"\u05be"))
+ self.failIf(in_table_d1(u"\u05bf"))
-verify(in_table_d2(u"\u0041"))
-verify(not in_table_d2(u"\u0040"))
+ self.failUnless(in_table_d2(u"\u0041"))
+ self.failIf(in_table_d2(u"\u0040"))
-# This would generate a hash of all predicates. However, running
-# it is quite expensive, and only serves to detect changes in the
-# unicode database. Instead, stringprep.py asserts the version of
-# the database.
+ # This would generate a hash of all predicates. However, running
+ # it is quite expensive, and only serves to detect changes in the
+ # unicode database. Instead, stringprep.py asserts the version of
+ # the database.
-# import hashlib
-# predicates = [k for k in dir(stringprep) if k.startswith("in_table")]
-# predicates.sort()
-# for p in predicates:
-# f = getattr(stringprep, p)
-# # Collect all BMP code points
-# data = ["0"] * 0x10000
-# for i in range(0x10000):
-# if f(unichr(i)):
-# data[i] = "1"
-# data = "".join(data)
-# h = hashlib.sha1()
-# h.update(data)
-# print p, h.hexdigest()
+ # import hashlib
+ # predicates = [k for k in dir(stringprep) if k.startswith("in_table")]
+ # predicates.sort()
+ # for p in predicates:
+ # f = getattr(stringprep, p)
+ # # Collect all BMP code points
+ # data = ["0"] * 0x10000
+ # for i in range(0x10000):
+ # if f(unichr(i)):
+ # data[i] = "1"
+ # data = "".join(data)
+ # h = hashlib.sha1()
+ # h.update(data)
+ # print p, h.hexdigest()
+
+def test_main():
+ test_support.run_unittest(StringprepTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py
index c1af281..0e1909e 100644
--- a/Lib/test/test_strptime.py
+++ b/Lib/test/test_strptime.py
@@ -505,6 +505,35 @@ class CacheTests(unittest.TestCase):
self.failIfEqual(locale_time_id,
id(_strptime._TimeRE_cache.locale_time))
+ def test_TimeRE_recreation(self):
+ # The TimeRE instance should be recreated upon changing the locale.
+ locale_info = locale.getlocale(locale.LC_TIME)
+ try:
+ locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8'))
+ except locale.Error:
+ return
+ try:
+ _strptime.strptime('10', '%d')
+ # Get id of current cache object.
+ first_time_re_id = id(_strptime._TimeRE_cache)
+ try:
+ # Change the locale and force a recreation of the cache.
+ locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8'))
+ _strptime.strptime('10', '%d')
+ # Get the new cache object's id.
+ second_time_re_id = id(_strptime._TimeRE_cache)
+ # They should not be equal.
+ self.failIfEqual(first_time_re_id, second_time_re_id)
+ # Possible test locale is not supported while initial locale is.
+ # If this is the case just suppress the exception and fall-through
+ # to the reseting to the original locale.
+ except locale.Error:
+ pass
+ # Make sure we don't trample on the locale setting once we leave the
+ # test.
+ finally:
+ locale.setlocale(locale.LC_TIME, locale_info)
+
def test_main():
test_support.run_unittest(
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index 0678761..b62d74c 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -614,53 +614,61 @@ def test_pack_into_fn():
assertRaises(struct.error, pack_into, small_buf, 0, test_string)
assertRaises(struct.error, pack_into, small_buf, 2, test_string)
+def test_unpack_with_buffer():
+ # SF bug 1563759: struct.unpack doens't support buffer protocol objects
+ data1 = array.array('B', '\x12\x34\x56\x78')
+ data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
+ for data in [data1, data2]:
+ value, = struct.unpack('>I', data)
+ vereq(value, 0x12345678)
# Test methods to pack and unpack from buffers rather than strings.
test_unpack_from()
test_pack_into()
test_pack_into_fn()
+test_unpack_with_buffer()
def test_bool():
for prefix in tuple("<>!=")+('',):
false = (), [], [], '', 0
true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
-
+
falseFormat = prefix + 't' * len(false)
if verbose:
print('trying bool pack/unpack on', false, 'using format', falseFormat)
packedFalse = struct.pack(falseFormat, *false)
unpackedFalse = struct.unpack(falseFormat, packedFalse)
-
+
trueFormat = prefix + 't' * len(true)
if verbose:
print('trying bool pack/unpack on', true, 'using format', trueFormat)
packedTrue = struct.pack(trueFormat, *true)
unpackedTrue = struct.unpack(trueFormat, packedTrue)
-
+
if len(true) != len(unpackedTrue):
raise TestFailed('unpacked true array is not of same size as input')
if len(false) != len(unpackedFalse):
raise TestFailed('unpacked false array is not of same size as input')
-
+
for t in unpackedFalse:
if t is not False:
raise TestFailed('%r did not unpack as False' % t)
for t in unpackedTrue:
if t is not True:
raise TestFailed('%r did not unpack as false' % t)
-
+
if prefix and verbose:
print('trying size of bool with format %r' % (prefix+'t'))
packed = struct.pack(prefix+'t', 1)
-
+
if len(packed) != struct.calcsize(prefix+'t'):
raise TestFailed('packed length is not equal to calculated size')
-
+
if len(packed) != 1 and prefix:
raise TestFailed('encoded bool is not one byte: %r' % packed)
elif not prefix and verbose:
print('size of bool in native format is %i' % (len(packed)))
-
+
for c in '\x01\x7f\xff\x0f\xf0':
if struct.unpack('>t', c)[0] is not True:
raise TestFailed('%c did not unpack as True' % c)
diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py
index 0713b87..599c6fb 100644
--- a/Lib/test/test_structmembers.py
+++ b/Lib/test/test_structmembers.py
@@ -4,7 +4,7 @@ from _testcapi import test_structmembersType, \
INT_MAX, INT_MIN, UINT_MAX, \
LONG_MAX, LONG_MIN, ULONG_MAX
-import warnings, unittest, test.test_warnings
+import warnings, unittest
from test import test_support
ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010)
@@ -39,34 +39,39 @@ class ReadWriteTests(unittest.TestCase):
ts.T_ULONG=ULONG_MAX
self.assertEquals(ts.T_ULONG, ULONG_MAX)
-class TestWarnings(test.test_warnings.TestModule):
- def has_warned(self):
- self.assertEqual(test.test_warnings.msg.category,
- RuntimeWarning.__name__)
+class TestWarnings(unittest.TestCase):
+ def has_warned(self, w):
+ self.assert_(w.category is RuntimeWarning)
def test_byte_max(self):
- ts.T_BYTE=CHAR_MAX+1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_BYTE=CHAR_MAX+1
+ self.has_warned(w)
def test_byte_min(self):
- ts.T_BYTE=CHAR_MIN-1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_BYTE=CHAR_MIN-1
+ self.has_warned(w)
def test_ubyte_max(self):
- ts.T_UBYTE=UCHAR_MAX+1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_UBYTE=UCHAR_MAX+1
+ self.has_warned(w)
def test_short_max(self):
- ts.T_SHORT=SHRT_MAX+1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_SHORT=SHRT_MAX+1
+ self.has_warned(w)
def test_short_min(self):
- ts.T_SHORT=SHRT_MIN-1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_SHORT=SHRT_MIN-1
+ self.has_warned(w)
def test_ushort_max(self):
- ts.T_USHORT=USHRT_MAX+1
- self.has_warned()
+ with test_support.catch_warning() as w:
+ ts.T_USHORT=USHRT_MAX+1
+ self.has_warned(w)
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index 6fbb3cc..1ff0e4d 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -1,11 +1,17 @@
"""Supporting definitions for the Python regression tests."""
if __name__ != 'test.test_support':
- raise ImportError, 'test_support must be imported from the test package'
+ raise ImportError('test_support must be imported from the test package')
-from contextlib import contextmanager
+import contextlib
+import errno
+import socket
import sys
+import os
+import os.path
import warnings
+import types
+import unittest
class Error(Exception):
"""Base class for regression test exceptions."""
@@ -54,7 +60,6 @@ def unload(name):
pass
def unlink(filename):
- import os
try:
os.unlink(filename)
except OSError:
@@ -64,7 +69,6 @@ def forget(modname):
'''"Forget" a module was ever imported by removing it from sys.modules and
deleting any .pyc and .pyo files.'''
unload(modname)
- import os
for dirname in sys.path:
unlink(os.path.join(dirname, modname + os.extsep + 'pyc'))
# Deleting the .pyo file cannot be within the 'try' for the .pyc since
@@ -96,7 +100,6 @@ def bind_port(sock, host='', preferred_port=54321):
tests and we don't try multiple ports, the test can fails. This
makes the test more robust."""
- import socket, errno
# some random ports that hopefully no one is listening on.
for port in [preferred_port, 9907, 10243, 32999]:
try:
@@ -107,7 +110,7 @@ def bind_port(sock, host='', preferred_port=54321):
if err != errno.EADDRINUSE:
raise
print(' WARNING: failed to listen on port %d, trying another' % port, file=sys.__stderr__)
- raise TestFailed, 'unable to find port to listen on'
+ raise TestFailed('unable to find port to listen on')
FUZZ = 1e-6
@@ -135,7 +138,6 @@ except NameError:
is_jython = sys.platform.startswith('java')
-import os
# Filename used for testing
if os.name == 'java':
# Jython disallows @ in module names
@@ -197,13 +199,12 @@ except IOError:
if fp is not None:
fp.close()
unlink(TESTFN)
-del os, fp
+del fp
def findfile(file, here=__file__):
"""Try to find a file on sys.path and the working directory. If it is not
found the argument passed to the function is returned (this does not
necessarily signal failure; could still be the legitimate path)."""
- import os
if os.path.isabs(file):
return file
path = sys.path
@@ -235,7 +236,7 @@ def vereq(a, b):
"""
if not (a == b):
- raise TestFailed, "%r == %r" % (a, b)
+ raise TestFailed("%r == %r" % (a, b))
def sortdict(dict):
"Like repr(dict), but in sorted order."
@@ -254,7 +255,6 @@ def check_syntax_error(testcase, statement):
def open_urlresource(url):
import urllib, urlparse
- import os.path
filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
@@ -268,7 +268,7 @@ def open_urlresource(url):
fn, _ = urllib.urlretrieve(url, filename)
return open(fn)
-@contextmanager
+@contextlib.contextmanager
def guard_warnings_filter():
"""Guard the warnings filter from being permanently changed."""
original_filters = warnings.filters[:]
@@ -277,14 +277,49 @@ def guard_warnings_filter():
finally:
warnings.filters = original_filters
+class WarningMessage(object):
+ "Holds the result of the latest showwarning() call"
+ def __init__(self):
+ self.message = None
+ self.category = None
+ self.filename = None
+ self.lineno = None
+
+ def _showwarning(self, message, category, filename, lineno, file=None):
+ self.message = message
+ self.category = category
+ self.filename = filename
+ self.lineno = lineno
+
+@contextlib.contextmanager
+def catch_warning():
+ """
+ Guard the warnings filter from being permanently changed and record the
+ data of the last warning that has been issued.
+
+ Use like this:
+
+ with catch_warning as w:
+ warnings.warn("foo")
+ assert str(w.message) == "foo"
+ """
+ warning = WarningMessage()
+ original_filters = warnings.filters[:]
+ original_showwarning = warnings.showwarning
+ warnings.showwarning = warning._showwarning
+ try:
+ yield warning
+ finally:
+ warnings.showwarning = original_showwarning
+ warnings.filters = original_filters
+
class EnvironmentVarGuard(object):
"""Class to help protect the environment variable properly. Can be used as
a context manager."""
def __init__(self):
- from os import environ
- self._environ = environ
+ self._environ = os.environ
self._unset = set()
self._reset = dict()
@@ -309,6 +344,40 @@ class EnvironmentVarGuard(object):
for unset in self._unset:
del self._environ[unset]
+class TransientResource(object):
+
+ """Raise ResourceDenied if an exception is raised while the context manager
+ is in effect that matches the specified exception and attributes."""
+
+ def __init__(self, exc, **kwargs):
+ self.exc = exc
+ self.attrs = kwargs
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type_=None, value=None, traceback=None):
+ """If type_ is a subclass of self.exc and value has attributes matching
+ self.attrs, raise ResourceDenied. Otherwise let the exception
+ propagate (if any)."""
+ if type_ is not None and issubclass(self.exc, type_):
+ for attr, attr_value in self.attrs.items():
+ if not hasattr(value, attr):
+ break
+ if getattr(value, attr) != attr_value:
+ break
+ else:
+ raise ResourceDenied("an optional resource is not available")
+
+
+def transient_internet():
+ """Return a context manager that raises ResourceDenied when various issues
+ with the Internet connection manifest themselves as exceptions."""
+ time_out = TransientResource(IOError, errno=errno.ETIMEDOUT)
+ socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET)
+ ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
+ return contextlib.nested(time_out, socket_peer_reset, ioerror_peer_reset)
+
#=======================================================================
# Decorator for running a function in a different locale, correctly resetting
@@ -432,10 +501,7 @@ def bigaddrspacetest(f):
return wrapper
#=======================================================================
-# Preliminary PyUNIT integration.
-
-import unittest
-
+# unittest integration.
class BasicTestRunner:
def run(self, test):
@@ -444,7 +510,7 @@ class BasicTestRunner:
return result
-def run_suite(suite, testclass=None):
+def _run_suite(suite):
"""Run tests from a unittest.TestSuite-derived class."""
if verbose:
runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
@@ -458,28 +524,26 @@ def run_suite(suite, testclass=None):
elif len(result.failures) == 1 and not result.errors:
err = result.failures[0][1]
else:
- if testclass is None:
- msg = "errors occurred; run in verbose mode for details"
- else:
- msg = "errors occurred in %s.%s" \
- % (testclass.__module__, testclass.__name__)
+ msg = "errors occurred; run in verbose mode for details"
raise TestFailed(msg)
raise TestFailed(err)
def run_unittest(*classes):
"""Run tests from unittest.TestCase-derived classes."""
+ valid_types = (unittest.TestSuite, unittest.TestCase)
suite = unittest.TestSuite()
for cls in classes:
- if isinstance(cls, (unittest.TestSuite, unittest.TestCase)):
+ if isinstance(cls, str):
+ if cls in sys.modules:
+ suite.addTest(unittest.findTestCases(sys.modules[cls]))
+ else:
+ raise ValueError("str arguments must be keys in sys.modules")
+ elif isinstance(cls, valid_types):
suite.addTest(cls)
else:
suite.addTest(unittest.makeSuite(cls))
- if len(classes)==1:
- testclass = classes[0]
- else:
- testclass = None
- run_suite(suite, testclass)
+ _run_suite(suite)
#=======================================================================
@@ -545,7 +609,6 @@ def reap_children():
# Reap all our dead child processes so we don't leave zombies around.
# These hog resources and might be causing some of the buildbots to die.
- import os
if hasattr(os, 'waitpid'):
any_process = -1
while True:
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index b5a5c5d..2b48ea6 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -374,7 +374,7 @@ Misuse of the nonlocal statement can lead to a few unique syntax errors.
Traceback (most recent call last):
...
SyntaxError: name 'x' is parameter and nonlocal
-
+
>>> def f():
... global x
... nonlocal x
@@ -403,7 +403,7 @@ TODO(jhylton): Figure out how to test SyntaxWarning with doctest.
## Traceback (most recent call last):
## ...
## SyntaxWarning: name 'x' is assigned to before nonlocal declaration
-
+
## >>> def f():
## ... x = 1
## ... nonlocal x
@@ -411,7 +411,56 @@ TODO(jhylton): Figure out how to test SyntaxWarning with doctest.
## ...
## SyntaxWarning: name 'x' is assigned to before nonlocal declaration
-
+
+This tests assignment-context; there was a bug in Python 2.5 where compiling
+a complex 'if' (one with 'elif') would fail to notice an invalid suite,
+leading to spurious errors.
+
+ >>> if 1:
+ ... x() = 1
+ ... elif 1:
+ ... pass
+ Traceback (most recent call last):
+ ...
+ SyntaxError: can't assign to function call (<doctest test.test_syntax[48]>, line 2)
+
+ >>> if 1:
+ ... pass
+ ... elif 1:
+ ... x() = 1
+ Traceback (most recent call last):
+ ...
+ SyntaxError: can't assign to function call (<doctest test.test_syntax[49]>, line 4)
+
+ >>> if 1:
+ ... x() = 1
+ ... elif 1:
+ ... pass
+ ... else:
+ ... pass
+ Traceback (most recent call last):
+ ...
+ SyntaxError: can't assign to function call (<doctest test.test_syntax[50]>, line 2)
+
+ >>> if 1:
+ ... pass
+ ... elif 1:
+ ... x() = 1
+ ... else:
+ ... pass
+ Traceback (most recent call last):
+ ...
+ SyntaxError: can't assign to function call (<doctest test.test_syntax[51]>, line 4)
+
+ >>> if 1:
+ ... pass
+ ... elif 1:
+ ... pass
+ ... else:
+ ... x() = 1
+ Traceback (most recent call last):
+ ...
+ SyntaxError: can't assign to function call (<doctest test.test_syntax[52]>, line 6)
"""
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index e9bf497..ac7dca3 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1,8 +1,12 @@
+# encoding: iso8859-1
+
import sys
import os
import shutil
import tempfile
import StringIO
+import md5
+import errno
import unittest
import tarfile
@@ -20,452 +24,547 @@ try:
except ImportError:
bz2 = None
+def md5sum(data):
+ return md5.new(data).hexdigest()
+
def path(path):
return test_support.findfile(path)
-testtar = path("testtar.tar")
-tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir")
-tempname = test_support.TESTFN
-membercount = 12
-
-def tarname(comp=""):
- if not comp:
- return testtar
- return os.path.join(tempdir, "%s%s%s" % (testtar, os.extsep, comp))
+TEMPDIR = os.path.join(tempfile.gettempdir(), "test_tarfile_tmp")
+tarname = path("testtar.tar")
+gzipname = os.path.join(TEMPDIR, "testtar.tar.gz")
+bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2")
+tmpname = os.path.join(TEMPDIR, "tmp.tar")
-def dirname():
- if not os.path.exists(tempdir):
- os.mkdir(tempdir)
- return tempdir
+md5_regtype = "65f477c818ad9e15f7feab0c6d37742f"
+md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6"
-def tmpname():
- return tempname
+class ReadTest(unittest.TestCase):
-class BaseTest(unittest.TestCase):
- comp = ''
- mode = 'r'
- sep = ':'
+ tarname = tarname
+ mode = "r:"
def setUp(self):
- mode = self.mode + self.sep + self.comp
- self.tar = tarfile.open(tarname(self.comp), mode)
+ self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1")
def tearDown(self):
self.tar.close()
-class ReadTest(BaseTest):
- def test(self):
- """Test member extraction.
- """
- members = 0
+class UstarReadTest(ReadTest):
+
+ def test_fileobj_regular_file(self):
+ tarinfo = self.tar.getmember("ustar/regtype")
+ fobj = self.tar.extractfile(tarinfo)
+ data = fobj.read()
+ self.assert_((len(data), md5sum(data)) == (tarinfo.size, md5_regtype),
+ "regular file extraction failed")
+
+ def test_fileobj_readlines(self):
+ self.tar.extract("ustar/regtype", TEMPDIR)
+ tarinfo = self.tar.getmember("ustar/regtype")
+ fobj1 = open(os.path.join(TEMPDIR, "ustar/regtype"), "rU")
+ fobj2 = self.tar.extractfile(tarinfo)
+
+ lines1 = fobj1.readlines()
+ lines2 = fobj2.readlines()
+ self.assert_(lines1 == lines2,
+ "fileobj.readlines() failed")
+ self.assert_(len(lines2) == 114,
+ "fileobj.readlines() failed")
+ self.assert_(lines2[83] == \
+ "I will gladly admit that Python is not the fastest running scripting language.\n",
+ "fileobj.readlines() failed")
+
+ def test_fileobj_iter(self):
+ self.tar.extract("ustar/regtype", TEMPDIR)
+ tarinfo = self.tar.getmember("ustar/regtype")
+ fobj1 = open(os.path.join(TEMPDIR, "ustar/regtype"), "rU")
+ fobj2 = self.tar.extractfile(tarinfo)
+ lines1 = fobj1.readlines()
+ lines2 = [line for line in fobj2]
+ self.assert_(lines1 == lines2,
+ "fileobj.__iter__() failed")
+
+ def test_fileobj_seek(self):
+ self.tar.extract("ustar/regtype", TEMPDIR)
+ fobj = open(os.path.join(TEMPDIR, "ustar/regtype"), "rb")
+ data = fobj.read()
+ fobj.close()
+
+ tarinfo = self.tar.getmember("ustar/regtype")
+ fobj = self.tar.extractfile(tarinfo)
+
+ text = fobj.read()
+ fobj.seek(0)
+ self.assert_(0 == fobj.tell(),
+ "seek() to file's start failed")
+ fobj.seek(2048, 0)
+ self.assert_(2048 == fobj.tell(),
+ "seek() to absolute position failed")
+ fobj.seek(-1024, 1)
+ self.assert_(1024 == fobj.tell(),
+ "seek() to negative relative position failed")
+ fobj.seek(1024, 1)
+ self.assert_(2048 == fobj.tell(),
+ "seek() to positive relative position failed")
+ s = fobj.read(10)
+ self.assert_(s == data[2048:2058],
+ "read() after seek failed")
+ fobj.seek(0, 2)
+ self.assert_(tarinfo.size == fobj.tell(),
+ "seek() to file's end failed")
+ self.assert_(fobj.read() == "",
+ "read() at file's end did not return empty string")
+ fobj.seek(-tarinfo.size, 2)
+ self.assert_(0 == fobj.tell(),
+ "relative seek() to file's start failed")
+ fobj.seek(512)
+ s1 = fobj.readlines()
+ fobj.seek(512)
+ s2 = fobj.readlines()
+ self.assert_(s1 == s2,
+ "readlines() after seek failed")
+ fobj.seek(0)
+ self.assert_(len(fobj.readline()) == fobj.tell(),
+ "tell() after readline() failed")
+ fobj.seek(512)
+ self.assert_(len(fobj.readline()) + 512 == fobj.tell(),
+ "tell() after seek() and readline() failed")
+ fobj.seek(0)
+ line = fobj.readline()
+ self.assert_(fobj.read() == data[len(line):],
+ "read() after readline() failed")
+ fobj.close()
+
+
+class MiscReadTest(ReadTest):
+
+ def test_no_filename(self):
+ fobj = open(self.tarname, "rb")
+ tar = tarfile.open(fileobj=fobj, mode=self.mode)
+ self.assertEqual(tar.name, os.path.abspath(fobj.name))
+
+ def test_fail_comp(self):
+ # For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file.
+ if self.mode == "r:":
+ return
+ self.assertRaises(tarfile.ReadError, tarfile.open, tarname, self.mode)
+ fobj = open(tarname, "rb")
+ self.assertRaises(tarfile.ReadError, tarfile.open, fileobj=fobj, mode=self.mode)
+
+ def test_v7_dirtype(self):
+ # Test old style dirtype member (bug #1336623):
+ # Old V7 tars create directory members using an AREGTYPE
+ # header with a "/" appended to the filename field.
+ tarinfo = self.tar.getmember("misc/dirtype-old-v7")
+ self.assert_(tarinfo.type == tarfile.DIRTYPE,
+ "v7 dirtype failed")
+
+ def test_check_members(self):
for tarinfo in self.tar:
- members += 1
- if not tarinfo.isreg():
+ self.assert_(int(tarinfo.mtime) == 07606136617,
+ "wrong mtime for %s" % tarinfo.name)
+ if not tarinfo.name.startswith("ustar/"):
continue
- f = self.tar.extractfile(tarinfo)
- self.assert_(len(f.read()) == tarinfo.size,
- "size read does not match expected size")
- f.close()
-
- self.assert_(members == membercount,
- "could not find all members")
-
- def test_sparse(self):
- """Test sparse member extraction.
- """
- if self.sep != "|":
- f1 = self.tar.extractfile("S-SPARSE")
- f2 = self.tar.extractfile("S-SPARSE-WITH-NULLS")
- self.assert_(f1.read() == f2.read(),
- "_FileObject failed on sparse file member")
-
- def test_readlines(self):
- """Test readlines() method of _FileObject.
- """
- if self.sep != "|":
- filename = "0-REGTYPE-TEXT"
- self.tar.extract(filename, dirname())
- f = open(os.path.join(dirname(), filename), "rU")
- lines1 = f.readlines()
- f.close()
- lines2 = self.tar.extractfile(filename).readlines()
- self.assert_(lines1 == lines2,
- "_FileObject.readline() does not work correctly")
-
- def test_iter(self):
- # Test iteration over ExFileObject.
- if self.sep != "|":
- filename = "0-REGTYPE-TEXT"
- self.tar.extract(filename, dirname())
- f = open(os.path.join(dirname(), filename), "rU")
- lines1 = f.readlines()
- f.close()
- lines2 = [line for line in self.tar.extractfile(filename)]
- self.assert_(lines1 == lines2,
- "ExFileObject iteration does not work correctly")
-
- def test_seek(self):
- """Test seek() method of _FileObject, incl. random reading.
- """
- if self.sep != "|":
- filename = "0-REGTYPE-TEXT"
- self.tar.extract(filename, dirname())
- f = open(os.path.join(dirname(), filename), "rb")
- data = f.read()
- f.close()
-
- tarinfo = self.tar.getmember(filename)
- fobj = self.tar.extractfile(tarinfo)
-
- text = fobj.read()
- fobj.seek(0)
- self.assert_(0 == fobj.tell(),
- "seek() to file's start failed")
- fobj.seek(2048, 0)
- self.assert_(2048 == fobj.tell(),
- "seek() to absolute position failed")
- fobj.seek(-1024, 1)
- self.assert_(1024 == fobj.tell(),
- "seek() to negative relative position failed")
- fobj.seek(1024, 1)
- self.assert_(2048 == fobj.tell(),
- "seek() to positive relative position failed")
- s = fobj.read(10)
- self.assert_(s == data[2048:2058],
- "read() after seek failed")
- fobj.seek(0, 2)
- self.assert_(tarinfo.size == fobj.tell(),
- "seek() to file's end failed")
- self.assert_(fobj.read() == "",
- "read() at file's end did not return empty string")
- fobj.seek(-tarinfo.size, 2)
- self.assert_(0 == fobj.tell(),
- "relative seek() to file's start failed")
- fobj.seek(512)
- s1 = fobj.readlines()
- fobj.seek(512)
- s2 = fobj.readlines()
- self.assert_(s1 == s2,
- "readlines() after seek failed")
- fobj.seek(0)
- self.assert_(len(fobj.readline()) == fobj.tell(),
- "tell() after readline() failed")
- fobj.seek(512)
- self.assert_(len(fobj.readline()) + 512 == fobj.tell(),
- "tell() after seek() and readline() failed")
- fobj.seek(0)
- line = fobj.readline()
- self.assert_(fobj.read() == data[len(line):],
- "read() after readline() failed")
- fobj.close()
+ self.assert_(tarinfo.uname == "tarfile",
+ "wrong uname for %s" % tarinfo.name)
- def test_old_dirtype(self):
- """Test old style dirtype member (bug #1336623).
- """
- # Old tars create directory members using a REGTYPE
- # header with a "/" appended to the filename field.
+ def test_find_members(self):
+ self.assert_(self.tar.getmembers()[-1].name == "misc/eof",
+ "could not find all members")
- # Create an old tar style directory entry.
- filename = tmpname()
- tarinfo = tarfile.TarInfo("directory/")
- tarinfo.type = tarfile.REGTYPE
+ def test_extract_hardlink(self):
+ # Test hardlink extraction (e.g. bug #857297).
+ tar = tarfile.open(tarname, errorlevel=1, encoding="iso8859-1")
- fobj = open(filename, "w")
- fobj.write(tarinfo.tobuf())
- fobj.close()
+ tar.extract("ustar/regtype", TEMPDIR)
+ try:
+ tar.extract("ustar/lnktype", TEMPDIR)
+ except EnvironmentError as e:
+ if e.errno == errno.ENOENT:
+ self.fail("hardlink not extracted properly")
+
+ data = open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb").read()
+ self.assertEqual(md5sum(data), md5_regtype)
try:
- # Test if it is still a directory entry when
- # read back.
- tar = tarfile.open(filename)
- tarinfo = tar.getmembers()[0]
- tar.close()
-
- self.assert_(tarinfo.type == tarfile.DIRTYPE)
- self.assert_(tarinfo.name.endswith("/"))
- finally:
- try:
- os.unlink(filename)
- except:
- pass
-
-class ReadStreamTest(ReadTest):
- sep = "|"
-
- def test(self):
- """Test member extraction, and for StreamError when
- seeking backwards.
- """
- ReadTest.test(self)
- tarinfo = self.tar.getmembers()[0]
- f = self.tar.extractfile(tarinfo)
+ tar.extract("ustar/symtype", TEMPDIR)
+ except EnvironmentError as e:
+ if e.errno == errno.ENOENT:
+ self.fail("symlink not extracted properly")
+
+ data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read()
+ self.assertEqual(md5sum(data), md5_regtype)
+
+
+class StreamReadTest(ReadTest):
+
+ mode="r|"
+
+ def test_fileobj_regular_file(self):
+ tarinfo = self.tar.next() # get "regtype" (can't use getmember)
+ fobj = self.tar.extractfile(tarinfo)
+ data = fobj.read()
+ self.assert_((len(data), md5sum(data)) == (tarinfo.size, md5_regtype),
+ "regular file extraction failed")
+
+ def test_provoke_stream_error(self):
+ tarinfos = self.tar.getmembers()
+ f = self.tar.extractfile(tarinfos[0]) # read the first member
self.assertRaises(tarfile.StreamError, f.read)
- def test_stream(self):
- """Compare the normal tar and the stream tar.
- """
- stream = self.tar
- tar = tarfile.open(tarname(), 'r')
+ def test_compare_members(self):
+ tar1 = tarfile.open(tarname, encoding="iso8859-1")
+ tar2 = self.tar
- while 1:
- t1 = tar.next()
- t2 = stream.next()
+ while True:
+ t1 = tar1.next()
+ t2 = tar2.next()
if t1 is None:
break
self.assert_(t2 is not None, "stream.next() failed.")
if t2.islnk() or t2.issym():
- self.assertRaises(tarfile.StreamError, stream.extractfile, t2)
+ self.assertRaises(tarfile.StreamError, tar2.extractfile, t2)
continue
- v1 = tar.extractfile(t1)
- v2 = stream.extractfile(t2)
+
+ v1 = tar1.extractfile(t1)
+ v2 = tar2.extractfile(t2)
if v1 is None:
continue
self.assert_(v2 is not None, "stream.extractfile() failed")
self.assert_(v1.read() == v2.read(), "stream extraction failed")
- tar.close()
- stream.close()
+ tar1.close()
-class ReadDetectTest(ReadTest):
- def setUp(self):
- self.tar = tarfile.open(tarname(self.comp), self.mode)
+class DetectReadTest(unittest.TestCase):
-class ReadDetectFileobjTest(ReadTest):
+ def _testfunc_file(self, name, mode):
+ try:
+ tarfile.open(name, mode)
+ except tarfile.ReadError:
+ self.fail()
- def setUp(self):
- name = tarname(self.comp)
- self.tar = tarfile.open(name, mode=self.mode,
- fileobj=open(name, "rb"))
+ def _testfunc_fileobj(self, name, mode):
+ try:
+ tarfile.open(name, mode, fileobj=open(name, "rb"))
+ except tarfile.ReadError:
+ self.fail()
-class ReadAsteriskTest(ReadTest):
+ def _test_modes(self, testfunc):
+ testfunc(tarname, "r")
+ testfunc(tarname, "r:")
+ testfunc(tarname, "r:*")
+ testfunc(tarname, "r|")
+ testfunc(tarname, "r|*")
- def setUp(self):
- mode = self.mode + self.sep + "*"
- self.tar = tarfile.open(tarname(self.comp), mode)
+ if gzip:
+ self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r:gz")
+ self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r|gz")
+ self.assertRaises(tarfile.ReadError, tarfile.open, gzipname, mode="r:")
+ self.assertRaises(tarfile.ReadError, tarfile.open, gzipname, mode="r|")
-class ReadStreamAsteriskTest(ReadStreamTest):
+ testfunc(gzipname, "r")
+ testfunc(gzipname, "r:*")
+ testfunc(gzipname, "r:gz")
+ testfunc(gzipname, "r|*")
+ testfunc(gzipname, "r|gz")
- def setUp(self):
- mode = self.mode + self.sep + "*"
- self.tar = tarfile.open(tarname(self.comp), mode)
+ if bz2:
+ self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r:bz2")
+ self.assertRaises(tarfile.ReadError, tarfile.open, tarname, mode="r|bz2")
+ self.assertRaises(tarfile.ReadError, tarfile.open, bz2name, mode="r:")
+ self.assertRaises(tarfile.ReadError, tarfile.open, bz2name, mode="r|")
-class WriteTest(BaseTest):
- mode = 'w'
+ testfunc(bz2name, "r")
+ testfunc(bz2name, "r:*")
+ testfunc(bz2name, "r:bz2")
+ testfunc(bz2name, "r|*")
+ testfunc(bz2name, "r|bz2")
- def setUp(self):
- mode = self.mode + self.sep + self.comp
- self.src = tarfile.open(tarname(self.comp), 'r')
- self.dstname = tmpname()
- self.dst = tarfile.open(self.dstname, mode)
+ def test_detect_file(self):
+ self._test_modes(self._testfunc_file)
- def tearDown(self):
- self.src.close()
- self.dst.close()
+ def test_detect_fileobj(self):
+ self._test_modes(self._testfunc_fileobj)
- def test_posix(self):
- self.dst.posix = 1
- self._test()
- def test_nonposix(self):
- self.dst.posix = 0
- self._test()
+class MemberReadTest(ReadTest):
- def test_small(self):
- self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1"))
- self.dst.close()
- self.assertNotEqual(os.stat(self.dstname).st_size, 0)
+ def _test_member(self, tarinfo, chksum=None, **kwargs):
+ if chksum is not None:
+ self.assert_(md5sum(self.tar.extractfile(tarinfo).read()) == chksum,
+ "wrong md5sum for %s" % tarinfo.name)
- def _test(self):
- for tarinfo in self.src:
- if not tarinfo.isreg():
- continue
- f = self.src.extractfile(tarinfo)
- if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME and "/" not in tarinfo.name:
- self.assertRaises(ValueError, self.dst.addfile,
- tarinfo, f)
- else:
- self.dst.addfile(tarinfo, f)
+ kwargs["mtime"] = 07606136617
+ kwargs["uid"] = 1000
+ kwargs["gid"] = 100
+ if "old-v7" not in tarinfo.name:
+ # V7 tar can't handle alphabetic owners.
+ kwargs["uname"] = "tarfile"
+ kwargs["gname"] = "tarfile"
+ for k, v in kwargs.items():
+ self.assert_(getattr(tarinfo, k) == v,
+ "wrong value in %s field of %s" % (k, tarinfo.name))
- def test_add_self(self):
- dstname = os.path.abspath(self.dstname)
+ def test_find_regtype(self):
+ tarinfo = self.tar.getmember("ustar/regtype")
+ self._test_member(tarinfo, size=7011, chksum=md5_regtype)
- self.assertEqual(self.dst.name, dstname, "archive name must be absolute")
+ def test_find_conttype(self):
+ tarinfo = self.tar.getmember("ustar/conttype")
+ self._test_member(tarinfo, size=7011, chksum=md5_regtype)
- self.dst.add(dstname)
- self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
+ def test_find_dirtype(self):
+ tarinfo = self.tar.getmember("ustar/dirtype")
+ self._test_member(tarinfo, size=0)
- cwd = os.getcwd()
- os.chdir(dirname())
- self.dst.add(dstname)
- os.chdir(cwd)
- self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
+ def test_find_dirtype_with_size(self):
+ tarinfo = self.tar.getmember("ustar/dirtype-with-size")
+ self._test_member(tarinfo, size=255)
+ def test_find_lnktype(self):
+ tarinfo = self.tar.getmember("ustar/lnktype")
+ self._test_member(tarinfo, size=0, linkname="ustar/regtype")
-class AppendTest(unittest.TestCase):
- # Test append mode (cp. patch #1652681).
+ def test_find_symtype(self):
+ tarinfo = self.tar.getmember("ustar/symtype")
+ self._test_member(tarinfo, size=0, linkname="regtype")
- def setUp(self):
- self.tarname = tmpname()
- if os.path.exists(self.tarname):
- os.remove(self.tarname)
+ def test_find_blktype(self):
+ tarinfo = self.tar.getmember("ustar/blktype")
+ self._test_member(tarinfo, size=0, devmajor=3, devminor=0)
- def _add_testfile(self, fileobj=None):
- tar = tarfile.open(self.tarname, "a", fileobj=fileobj)
- tar.addfile(tarfile.TarInfo("bar"))
- tar.close()
+ def test_find_chrtype(self):
+ tarinfo = self.tar.getmember("ustar/chrtype")
+ self._test_member(tarinfo, size=0, devmajor=1, devminor=3)
- def _create_testtar(self):
- src = tarfile.open(tarname())
- t = src.getmember("0-REGTYPE")
- t.name = "foo"
- f = src.extractfile(t)
- tar = tarfile.open(self.tarname, "w")
- tar.addfile(t, f)
- tar.close()
+ def test_find_fifotype(self):
+ tarinfo = self.tar.getmember("ustar/fifotype")
+ self._test_member(tarinfo, size=0)
- def _test(self, names=["bar"], fileobj=None):
- tar = tarfile.open(self.tarname, fileobj=fileobj)
- self.assert_(tar.getnames() == names)
+ def test_find_sparse(self):
+ tarinfo = self.tar.getmember("ustar/sparse")
+ self._test_member(tarinfo, size=86016, chksum=md5_sparse)
- def test_non_existing(self):
- self._add_testfile()
- self._test()
+ def test_find_umlauts(self):
+ tarinfo = self.tar.getmember("ustar/umlauts-ÄÖÜäöüß")
+ self._test_member(tarinfo, size=7011, chksum=md5_regtype)
- def test_empty(self):
- open(self.tarname, "wb").close()
- self._add_testfile()
- self._test()
+ def test_find_ustar_longname(self):
+ name = "ustar/" + "12345/" * 39 + "1234567/longname"
+ self.assert_(name in self.tar.getnames())
- def test_empty_fileobj(self):
- fobj = StringIO.StringIO()
- self._add_testfile(fobj)
- fobj.seek(0)
- self._test(fileobj=fobj)
+ def test_find_regtype_oldv7(self):
+ tarinfo = self.tar.getmember("misc/regtype-old-v7")
+ self._test_member(tarinfo, size=7011, chksum=md5_regtype)
- def test_fileobj(self):
- self._create_testtar()
- data = open(self.tarname, "rb").read()
- fobj = StringIO.StringIO(data)
- self._add_testfile(fobj)
- fobj.seek(0)
- self._test(names=["foo", "bar"], fileobj=fobj)
+ def test_find_pax_umlauts(self):
+ self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1")
+ tarinfo = self.tar.getmember("pax/umlauts-ÄÖÜäöüß")
+ self._test_member(tarinfo, size=7011, chksum=md5_regtype)
- def test_existing(self):
- self._create_testtar()
- self._add_testfile()
- self._test(names=["foo", "bar"])
+class LongnameTest(ReadTest):
-class Write100Test(BaseTest):
- # The name field in a tar header stores strings of at most 100 chars.
- # If a string is shorter than 100 chars it has to be padded with '\0',
- # which implies that a string of exactly 100 chars is stored without
- # a trailing '\0'.
+ def test_read_longname(self):
+ # Test reading of longname (bug #1471427).
+ name = self.subdir + "/" + "123/" * 125 + "longname"
+ try:
+ tarinfo = self.tar.getmember(name)
+ except KeyError:
+ self.fail("longname not found")
+ self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
- def setUp(self):
- self.name = "01234567890123456789012345678901234567890123456789"
- self.name += "01234567890123456789012345678901234567890123456789"
+ def test_read_longlink(self):
+ longname = self.subdir + "/" + "123/" * 125 + "longname"
+ longlink = self.subdir + "/" + "123/" * 125 + "longlink"
+ try:
+ tarinfo = self.tar.getmember(longlink)
+ except KeyError:
+ self.fail("longlink not found")
+ self.assert_(tarinfo.linkname == longname, "linkname wrong")
- self.tar = tarfile.open(tmpname(), "w")
- t = tarfile.TarInfo(self.name)
- self.tar.addfile(t)
- self.tar.close()
+ def test_truncated_longname(self):
+ longname = self.subdir + "/" + "123/" * 125 + "longname"
+ tarinfo = self.tar.getmember(longname)
+ offset = tarinfo.offset
+ self.tar.fileobj.seek(offset)
+ fobj = StringIO.StringIO(self.tar.fileobj.read(1536))
+ self.assertRaises(tarfile.ReadError, tarfile.open, name="foo.tar", fileobj=fobj)
- self.tar = tarfile.open(tmpname())
- def tearDown(self):
- self.tar.close()
+class GNUReadTest(LongnameTest):
- def test(self):
- self.assertEqual(self.tar.getnames()[0], self.name,
- "failed to store 100 char filename")
+ subdir = "gnu"
+ def test_sparse_file(self):
+ tarinfo1 = self.tar.getmember("ustar/sparse")
+ fobj1 = self.tar.extractfile(tarinfo1)
+ tarinfo2 = self.tar.getmember("gnu/sparse")
+ fobj2 = self.tar.extractfile(tarinfo2)
+ self.assert_(fobj1.read() == fobj2.read(),
+ "sparse file extraction failed")
-class WriteSize0Test(BaseTest):
- mode = 'w'
- def setUp(self):
- self.tmpdir = dirname()
- self.dstname = tmpname()
- self.dst = tarfile.open(self.dstname, "w")
+class PaxReadTest(ReadTest):
- def tearDown(self):
- self.dst.close()
+ subdir = "pax"
+
+ def test_pax_globheaders(self):
+ tar = tarfile.open(tarname, encoding="iso8859-1")
+ tarinfo = tar.getmember("pax/regtype1")
+ self.assertEqual(tarinfo.uname, "foo")
+ self.assertEqual(tarinfo.gname, "bar")
+ self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "ÄÖÜäöüß")
+
+ tarinfo = tar.getmember("pax/regtype2")
+ self.assertEqual(tarinfo.uname, "")
+ self.assertEqual(tarinfo.gname, "bar")
+ self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "ÄÖÜäöüß")
+
+ tarinfo = tar.getmember("pax/regtype3")
+ self.assertEqual(tarinfo.uname, "tarfile")
+ self.assertEqual(tarinfo.gname, "tarfile")
+ self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"), "ÄÖÜäöüß")
+
+
+class WriteTest(unittest.TestCase):
+
+ mode = "w:"
+
+ def test_100_char_name(self):
+ # The name field in a tar header stores strings of at most 100 chars.
+ # If a string is shorter than 100 chars it has to be padded with '\0',
+ # which implies that a string of exactly 100 chars is stored without
+ # a trailing '\0'.
+ name = "0123456789" * 10
+ tar = tarfile.open(tmpname, self.mode)
+ t = tarfile.TarInfo(name)
+ tar.addfile(t)
+ tar.close()
+
+ tar = tarfile.open(tmpname)
+ self.assert_(tar.getnames()[0] == name,
+ "failed to store 100 char filename")
+ tar.close()
+
+ def test_tar_size(self):
+ # Test for bug #1013882.
+ tar = tarfile.open(tmpname, self.mode)
+ path = os.path.join(TEMPDIR, "file")
+ fobj = open(path, "wb")
+ fobj.write("aaa")
+ fobj.close()
+ tar.add(path)
+ tar.close()
+ self.assert_(os.path.getsize(tmpname) > 0,
+ "tarfile is empty")
+
+ # The test_*_size tests test for bug #1167128.
+ def test_file_size(self):
+ tar = tarfile.open(tmpname, self.mode)
- def test_file(self):
- path = os.path.join(self.tmpdir, "file")
- f = open(path, "w")
- f.close()
- tarinfo = self.dst.gettarinfo(path)
+ path = os.path.join(TEMPDIR, "file")
+ fobj = open(path, "wb")
+ fobj.close()
+ tarinfo = tar.gettarinfo(path)
self.assertEqual(tarinfo.size, 0)
- f = open(path, "w")
- f.write("aaa")
- f.close()
- tarinfo = self.dst.gettarinfo(path)
+
+ fobj = open(path, "wb")
+ fobj.write("aaa")
+ fobj.close()
+ tarinfo = tar.gettarinfo(path)
self.assertEqual(tarinfo.size, 3)
- def test_directory(self):
- path = os.path.join(self.tmpdir, "directory")
- if os.path.exists(path):
- # This shouldn't be necessary, but is <wink> if a previous
- # run was killed in mid-stream.
- shutil.rmtree(path)
- os.mkdir(path)
- tarinfo = self.dst.gettarinfo(path)
- self.assertEqual(tarinfo.size, 0)
+ tar.close()
- def test_symlink(self):
+ def test_directory_size(self):
+ path = os.path.join(TEMPDIR, "directory")
+ os.mkdir(path)
+ try:
+ tar = tarfile.open(tmpname, self.mode)
+ tarinfo = tar.gettarinfo(path)
+ self.assertEqual(tarinfo.size, 0)
+ finally:
+ os.rmdir(path)
+
+ def test_link_size(self):
+ if hasattr(os, "link"):
+ link = os.path.join(TEMPDIR, "link")
+ target = os.path.join(TEMPDIR, "link_target")
+ open(target, "wb").close()
+ os.link(target, link)
+ try:
+ tar = tarfile.open(tmpname, self.mode)
+ tarinfo = tar.gettarinfo(link)
+ self.assertEqual(tarinfo.size, 0)
+ finally:
+ os.remove(target)
+ os.remove(link)
+
+ def test_symlink_size(self):
if hasattr(os, "symlink"):
- path = os.path.join(self.tmpdir, "symlink")
+ path = os.path.join(TEMPDIR, "symlink")
os.symlink("link_target", path)
- tarinfo = self.dst.gettarinfo(path)
- self.assertEqual(tarinfo.size, 0)
+ try:
+ tar = tarfile.open(tmpname, self.mode)
+ tarinfo = tar.gettarinfo(path)
+ self.assertEqual(tarinfo.size, 0)
+ finally:
+ os.remove(path)
+ def test_add_self(self):
+ # Test for #1257255.
+ dstname = os.path.abspath(tmpname)
-class WriteStreamTest(WriteTest):
- sep = '|'
+ tar = tarfile.open(tmpname, self.mode)
+ self.assert_(tar.name == dstname, "archive name must be absolute")
- def test_padding(self):
- self.dst.close()
+ tar.add(dstname)
+ self.assert_(tar.getnames() == [], "added the archive to itself")
- if self.comp == "gz":
- f = gzip.GzipFile(self.dstname)
- s = f.read()
- f.close()
- elif self.comp == "bz2":
- f = bz2.BZ2Decompressor()
- s = open(self.dstname).read()
- s = f.decompress(s)
- self.assertEqual(len(f.unused_data), 0, "trailing data")
- else:
- f = open(self.dstname)
- s = f.read()
- f.close()
+ cwd = os.getcwd()
+ os.chdir(TEMPDIR)
+ tar.add(dstname)
+ os.chdir(cwd)
+ self.assert_(tar.getnames() == [], "added the archive to itself")
- self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
- "incorrect zero padding")
+class StreamWriteTest(unittest.TestCase):
-class WriteGNULongTest(unittest.TestCase):
- """This testcase checks for correct creation of GNU Longname
- and Longlink extensions.
+ mode = "w|"
- It creates a tarfile and adds empty members with either
- long names, long linknames or both and compares the size
- of the tarfile with the expected size.
+ def test_stream_padding(self):
+ # Test for bug #1543303.
+ tar = tarfile.open(tmpname, self.mode)
+ tar.close()
- It checks for SF bug #812325 in TarFile._create_gnulong().
+ if self.mode.endswith("gz"):
+ fobj = gzip.GzipFile(tmpname)
+ data = fobj.read()
+ fobj.close()
+ elif self.mode.endswith("bz2"):
+ dec = bz2.BZ2Decompressor()
+ data = open(tmpname, "rb").read()
+ data = dec.decompress(data)
+ self.assert_(len(dec.unused_data) == 0,
+ "found trailing data")
+ else:
+ fobj = open(tmpname, "rb")
+ data = fobj.read()
+ fobj.close()
+
+ self.assert_(data.count("\0") == tarfile.RECORDSIZE,
+ "incorrect zero padding")
- While I was writing this testcase, I noticed a second bug
- in the same method:
- Long{names,links} weren't null-terminated which lead to
- bad tarfiles when their length was a multiple of 512. This
- is tested as well.
- """
+
+class GNUWriteTest(unittest.TestCase):
+ # This testcase checks for correct creation of GNU Longname
+ # and Longlink extended headers (cp. bug #812325).
def _length(self, s):
blocks, remainder = divmod(len(s) + 1, 512)
@@ -474,19 +573,17 @@ class WriteGNULongTest(unittest.TestCase):
return blocks * 512
def _calc_size(self, name, link=None):
- # initial tar header
+ # Initial tar header
count = 512
if len(name) > tarfile.LENGTH_NAME:
- # gnu longname extended header + longname
+ # GNU longname extended header + longname
count += 512
count += self._length(name)
-
if link is not None and len(link) > tarfile.LENGTH_LINK:
- # gnu longlink extended header + longlink
+ # GNU longlink extended header + longlink
count += 512
count += self._length(link)
-
return count
def _test(self, name, link=None):
@@ -495,17 +592,17 @@ class WriteGNULongTest(unittest.TestCase):
tarinfo.linkname = link
tarinfo.type = tarfile.LNKTYPE
- tar = tarfile.open(tmpname(), "w")
- tar.posix = False
+ tar = tarfile.open(tmpname, "w")
+ tar.format = tarfile.GNU_FORMAT
tar.addfile(tarinfo)
v1 = self._calc_size(name, link)
v2 = tar.offset
- self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
+ self.assert_(v1 == v2, "GNU longname/longlink creation failed")
tar.close()
- tar = tarfile.open(tmpname())
+ tar = tarfile.open(tmpname)
member = tar.next()
self.failIf(member is None, "unable to read longname member")
self.assert_(tarinfo.name == member.name and \
@@ -542,268 +639,351 @@ class WriteGNULongTest(unittest.TestCase):
self._test(("longnam/" * 127) + "longname_",
("longlnk/" * 127) + "longlink_")
-class ReadGNULongTest(unittest.TestCase):
+
+class HardlinkTest(unittest.TestCase):
+ # Test the creation of LNKTYPE (hardlink) members in an archive.
def setUp(self):
- self.tar = tarfile.open(tarname())
+ self.foo = os.path.join(TEMPDIR, "foo")
+ self.bar = os.path.join(TEMPDIR, "bar")
+
+ fobj = open(self.foo, "wb")
+ fobj.write("foo")
+ fobj.close()
+
+ os.link(self.foo, self.bar)
+
+ self.tar = tarfile.open(tmpname, "w")
+ self.tar.add(self.foo)
def tearDown(self):
- self.tar.close()
+ os.remove(self.foo)
+ os.remove(self.bar)
- def test_1471427(self):
- """Test reading of longname (bug #1471427).
- """
- name = "test/" * 20 + "0-REGTYPE"
- try:
- tarinfo = self.tar.getmember(name)
- except KeyError:
- tarinfo = None
- self.assert_(tarinfo is not None, "longname not found")
- self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
+ def test_add_twice(self):
+ # The same name will be added as a REGTYPE every
+ # time regardless of st_nlink.
+ tarinfo = self.tar.gettarinfo(self.foo)
+ self.assert_(tarinfo.type == tarfile.REGTYPE,
+ "add file as regular failed")
- def test_read_name(self):
- name = ("0-LONGNAME-" * 10)[:101]
- try:
- tarinfo = self.tar.getmember(name)
- except KeyError:
- tarinfo = None
- self.assert_(tarinfo is not None, "longname not found")
+ def test_add_hardlink(self):
+ tarinfo = self.tar.gettarinfo(self.bar)
+ self.assert_(tarinfo.type == tarfile.LNKTYPE,
+ "add file as hardlink failed")
- def test_read_link(self):
- link = ("1-LONGLINK-" * 10)[:101]
- name = ("0-LONGNAME-" * 10)[:101]
- try:
- tarinfo = self.tar.getmember(link)
- except KeyError:
- tarinfo = None
- self.assert_(tarinfo is not None, "longlink not found")
- self.assert_(tarinfo.linkname == name, "linkname wrong")
+ def test_dereference_hardlink(self):
+ self.tar.dereference = True
+ tarinfo = self.tar.gettarinfo(self.bar)
+ self.assert_(tarinfo.type == tarfile.REGTYPE,
+ "dereferencing hardlink failed")
- def test_truncated_longname(self):
- f = open(tarname())
- fobj = StringIO.StringIO(f.read(1024))
- f.close()
- tar = tarfile.open(name="foo.tar", fileobj=fobj)
- self.assert_(len(tar.getmembers()) == 0, "")
+
+class PaxWriteTest(GNUWriteTest):
+
+ def _test(self, name, link=None):
+ # See GNUWriteTest.
+ tarinfo = tarfile.TarInfo(name)
+ if link:
+ tarinfo.linkname = link
+ tarinfo.type = tarfile.LNKTYPE
+
+ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
+ tar.addfile(tarinfo)
tar.close()
+ tar = tarfile.open(tmpname)
+ if link:
+ l = tar.getmembers()[0].linkname
+ self.assert_(link == l, "PAX longlink creation failed")
+ else:
+ n = tar.getmembers()[0].name
+ self.assert_(name == n, "PAX longname creation failed")
-class ExtractHardlinkTest(BaseTest):
+ def test_iso8859_15_filename(self):
+ self._test_unicode_filename("iso8859-15")
- def test_hardlink(self):
- """Test hardlink extraction (bug #857297)
- """
- # Prevent errors from being caught
- self.tar.errorlevel = 1
+ def test_utf8_filename(self):
+ self._test_unicode_filename("utf8")
- self.tar.extract("0-REGTYPE", dirname())
- try:
- # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
- self.tar.extract("1-LNKTYPE", dirname())
- except EnvironmentError as e:
- import errno
- if e.errno == errno.ENOENT:
- self.fail("hardlink not extracted properly")
+ def test_utf16_filename(self):
+ self._test_unicode_filename("utf16")
-class CreateHardlinkTest(BaseTest):
- """Test the creation of LNKTYPE (hardlink) members in an archive.
- In this respect tarfile.py mimics the behaviour of GNU tar: If
- a file has a st_nlink > 1, it will be added a REGTYPE member
- only the first time.
- """
+ def _test_unicode_filename(self, encoding):
+ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
+ name = u"\u20ac".encode(encoding) # Euro sign
+ tar.encoding = encoding
+ tar.addfile(tarfile.TarInfo(name))
+ tar.close()
- def setUp(self):
- self.tar = tarfile.open(tmpname(), "w")
+ tar = tarfile.open(tmpname, encoding=encoding)
+ self.assertEqual(tar.getmembers()[0].name, name)
+ tar.close()
- self.foo = os.path.join(dirname(), "foo")
- self.bar = os.path.join(dirname(), "bar")
+ def test_unicode_filename_error(self):
+ # The euro sign filename cannot be translated to iso8859-1 encoding.
+ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT, encoding="utf8")
+ name = u"\u20ac".encode("utf8") # Euro sign
+ tar.addfile(tarfile.TarInfo(name))
+ tar.close()
- if os.path.exists(self.foo):
- os.remove(self.foo)
- if os.path.exists(self.bar):
- os.remove(self.bar)
+ self.assertRaises(UnicodeError, tarfile.open, tmpname, encoding="iso8859-1")
- f = open(self.foo, "w")
- f.write("foo")
- f.close()
- self.tar.add(self.foo)
+ def test_pax_headers(self):
+ self._test_pax_headers({"foo": "bar", "uid": 0, "mtime": 1.23})
- def test_add_twice(self):
- # If st_nlink == 1 then the same file will be added as
- # REGTYPE every time.
- tarinfo = self.tar.gettarinfo(self.foo)
- self.assertEqual(tarinfo.type, tarfile.REGTYPE,
- "add file as regular failed")
+ self._test_pax_headers({"euro": u"\u20ac".encode("utf8")})
- def test_add_hardlink(self):
- # If st_nlink > 1 then the same file will be added as
- # LNKTYPE.
- os.link(self.foo, self.bar)
- tarinfo = self.tar.gettarinfo(self.foo)
- self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
- "add file as hardlink failed")
+ self._test_pax_headers({"euro": u"\u20ac"},
+ {"euro": u"\u20ac".encode("utf8")})
- tarinfo = self.tar.gettarinfo(self.bar)
- self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
- "add file as hardlink failed")
+ self._test_pax_headers({u"\u20ac": "euro"},
+ {u"\u20ac".encode("utf8"): "euro"})
- def test_dereference_hardlink(self):
- self.tar.dereference = True
- os.link(self.foo, self.bar)
- tarinfo = self.tar.gettarinfo(self.bar)
- self.assertEqual(tarinfo.type, tarfile.REGTYPE,
- "dereferencing hardlink failed")
+ def _test_pax_headers(self, pax_headers, cmp_headers=None):
+ if cmp_headers is None:
+ cmp_headers = pax_headers
+ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT, \
+ pax_headers=pax_headers, encoding="utf8")
+ tar.addfile(tarfile.TarInfo("test"))
+ tar.close()
-# Gzip TestCases
-class ReadTestGzip(ReadTest):
- comp = "gz"
-class ReadStreamTestGzip(ReadStreamTest):
- comp = "gz"
-class WriteTestGzip(WriteTest):
- comp = "gz"
-class WriteStreamTestGzip(WriteStreamTest):
- comp = "gz"
-class ReadDetectTestGzip(ReadDetectTest):
- comp = "gz"
-class ReadDetectFileobjTestGzip(ReadDetectFileobjTest):
- comp = "gz"
-class ReadAsteriskTestGzip(ReadAsteriskTest):
- comp = "gz"
-class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
- comp = "gz"
-
-# Filemode test cases
-
-class FileModeTest(unittest.TestCase):
- def test_modes(self):
- self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x')
- self.assertEqual(tarfile.filemode(07111), '---s--s--t')
-
-class HeaderErrorTest(unittest.TestCase):
+ tar = tarfile.open(tmpname, encoding="utf8")
+ self.assertEqual(tar.pax_headers, cmp_headers)
def test_truncated_header(self):
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "")
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "filename\0")
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 511)
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 513)
-
- def test_empty_header(self):
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 512)
-
- def test_invalid_header(self):
- buf = tarfile.TarInfo("filename").tobuf()
- buf = buf[:148] + "foo\0\0\0\0\0" + buf[156:] # invalid number field.
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, buf)
-
- def test_bad_checksum(self):
- buf = tarfile.TarInfo("filename").tobuf()
- b = buf[:148] + " " + buf[156:] # clear the checksum field.
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
- b = "a" + buf[1:] # manipulate the buffer, so checksum won't match.
- self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
-
-class OpenFileobjTest(BaseTest):
- # Test for SF bug #1496501.
-
- def test_opener(self):
- fobj = StringIO.StringIO("foo\n")
- try:
- tarfile.open("", "r", fileobj=fobj)
- except tarfile.ReadError:
- self.assertEqual(fobj.tell(), 0, "fileobj's position has moved")
-
-if bz2:
- # Bzip2 TestCases
- class ReadTestBzip2(ReadTestGzip):
- comp = "bz2"
- class ReadStreamTestBzip2(ReadStreamTestGzip):
- comp = "bz2"
- class WriteTestBzip2(WriteTest):
- comp = "bz2"
- class WriteStreamTestBzip2(WriteStreamTestGzip):
- comp = "bz2"
- class ReadDetectTestBzip2(ReadDetectTest):
- comp = "bz2"
- class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest):
- comp = "bz2"
- class ReadAsteriskTestBzip2(ReadAsteriskTest):
- comp = "bz2"
- class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
- comp = "bz2"
-
-# If importing gzip failed, discard the Gzip TestCases.
-if not gzip:
- del ReadTestGzip
- del ReadStreamTestGzip
- del WriteTestGzip
- del WriteStreamTestGzip
+ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
+ tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
+ tar.addfile(tarinfo)
+ tar.close()
-def test_main():
- # Create archive.
- f = open(tarname(), "rb")
- fguts = f.read()
- f.close()
- if gzip:
- # create testtar.tar.gz
- tar = gzip.open(tarname("gz"), "wb")
- tar.write(fguts)
+ # Simulate a premature EOF.
+ open(tmpname, "rb+").truncate(1536)
+ tar = tarfile.open(tmpname)
+ self.assertEqual(tar.getmembers(), [])
+
+
+class AppendTest(unittest.TestCase):
+ # Test append mode (cp. patch #1652681).
+
+ def setUp(self):
+ self.tarname = tmpname
+ if os.path.exists(self.tarname):
+ os.remove(self.tarname)
+
+ def _add_testfile(self, fileobj=None):
+ tar = tarfile.open(self.tarname, "a", fileobj=fileobj)
+ tar.addfile(tarfile.TarInfo("bar"))
tar.close()
- if bz2:
- # create testtar.tar.bz2
- tar = bz2.BZ2File(tarname("bz2"), "wb")
- tar.write(fguts)
+
+ def _create_testtar(self, mode="w:"):
+ src = tarfile.open(tarname, encoding="iso8859-1")
+ t = src.getmember("ustar/regtype")
+ t.name = "foo"
+ f = src.extractfile(t)
+ tar = tarfile.open(self.tarname, mode)
+ tar.addfile(t, f)
tar.close()
+ def _test(self, names=["bar"], fileobj=None):
+ tar = tarfile.open(self.tarname, fileobj=fileobj)
+ self.assertEqual(tar.getnames(), names)
+
+ def test_non_existing(self):
+ self._add_testfile()
+ self._test()
+
+ def test_empty(self):
+ open(self.tarname, "w").close()
+ self._add_testfile()
+ self._test()
+
+ def test_empty_fileobj(self):
+ fobj = StringIO.StringIO()
+ self._add_testfile(fobj)
+ fobj.seek(0)
+ self._test(fileobj=fobj)
+
+ def test_fileobj(self):
+ self._create_testtar()
+ data = open(self.tarname).read()
+ fobj = StringIO.StringIO(data)
+ self._add_testfile(fobj)
+ fobj.seek(0)
+ self._test(names=["foo", "bar"], fileobj=fobj)
+
+ def test_existing(self):
+ self._create_testtar()
+ self._add_testfile()
+ self._test(names=["foo", "bar"])
+
+ def test_append_gz(self):
+ if gzip is None:
+ return
+ self._create_testtar("w:gz")
+ self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a")
+
+ def test_append_bz2(self):
+ if bz2 is None:
+ return
+ self._create_testtar("w:bz2")
+ self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a")
+
+
+class LimitsTest(unittest.TestCase):
+
+ def test_ustar_limits(self):
+ # 100 char name
+ tarinfo = tarfile.TarInfo("0123456789" * 10)
+ tarinfo.create_ustar_header()
+
+ # 101 char name that cannot be stored
+ tarinfo = tarfile.TarInfo("0123456789" * 10 + "0")
+ self.assertRaises(ValueError, tarinfo.create_ustar_header)
+
+ # 256 char name with a slash at pos 156
+ tarinfo = tarfile.TarInfo("123/" * 62 + "longname")
+ tarinfo.create_ustar_header()
+
+ # 256 char name that cannot be stored
+ tarinfo = tarfile.TarInfo("1234567/" * 31 + "longname")
+ self.assertRaises(ValueError, tarinfo.create_ustar_header)
+
+ # 512 char name
+ tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
+ self.assertRaises(ValueError, tarinfo.create_ustar_header)
+
+ # 512 char linkname
+ tarinfo = tarfile.TarInfo("longlink")
+ tarinfo.linkname = "123/" * 126 + "longname"
+ self.assertRaises(ValueError, tarinfo.create_ustar_header)
+
+ # uid > 8 digits
+ tarinfo = tarfile.TarInfo("name")
+ tarinfo.uid = 010000000
+ self.assertRaises(ValueError, tarinfo.create_ustar_header)
+
+ def test_gnu_limits(self):
+ tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
+ tarinfo.create_gnu_header()
+
+ tarinfo = tarfile.TarInfo("longlink")
+ tarinfo.linkname = "123/" * 126 + "longname"
+ tarinfo.create_gnu_header()
+
+ # uid >= 256 ** 7
+ tarinfo = tarfile.TarInfo("name")
+ tarinfo.uid = 04000000000000000000
+ self.assertRaises(ValueError, tarinfo.create_gnu_header)
+
+ def test_pax_limits(self):
+ # A 256 char name that can be stored without an extended header.
+ tarinfo = tarfile.TarInfo("123/" * 62 + "longname")
+ self.assert_(len(tarinfo.create_pax_header("utf8")) == 512,
+ "create_pax_header attached superfluous extended header")
+
+ tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
+ tarinfo.create_pax_header("utf8")
+
+ tarinfo = tarfile.TarInfo("longlink")
+ tarinfo.linkname = "123/" * 126 + "longname"
+ tarinfo.create_pax_header("utf8")
+
+ tarinfo = tarfile.TarInfo("name")
+ tarinfo.uid = 04000000000000000000
+ tarinfo.create_pax_header("utf8")
+
+
+class GzipMiscReadTest(MiscReadTest):
+ tarname = gzipname
+ mode = "r:gz"
+class GzipUstarReadTest(UstarReadTest):
+ tarname = gzipname
+ mode = "r:gz"
+class GzipStreamReadTest(StreamReadTest):
+ tarname = gzipname
+ mode = "r|gz"
+class GzipWriteTest(WriteTest):
+ mode = "w:gz"
+class GzipStreamWriteTest(StreamWriteTest):
+ mode = "w|gz"
+
+
+class Bz2MiscReadTest(MiscReadTest):
+ tarname = bz2name
+ mode = "r:bz2"
+class Bz2UstarReadTest(UstarReadTest):
+ tarname = bz2name
+ mode = "r:bz2"
+class Bz2StreamReadTest(StreamReadTest):
+ tarname = bz2name
+ mode = "r|bz2"
+class Bz2WriteTest(WriteTest):
+ mode = "w:bz2"
+class Bz2StreamWriteTest(StreamWriteTest):
+ mode = "w|bz2"
+
+def test_main():
+ if not os.path.exists(TEMPDIR):
+ os.mkdir(TEMPDIR)
+
tests = [
- FileModeTest,
- HeaderErrorTest,
- OpenFileobjTest,
- ReadTest,
- ReadStreamTest,
- ReadDetectTest,
- ReadDetectFileobjTest,
- ReadAsteriskTest,
- ReadStreamAsteriskTest,
+ UstarReadTest,
+ MiscReadTest,
+ StreamReadTest,
+ DetectReadTest,
+ MemberReadTest,
+ GNUReadTest,
+ PaxReadTest,
WriteTest,
+ StreamWriteTest,
+ GNUWriteTest,
+ PaxWriteTest,
AppendTest,
- Write100Test,
- WriteSize0Test,
- WriteStreamTest,
- WriteGNULongTest,
- ReadGNULongTest,
+ LimitsTest,
]
if hasattr(os, "link"):
- tests.append(ExtractHardlinkTest)
- tests.append(CreateHardlinkTest)
+ tests.append(HardlinkTest)
+
+ fobj = open(tarname, "rb")
+ data = fobj.read()
+ fobj.close()
if gzip:
- tests.extend([
- ReadTestGzip, ReadStreamTestGzip,
- WriteTestGzip, WriteStreamTestGzip,
- ReadDetectTestGzip, ReadDetectFileobjTestGzip,
- ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip
- ])
+ # Create testtar.tar.gz and add gzip-specific tests.
+ tar = gzip.open(gzipname, "wb")
+ tar.write(data)
+ tar.close()
+
+ tests += [
+ GzipMiscReadTest,
+ GzipUstarReadTest,
+ GzipStreamReadTest,
+ GzipWriteTest,
+ GzipStreamWriteTest,
+ ]
if bz2:
- tests.extend([
- ReadTestBzip2, ReadStreamTestBzip2,
- WriteTestBzip2, WriteStreamTestBzip2,
- ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
- ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2
- ])
+ # Create testtar.tar.bz2 and add bz2-specific tests.
+ tar = bz2.BZ2File(bz2name, "wb")
+ tar.write(data)
+ tar.close()
+
+ tests += [
+ Bz2MiscReadTest,
+ Bz2UstarReadTest,
+ Bz2StreamReadTest,
+ Bz2WriteTest,
+ Bz2StreamWriteTest,
+ ]
+
try:
test_support.run_unittest(*tests)
finally:
- if gzip:
- os.remove(tarname("gz"))
- if bz2:
- os.remove(tarname("bz2"))
- if os.path.exists(dirname()):
- shutil.rmtree(dirname())
- if os.path.exists(tmpname()):
- os.remove(tmpname())
+ if os.path.exists(TEMPDIR):
+ shutil.rmtree(TEMPDIR)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_telnetlib.py b/Lib/test/test_telnetlib.py
new file mode 100644
index 0000000..0a3604e
--- /dev/null
+++ b/Lib/test/test_telnetlib.py
@@ -0,0 +1,74 @@
+import socket
+import threading
+import telnetlib
+import time
+
+from unittest import TestCase
+from test import test_support
+
+
+def server(evt):
+ serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ serv.settimeout(3)
+ serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ serv.bind(("", 9091))
+ serv.listen(5)
+ try:
+ conn, addr = serv.accept()
+ except socket.timeout:
+ pass
+ finally:
+ serv.close()
+ evt.set()
+
+class GeneralTests(TestCase):
+
+ def setUp(self):
+ self.evt = threading.Event()
+ threading.Thread(target=server, args=(self.evt,)).start()
+ time.sleep(.1)
+
+ def tearDown(self):
+ self.evt.wait()
+
+ def testBasic(self):
+ # connects
+ telnet = telnetlib.Telnet("localhost", 9091)
+ telnet.sock.close()
+
+ def testTimeoutDefault(self):
+ # default
+ telnet = telnetlib.Telnet("localhost", 9091)
+ self.assertTrue(telnet.sock.gettimeout() is None)
+ telnet.sock.close()
+
+ def testTimeoutValue(self):
+ # a value
+ telnet = telnetlib.Telnet("localhost", 9091, timeout=30)
+ self.assertEqual(telnet.sock.gettimeout(), 30)
+ telnet.sock.close()
+
+ def testTimeoutDifferentOrder(self):
+ telnet = telnetlib.Telnet(timeout=30)
+ telnet.open("localhost", 9091)
+ self.assertEqual(telnet.sock.gettimeout(), 30)
+ telnet.sock.close()
+
+ def testTimeoutNone(self):
+ # None, having other default
+ previous = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(30)
+ try:
+ telnet = telnetlib.Telnet("localhost", 9091, timeout=None)
+ finally:
+ socket.setdefaulttimeout(previous)
+ self.assertEqual(telnet.sock.gettimeout(), 30)
+ telnet.sock.close()
+
+
+
+def test_main(verbose=None):
+ test_support.run_unittest(GeneralTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py
index a398d37..20f22ed 100644
--- a/Lib/test/test_tempfile.py
+++ b/Lib/test/test_tempfile.py
@@ -81,7 +81,8 @@ class test_exports(TC):
"gettempprefix" : 1,
"gettempdir" : 1,
"tempdir" : 1,
- "template" : 1
+ "template" : 1,
+ "SpooledTemporaryFile" : 1
}
unexp = []
@@ -561,11 +562,12 @@ test_classes.append(test_mktemp)
class test_NamedTemporaryFile(TC):
"""Test NamedTemporaryFile()."""
- def do_create(self, dir=None, pre="", suf=""):
+ def do_create(self, dir=None, pre="", suf="", delete=True):
if dir is None:
dir = tempfile.gettempdir()
try:
- file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf)
+ file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf,
+ delete=delete)
except:
self.failOnException("NamedTemporaryFile")
@@ -599,6 +601,22 @@ class test_NamedTemporaryFile(TC):
finally:
os.rmdir(dir)
+ def test_dis_del_on_close(self):
+ # Tests that delete-on-close can be disabled
+ dir = tempfile.mkdtemp()
+ tmp = None
+ try:
+ f = tempfile.NamedTemporaryFile(dir=dir, delete=False)
+ tmp = f.name
+ f.write('blat')
+ f.close()
+ self.failUnless(os.path.exists(f.name),
+ "NamedTemporaryFile %s missing after close" % f.name)
+ finally:
+ if tmp is not None:
+ os.unlink(tmp)
+ os.rmdir(dir)
+
def test_multiple_close(self):
# A NamedTemporaryFile can be closed many times without error
@@ -615,6 +633,107 @@ class test_NamedTemporaryFile(TC):
test_classes.append(test_NamedTemporaryFile)
+class test_SpooledTemporaryFile(TC):
+ """Test SpooledTemporaryFile()."""
+
+ def do_create(self, max_size=0, dir=None, pre="", suf=""):
+ if dir is None:
+ dir = tempfile.gettempdir()
+ try:
+ file = tempfile.SpooledTemporaryFile(max_size=max_size, dir=dir, prefix=pre, suffix=suf)
+ except:
+ self.failOnException("SpooledTemporaryFile")
+
+ return file
+
+
+ def test_basic(self):
+ # SpooledTemporaryFile can create files
+ f = self.do_create()
+ self.failIf(f._rolled)
+ f = self.do_create(max_size=100, pre="a", suf=".txt")
+ self.failIf(f._rolled)
+
+ def test_del_on_close(self):
+ # A SpooledTemporaryFile is deleted when closed
+ dir = tempfile.mkdtemp()
+ try:
+ f = tempfile.SpooledTemporaryFile(max_size=10, dir=dir)
+ self.failIf(f._rolled)
+ f.write('blat ' * 5)
+ self.failUnless(f._rolled)
+ filename = f.name
+ f.close()
+ self.failIf(os.path.exists(filename),
+ "SpooledTemporaryFile %s exists after close" % filename)
+ finally:
+ os.rmdir(dir)
+
+ def test_rewrite_small(self):
+ # A SpooledTemporaryFile can be written to multiple within the max_size
+ f = self.do_create(max_size=30)
+ self.failIf(f._rolled)
+ for i in range(5):
+ f.seek(0, 0)
+ f.write('x' * 20)
+ self.failIf(f._rolled)
+
+ def test_write_sequential(self):
+ # A SpooledTemporaryFile should hold exactly max_size bytes, and roll
+ # over afterward
+ f = self.do_create(max_size=30)
+ self.failIf(f._rolled)
+ f.write('x' * 20)
+ self.failIf(f._rolled)
+ f.write('x' * 10)
+ self.failIf(f._rolled)
+ f.write('x')
+ self.failUnless(f._rolled)
+
+ def test_sparse(self):
+ # A SpooledTemporaryFile that is written late in the file will extend
+ # when that occurs
+ f = self.do_create(max_size=30)
+ self.failIf(f._rolled)
+ f.seek(100, 0)
+ self.failIf(f._rolled)
+ f.write('x')
+ self.failUnless(f._rolled)
+
+ def test_fileno(self):
+ # A SpooledTemporaryFile should roll over to a real file on fileno()
+ f = self.do_create(max_size=30)
+ self.failIf(f._rolled)
+ self.failUnless(f.fileno() > 0)
+ self.failUnless(f._rolled)
+
+ def test_multiple_close(self):
+ # A SpooledTemporaryFile can be closed many times without error
+ f = tempfile.SpooledTemporaryFile()
+ f.write('abc\n')
+ f.close()
+ try:
+ f.close()
+ f.close()
+ except:
+ self.failOnException("close")
+
+ def test_bound_methods(self):
+ # It should be OK to steal a bound method from a SpooledTemporaryFile
+ # and use it independently; when the file rolls over, those bound
+ # methods should continue to function
+ f = self.do_create(max_size=30)
+ read = f.read
+ write = f.write
+ seek = f.seek
+
+ write("a" * 35)
+ write("b" * 35)
+ seek(0, 0)
+ self.failUnless(read(70) == 'a'*35 + 'b'*35)
+
+test_classes.append(test_SpooledTemporaryFile)
+
class test_TemporaryFile(TC):
"""Test TemporaryFile()."""
diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py
index 500eceb..5f0b51b 100644
--- a/Lib/test/test_textwrap.py
+++ b/Lib/test/test_textwrap.py
@@ -328,6 +328,14 @@ What a mess!
self.check_wrap(text, 30,
[" This is a sentence with", "leading whitespace."])
+ def test_no_drop_whitespace(self):
+ # SF patch #1581073
+ text = " This is a sentence with much whitespace."
+ self.check_wrap(text, 10,
+ [" This is a", " ", "sentence ",
+ "with ", "much white", "space."],
+ drop_whitespace=False)
+
if test_support.have_unicode:
def test_unicode(self):
# *Very* simple test of wrapping Unicode strings. I'm sure
diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py
index 75d719d..753f388 100644
--- a/Lib/test/test_threadedtempfile.py
+++ b/Lib/test/test_threadedtempfile.py
@@ -10,22 +10,20 @@ failures. A failure is a bug in tempfile, and may be due to:
By default, NUM_THREADS == 20 and FILES_PER_THREAD == 50. This is enough to
create about 150 failures per run under Win98SE in 2.0, and runs pretty
quickly. Guido reports needing to boost FILES_PER_THREAD to 500 before
-provoking a 2.0 failure under Linux. Run the test alone to boost either
-via cmdline switches:
-
--f FILES_PER_THREAD (int)
--t NUM_THREADS (int)
+provoking a 2.0 failure under Linux.
"""
-NUM_THREADS = 20 # change w/ -t option
-FILES_PER_THREAD = 50 # change w/ -f option
+NUM_THREADS = 20
+FILES_PER_THREAD = 50
import thread # If this fails, we can't test this module
import threading
-from test.test_support import TestFailed, threading_setup, threading_cleanup
+import tempfile
+
+from test.test_support import threading_setup, threading_cleanup, run_unittest
+import unittest
import StringIO
from traceback import print_exc
-import tempfile
startEvent = threading.Event()
@@ -46,41 +44,36 @@ class TempFileGreedy(threading.Thread):
else:
self.ok_count += 1
+
+class ThreadedTempFileTest(unittest.TestCase):
+ def test_main(self):
+ threads = []
+ thread_info = threading_setup()
+
+ for i in range(NUM_THREADS):
+ t = TempFileGreedy()
+ threads.append(t)
+ t.start()
+
+ startEvent.set()
+
+ ok = 0
+ errors = []
+ for t in threads:
+ t.join()
+ ok += t.ok_count
+ if t.error_count:
+ errors.append(str(t.getName()) + str(t.errors.getvalue()))
+
+ threading_cleanup(*thread_info)
+
+ msg = "Errors: errors %d ok %d\n%s" % (len(errors), ok,
+ '\n'.join(errors))
+ self.assertEquals(errors, [], msg)
+ self.assertEquals(ok, NUM_THREADS * FILES_PER_THREAD)
+
def test_main():
- threads = []
- thread_info = threading_setup()
-
- print("Creating")
- for i in range(NUM_THREADS):
- t = TempFileGreedy()
- threads.append(t)
- t.start()
-
- print("Starting")
- startEvent.set()
-
- print("Reaping")
- ok = errors = 0
- for t in threads:
- t.join()
- ok += t.ok_count
- errors += t.error_count
- if t.error_count:
- print('%s errors:\n%s' % (t.getName(), t.errors.getvalue()))
-
- msg = "Done: errors %d ok %d" % (errors, ok)
- print(msg)
- if errors:
- raise TestFailed(msg)
-
- threading_cleanup(*thread_info)
+ run_unittest(ThreadedTempFileTest)
if __name__ == "__main__":
- import sys, getopt
- opts, args = getopt.getopt(sys.argv[1:], "t:f:")
- for o, v in opts:
- if o == "-f":
- FILES_PER_THREAD = int(v)
- elif o == "-t":
- NUM_THREADS = int(v)
test_main()
diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py
index 56fbedd..0aaedbc 100644
--- a/Lib/test/test_threading_local.py
+++ b/Lib/test/test_threading_local.py
@@ -20,7 +20,7 @@ def test_main():
setUp=setUp, tearDown=tearDown)
)
- test_support.run_suite(suite)
+ test_support.run_unittest(suite)
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index cb7586c..a704cc9 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -829,7 +829,7 @@ class UnicodeTest(
def test_main():
- test_support.run_unittest(UnicodeTest)
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_unicode_file.py b/Lib/test/test_unicode_file.py
index 0058d98..328b5b6 100644
--- a/Lib/test/test_unicode_file.py
+++ b/Lib/test/test_unicode_file.py
@@ -5,7 +5,7 @@ import os, glob, time, shutil
import unicodedata
import unittest
-from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE
+from test.test_support import run_unittest, TestSkipped, TESTFN_UNICODE
from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE
try:
TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING)
@@ -205,9 +205,7 @@ class TestUnicodeFiles(unittest.TestCase):
False)
def test_main():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestUnicodeFiles))
- run_suite(suite)
+ run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py
index 9151166..70f12d2 100644
--- a/Lib/test/test_unittest.py
+++ b/Lib/test/test_unittest.py
@@ -1,31 +1,2302 @@
"""Test script for unittest.
-This just includes tests for new features. We really need a
-full set of tests.
+By Collin Winter <collinw at gmail.com>
+
+Still need testing:
+ TestCase.{assert,fail}* methods (some are tested implicitly)
"""
+from test import test_support
import unittest
+from unittest import TestCase
+
+### Support code
+################################################################
+
+class LoggingResult(unittest.TestResult):
+ def __init__(self, log):
+ self._events = log
+ super(LoggingResult, self).__init__()
+
+ def startTest(self, test):
+ self._events.append('startTest')
+ super(LoggingResult, self).startTest(test)
+
+ def stopTest(self, test):
+ self._events.append('stopTest')
+ super(LoggingResult, self).stopTest(test)
+
+ def addFailure(self, *args):
+ self._events.append('addFailure')
+ super(LoggingResult, self).addFailure(*args)
+
+ def addError(self, *args):
+ self._events.append('addError')
+ super(LoggingResult, self).addError(*args)
+
+class TestEquality(object):
+ # Check for a valid __eq__ implementation
+ def test_eq(self):
+ for obj_1, obj_2 in self.eq_pairs:
+ self.assertEqual(obj_1, obj_2)
+ self.assertEqual(obj_2, obj_1)
+
+ # Check for a valid __ne__ implementation
+ def test_ne(self):
+ for obj_1, obj_2 in self.ne_pairs:
+ self.failIfEqual(obj_1, obj_2)
+ self.failIfEqual(obj_2, obj_1)
+
+class TestHashing(object):
+ # Check for a valid __hash__ implementation
+ def test_hash(self):
+ for obj_1, obj_2 in self.eq_pairs:
+ try:
+ assert hash(obj_1) == hash(obj_2)
+ except KeyboardInterrupt:
+ raise
+ except AssertionError:
+ self.fail("%s and %s do not hash equal" % (obj_1, obj_2))
+ except Exception as e:
+ self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e))
+
+ for obj_1, obj_2 in self.ne_pairs:
+ try:
+ assert hash(obj_1) != hash(obj_2)
+ except KeyboardInterrupt:
+ raise
+ except AssertionError:
+ self.fail("%s and %s hash equal, but shouldn't" % (obj_1, obj_2))
+ except Exception as e:
+ self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e))
+
+
+################################################################
+### /Support code
+
+class Test_TestLoader(TestCase):
+
+ ### Tests for TestLoader.loadTestsFromTestCase
+ ################################################################
+
+ # "Return a suite of all tests cases contained in the TestCase-derived
+ # class testCaseClass"
+ def test_loadTestsFromTestCase(self):
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+
+ tests = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
+
+ loader = unittest.TestLoader()
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
+
+ # "Return a suite of all tests cases contained in the TestCase-derived
+ # class testCaseClass"
+ #
+ # Make sure it does the right thing even if no tests were found
+ def test_loadTestsFromTestCase__no_matches(self):
+ class Foo(unittest.TestCase):
+ def foo_bar(self): pass
+
+ empty_suite = unittest.TestSuite()
+
+ loader = unittest.TestLoader()
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), empty_suite)
+
+ # "Return a suite of all tests cases contained in the TestCase-derived
+ # class testCaseClass"
+ #
+ # What happens if loadTestsFromTestCase() is given an object
+ # that isn't a subclass of TestCase? Specifically, what happens
+ # if testCaseClass is a subclass of TestSuite?
+ #
+ # This is checked for specifically in the code, so we better add a
+ # test for it.
+ def test_loadTestsFromTestCase__TestSuite_subclass(self):
+ class NotATestCase(unittest.TestSuite):
+ pass
+
+ loader = unittest.TestLoader()
+ try:
+ loader.loadTestsFromTestCase(NotATestCase)
+ except TypeError:
+ pass
+ else:
+ self.fail('Should raise TypeError')
+
+ # "Return a suite of all tests cases contained in the TestCase-derived
+ # class testCaseClass"
+ #
+ # Make sure loadTestsFromTestCase() picks up the default test method
+ # name (as specified by TestCase), even though the method name does
+ # not match the default TestLoader.testMethodPrefix string
+ def test_loadTestsFromTestCase__default_method_name(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ loader = unittest.TestLoader()
+ # This has to be false for the test to succeed
+ self.failIf('runTest'.startswith(loader.testMethodPrefix))
+
+ suite = loader.loadTestsFromTestCase(Foo)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [Foo('runTest')])
+
+ ################################################################
+ ### /Tests for TestLoader.loadTestsFromTestCase
+
+ ### Tests for TestLoader.loadTestsFromModule
+ ################################################################
+
+ # "This method searches `module` for classes derived from TestCase"
+ def test_loadTestsFromModule__TestCase_subclass(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromModule(m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ expected = [loader.suiteClass([MyTestCase('test')])]
+ self.assertEqual(list(suite), expected)
+
+ # "This method searches `module` for classes derived from TestCase"
+ #
+ # What happens if no tests are found (no TestCase instances)?
+ def test_loadTestsFromModule__no_TestCase_instances(self):
+ import new
+ m = new.module('m')
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromModule(m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [])
+
+ # "This method searches `module` for classes derived from TestCase"
+ #
+ # What happens if no tests are found (TestCases instances, but no tests)?
+ def test_loadTestsFromModule__no_TestCase_tests(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromModule(m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ self.assertEqual(list(suite), [loader.suiteClass()])
+
+ # "This method searches `module` for classes derived from TestCase"s
+ #
+ # What happens if loadTestsFromModule() is given something other
+ # than a module?
+ #
+ # XXX Currently, it succeeds anyway. This flexibility
+ # should either be documented or loadTestsFromModule() should
+ # raise a TypeError
+ #
+ # XXX Certain people are using this behaviour. We'll add a test for it
+ def test_loadTestsFromModule__not_a_module(self):
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+
+ class NotAModule(object):
+ test_2 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromModule(NotAModule)
+
+ reference = [unittest.TestSuite([MyTestCase('test')])]
+ self.assertEqual(list(suite), reference)
+
+ ################################################################
+ ### /Tests for TestLoader.loadTestsFromModule()
+
+ ### Tests for TestLoader.loadTestsFromName()
+ ################################################################
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # Is ValueError raised in response to an empty name?
+ def test_loadTestsFromName__empty_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromName('')
+ except ValueError as e:
+ self.assertEqual(str(e), "Empty module name")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise ValueError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when the name contains invalid characters?
+ def test_loadTestsFromName__malformed_name(self):
+ loader = unittest.TestLoader()
+
+ # XXX Should this raise ValueError or ImportError?
+ try:
+ loader.loadTestsFromName('abc () //')
+ except ValueError:
+ pass
+ except ImportError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise ValueError")
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to a
+ # module"
+ #
+ # What happens when a module by that name can't be found?
+ def test_loadTestsFromName__unknown_module_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromName('sdasfasfasdf')
+ except ImportError as e:
+ self.assertEqual(str(e), "No module named sdasfasfasdf")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise ImportError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when the module is found, but the attribute can't?
+ def test_loadTestsFromName__unknown_attr_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromName('unittest.sdasfasfasdf')
+ except AttributeError as e:
+ self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when we provide the module, but the attribute can't be
+ # found?
+ def test_loadTestsFromName__relative_unknown_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromName('sdasfasfasdf', unittest)
+ except AttributeError as e:
+ self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # Does loadTestsFromName raise ValueError when passed an empty
+ # name relative to a provided module?
+ #
+ # XXX Should probably raise a ValueError instead of an AttributeError
+ def test_loadTestsFromName__relative_empty_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromName('', unittest)
+ except AttributeError as e:
+ pass
+ else:
+ self.fail("Failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # What happens when an impossible name is given, relative to the provided
+ # `module`?
+ def test_loadTestsFromName__relative_malformed_name(self):
+ loader = unittest.TestLoader()
+
+ # XXX Should this raise AttributeError or ValueError?
+ try:
+ loader.loadTestsFromName('abc () //', unittest)
+ except ValueError:
+ pass
+ except AttributeError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise ValueError")
+
+ # "The method optionally resolves name relative to the given module"
+ #
+ # Does loadTestsFromName raise TypeError when the `module` argument
+ # isn't a module object?
+ #
+ # XXX Accepts the not-a-module object, ignorning the object's type
+ # This should raise an exception or the method name should be changed
+ #
+ # XXX Some people are relying on this, so keep it for now
+ def test_loadTestsFromName__relative_not_a_module(self):
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+
+ class NotAModule(object):
+ test_2 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('test_2', NotAModule)
+
+ reference = [MyTestCase('test')]
+ self.assertEqual(list(suite), reference)
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # Does it raise an exception if the name resolves to an invalid
+ # object?
+ def test_loadTestsFromName__relative_bad_object(self):
+ import new
+ m = new.module('m')
+ m.testcase_1 = object()
+
+ loader = unittest.TestLoader()
+ try:
+ loader.loadTestsFromName('testcase_1', m)
+ except TypeError:
+ pass
+ else:
+ self.fail("Should have raised TypeError")
+
+ # "The specifier name is a ``dotted name'' that may
+ # resolve either to ... a test case class"
+ def test_loadTestsFromName__relative_TestCase_subclass(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('testcase_1', m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [MyTestCase('test')])
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ def test_loadTestsFromName__relative_TestSuite(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testsuite = unittest.TestSuite([MyTestCase('test')])
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('testsuite', m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ self.assertEqual(list(suite), [MyTestCase('test')])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a test method within a test case class"
+ def test_loadTestsFromName__relative_testmethod(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('testcase_1.test', m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ self.assertEqual(list(suite), [MyTestCase('test')])
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # Does loadTestsFromName() raise the proper exception when trying to
+ # resolve "a test method within a test case class" that doesn't exist
+ # for the given name (relative to a provided module)?
+ def test_loadTestsFromName__relative_invalid_testmethod(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ try:
+ loader.loadTestsFromName('testcase_1.testfoo', m)
+ except AttributeError as e:
+ self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'")
+ else:
+ self.fail("Failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a ... TestSuite instance"
+ def test_loadTestsFromName__callable__TestSuite(self):
+ import new
+ m = new.module('m')
+ testcase_1 = unittest.FunctionTestCase(lambda: None)
+ testcase_2 = unittest.FunctionTestCase(lambda: None)
+ def return_TestSuite():
+ return unittest.TestSuite([testcase_1, testcase_2])
+ m.return_TestSuite = return_TestSuite
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('return_TestSuite', m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [testcase_1, testcase_2])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a TestCase ... instance"
+ def test_loadTestsFromName__callable__TestCase_instance(self):
+ import new
+ m = new.module('m')
+ testcase_1 = unittest.FunctionTestCase(lambda: None)
+ def return_TestCase():
+ return testcase_1
+ m.return_TestCase = return_TestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromName('return_TestCase', m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [testcase_1])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a TestCase or TestSuite instance"
+ #
+ # What happens if the callable returns something else?
+ def test_loadTestsFromName__callable__wrong_type(self):
+ import new
+ m = new.module('m')
+ def return_wrong():
+ return 6
+ m.return_wrong = return_wrong
+
+ loader = unittest.TestLoader()
+ try:
+ suite = loader.loadTestsFromName('return_wrong', m)
+ except TypeError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise TypeError")
+
+ # "The specifier can refer to modules and packages which have not been
+ # imported; they will be imported as a side-effect"
+ def test_loadTestsFromName__module_not_loaded(self):
+ # We're going to try to load this module as a side-effect, so it
+ # better not be loaded before we try.
+ #
+ # Why pick audioop? Google shows it isn't used very often, so there's
+ # a good chance that it won't be imported when this test is run
+ module_name = 'audioop'
+
+ import sys
+ if module_name in sys.modules:
+ del sys.modules[module_name]
+
+ loader = unittest.TestLoader()
+ try:
+ suite = loader.loadTestsFromName(module_name)
+
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [])
+
+ # audioop should now be loaded, thanks to loadTestsFromName()
+ self.failUnless(module_name in sys.modules)
+ finally:
+ del sys.modules[module_name]
+
+ ################################################################
+ ### Tests for TestLoader.loadTestsFromName()
+
+ ### Tests for TestLoader.loadTestsFromNames()
+ ################################################################
+
+ # "Similar to loadTestsFromName(), but takes a sequence of names rather
+ # than a single name."
+ #
+ # What happens if that sequence of names is empty?
+ def test_loadTestsFromNames__empty_name_list(self):
+ loader = unittest.TestLoader()
+
+ suite = loader.loadTestsFromNames([])
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [])
+
+ # "Similar to loadTestsFromName(), but takes a sequence of names rather
+ # than a single name."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # What happens if that sequence of names is empty?
+ #
+ # XXX Should this raise a ValueError or just return an empty TestSuite?
+ def test_loadTestsFromNames__relative_empty_name_list(self):
+ loader = unittest.TestLoader()
+
+ suite = loader.loadTestsFromNames([], unittest)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [])
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # Is ValueError raised in response to an empty name?
+ def test_loadTestsFromNames__empty_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames([''])
+ except ValueError as e:
+ self.assertEqual(str(e), "Empty module name")
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise ValueError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when presented with an impossible module name?
+ def test_loadTestsFromNames__malformed_name(self):
+ loader = unittest.TestLoader()
+
+ # XXX Should this raise ValueError or ImportError?
+ try:
+ loader.loadTestsFromNames(['abc () //'])
+ except ValueError:
+ pass
+ except ImportError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise ValueError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when no module can be found for the given name?
+ def test_loadTestsFromNames__unknown_module_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames(['sdasfasfasdf'])
+ except ImportError as e:
+ self.assertEqual(str(e), "No module named sdasfasfasdf")
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise ImportError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # What happens when the module can be found, but not the attribute?
+ def test_loadTestsFromNames__unknown_attr_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames(['unittest.sdasfasfasdf', 'unittest'])
+ except AttributeError as e:
+ self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'")
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # What happens when given an unknown attribute on a specified `module`
+ # argument?
+ def test_loadTestsFromNames__unknown_name_relative_1(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames(['sdasfasfasdf'], unittest)
+ except AttributeError as e:
+ self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # Do unknown attributes (relative to a provided module) still raise an
+ # exception even in the presence of valid attribute names?
+ def test_loadTestsFromNames__unknown_name_relative_2(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames(['TestCase', 'sdasfasfasdf'], unittest)
+ except AttributeError as e:
+ self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'")
+ else:
+ self.fail("TestLoader.loadTestsFromName failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # What happens when faced with the empty string?
+ #
+ # XXX This currently raises AttributeError, though ValueError is probably
+ # more appropriate
+ def test_loadTestsFromNames__relative_empty_name(self):
+ loader = unittest.TestLoader()
+
+ try:
+ loader.loadTestsFromNames([''], unittest)
+ except AttributeError:
+ pass
+ else:
+ self.fail("Failed to raise ValueError")
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ # ...
+ # "The method optionally resolves name relative to the given module"
+ #
+ # What happens when presented with an impossible attribute name?
+ def test_loadTestsFromNames__relative_malformed_name(self):
+ loader = unittest.TestLoader()
+
+ # XXX Should this raise AttributeError or ValueError?
+ try:
+ loader.loadTestsFromNames(['abc () //'], unittest)
+ except AttributeError:
+ pass
+ except ValueError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise ValueError")
+
+ # "The method optionally resolves name relative to the given module"
+ #
+ # Does loadTestsFromNames() make sure the provided `module` is in fact
+ # a module?
+ #
+ # XXX This validation is currently not done. This flexibility should
+ # either be documented or a TypeError should be raised.
+ def test_loadTestsFromNames__relative_not_a_module(self):
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+
+ class NotAModule(object):
+ test_2 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['test_2'], NotAModule)
+
+ reference = [unittest.TestSuite([MyTestCase('test')])]
+ self.assertEqual(list(suite), reference)
+
+ # "The specifier name is a ``dotted name'' that may resolve either to
+ # a module, a test case class, a TestSuite instance, a test method
+ # within a test case class, or a callable object which returns a
+ # TestCase or TestSuite instance."
+ #
+ # Does it raise an exception if the name resolves to an invalid
+ # object?
+ def test_loadTestsFromNames__relative_bad_object(self):
+ import new
+ m = new.module('m')
+ m.testcase_1 = object()
+
+ loader = unittest.TestLoader()
+ try:
+ loader.loadTestsFromNames(['testcase_1'], m)
+ except TypeError:
+ pass
+ else:
+ self.fail("Should have raised TypeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a test case class"
+ def test_loadTestsFromNames__relative_TestCase_subclass(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['testcase_1'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ expected = loader.suiteClass([MyTestCase('test')])
+ self.assertEqual(list(suite), [expected])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a TestSuite instance"
+ def test_loadTestsFromNames__relative_TestSuite(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testsuite = unittest.TestSuite([MyTestCase('test')])
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['testsuite'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ self.assertEqual(list(suite), [m.testsuite])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to ... a
+ # test method within a test case class"
+ def test_loadTestsFromNames__relative_testmethod(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['testcase_1.test'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ ref_suite = unittest.TestSuite([MyTestCase('test')])
+ self.assertEqual(list(suite), [ref_suite])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to ... a
+ # test method within a test case class"
+ #
+ # Does the method gracefully handle names that initially look like they
+ # resolve to "a test method within a test case class" but don't?
+ def test_loadTestsFromNames__relative_invalid_testmethod(self):
+ import new
+ m = new.module('m')
+ class MyTestCase(unittest.TestCase):
+ def test(self):
+ pass
+ m.testcase_1 = MyTestCase
+
+ loader = unittest.TestLoader()
+ try:
+ loader.loadTestsFromNames(['testcase_1.testfoo'], m)
+ except AttributeError as e:
+ self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'")
+ else:
+ self.fail("Failed to raise AttributeError")
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a ... TestSuite instance"
+ def test_loadTestsFromNames__callable__TestSuite(self):
+ import new
+ m = new.module('m')
+ testcase_1 = unittest.FunctionTestCase(lambda: None)
+ testcase_2 = unittest.FunctionTestCase(lambda: None)
+ def return_TestSuite():
+ return unittest.TestSuite([testcase_1, testcase_2])
+ m.return_TestSuite = return_TestSuite
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['return_TestSuite'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ expected = unittest.TestSuite([testcase_1, testcase_2])
+ self.assertEqual(list(suite), [expected])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a TestCase ... instance"
+ def test_loadTestsFromNames__callable__TestCase_instance(self):
+ import new
+ m = new.module('m')
+ testcase_1 = unittest.FunctionTestCase(lambda: None)
+ def return_TestCase():
+ return testcase_1
+ m.return_TestCase = return_TestCase
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['return_TestCase'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ ref_suite = unittest.TestSuite([testcase_1])
+ self.assertEqual(list(suite), [ref_suite])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a TestCase or TestSuite instance"
+ #
+ # Are staticmethods handled correctly?
+ def test_loadTestsFromNames__callable__call_staticmethod(self):
+ import new
+ m = new.module('m')
+ class Test1(unittest.TestCase):
+ def test(self):
+ pass
+
+ testcase_1 = Test1('test')
+ class Foo(unittest.TestCase):
+ @staticmethod
+ def foo():
+ return testcase_1
+ m.Foo = Foo
+
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(['Foo.foo'], m)
+ self.failUnless(isinstance(suite, loader.suiteClass))
+
+ ref_suite = unittest.TestSuite([testcase_1])
+ self.assertEqual(list(suite), [ref_suite])
+
+ # "The specifier name is a ``dotted name'' that may resolve ... to
+ # ... a callable object which returns a TestCase or TestSuite instance"
+ #
+ # What happens when the callable returns something else?
+ def test_loadTestsFromNames__callable__wrong_type(self):
+ import new
+ m = new.module('m')
+ def return_wrong():
+ return 6
+ m.return_wrong = return_wrong
+
+ loader = unittest.TestLoader()
+ try:
+ suite = loader.loadTestsFromNames(['return_wrong'], m)
+ except TypeError:
+ pass
+ else:
+ self.fail("TestLoader.loadTestsFromNames failed to raise TypeError")
+
+ # "The specifier can refer to modules and packages which have not been
+ # imported; they will be imported as a side-effect"
+ def test_loadTestsFromNames__module_not_loaded(self):
+ # We're going to try to load this module as a side-effect, so it
+ # better not be loaded before we try.
+ #
+ # Why pick audioop? Google shows it isn't used very often, so there's
+ # a good chance that it won't be imported when this test is run
+ module_name = 'audioop'
+
+ import sys
+ if module_name in sys.modules:
+ del sys.modules[module_name]
+
+ loader = unittest.TestLoader()
+ try:
+ suite = loader.loadTestsFromNames([module_name])
+
+ self.failUnless(isinstance(suite, loader.suiteClass))
+ self.assertEqual(list(suite), [unittest.TestSuite()])
+
+ # audioop should now be loaded, thanks to loadTestsFromName()
+ self.failUnless(module_name in sys.modules)
+ finally:
+ del sys.modules[module_name]
+
+ ################################################################
+ ### /Tests for TestLoader.loadTestsFromNames()
+
+ ### Tests for TestLoader.getTestCaseNames()
+ ################################################################
+
+ # "Return a sorted sequence of method names found within testCaseClass"
+ #
+ # Test.foobar is defined to make sure getTestCaseNames() respects
+ # loader.testMethodPrefix
+ def test_getTestCaseNames(self):
+ class Test(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foobar(self): pass
+
+ loader = unittest.TestLoader()
+
+ self.assertEqual(loader.getTestCaseNames(Test), ['test_1', 'test_2'])
+
+ # "Return a sorted sequence of method names found within testCaseClass"
+ #
+ # Does getTestCaseNames() behave appropriately if no tests are found?
+ def test_getTestCaseNames__no_tests(self):
+ class Test(unittest.TestCase):
+ def foobar(self): pass
+
+ loader = unittest.TestLoader()
+
+ self.assertEqual(loader.getTestCaseNames(Test), [])
+
+ # "Return a sorted sequence of method names found within testCaseClass"
+ #
+ # Are not-TestCases handled gracefully?
+ #
+ # XXX This should raise a TypeError, not return a list
+ #
+ # XXX It's too late in the 2.5 release cycle to fix this, but it should
+ # probably be revisited for 2.6
+ def test_getTestCaseNames__not_a_TestCase(self):
+ class BadCase(int):
+ def test_foo(self):
+ pass
+
+ loader = unittest.TestLoader()
+ names = loader.getTestCaseNames(BadCase)
+
+ self.assertEqual(names, ['test_foo'])
+
+ # "Return a sorted sequence of method names found within testCaseClass"
+ #
+ # Make sure inherited names are handled.
+ #
+ # TestP.foobar is defined to make sure getTestCaseNames() respects
+ # loader.testMethodPrefix
+ def test_getTestCaseNames__inheritance(self):
+ class TestP(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foobar(self): pass
+
+ class TestC(TestP):
+ def test_1(self): pass
+ def test_3(self): pass
+
+ loader = unittest.TestLoader()
+
+ names = ['test_1', 'test_2', 'test_3']
+ self.assertEqual(loader.getTestCaseNames(TestC), names)
+
+ ################################################################
+ ### /Tests for TestLoader.getTestCaseNames()
+
+ ### Tests for TestLoader.testMethodPrefix
+ ################################################################
+
+ # "String giving the prefix of method names which will be interpreted as
+ # test methods"
+ #
+ # Implicit in the documentation is that testMethodPrefix is respected by
+ # all loadTestsFrom* methods.
+ def test_testMethodPrefix__loadTestsFromTestCase(self):
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+
+ tests_1 = unittest.TestSuite([Foo('foo_bar')])
+ tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
+
+ loader = unittest.TestLoader()
+ loader.testMethodPrefix = 'foo'
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_1)
+
+ loader.testMethodPrefix = 'test'
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_2)
+
+ # "String giving the prefix of method names which will be interpreted as
+ # test methods"
+ #
+ # Implicit in the documentation is that testMethodPrefix is respected by
+ # all loadTestsFrom* methods.
+ def test_testMethodPrefix__loadTestsFromModule(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests_1 = [unittest.TestSuite([Foo('foo_bar')])]
+ tests_2 = [unittest.TestSuite([Foo('test_1'), Foo('test_2')])]
+
+ loader = unittest.TestLoader()
+ loader.testMethodPrefix = 'foo'
+ self.assertEqual(list(loader.loadTestsFromModule(m)), tests_1)
+
+ loader.testMethodPrefix = 'test'
+ self.assertEqual(list(loader.loadTestsFromModule(m)), tests_2)
+
+ # "String giving the prefix of method names which will be interpreted as
+ # test methods"
+ #
+ # Implicit in the documentation is that testMethodPrefix is respected by
+ # all loadTestsFrom* methods.
+ def test_testMethodPrefix__loadTestsFromName(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests_1 = unittest.TestSuite([Foo('foo_bar')])
+ tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
+
+ loader = unittest.TestLoader()
+ loader.testMethodPrefix = 'foo'
+ self.assertEqual(loader.loadTestsFromName('Foo', m), tests_1)
+
+ loader.testMethodPrefix = 'test'
+ self.assertEqual(loader.loadTestsFromName('Foo', m), tests_2)
+
+ # "String giving the prefix of method names which will be interpreted as
+ # test methods"
+ #
+ # Implicit in the documentation is that testMethodPrefix is respected by
+ # all loadTestsFrom* methods.
+ def test_testMethodPrefix__loadTestsFromNames(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests_1 = unittest.TestSuite([unittest.TestSuite([Foo('foo_bar')])])
+ tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')])
+ tests_2 = unittest.TestSuite([tests_2])
+
+ loader = unittest.TestLoader()
+ loader.testMethodPrefix = 'foo'
+ self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_1)
+
+ loader.testMethodPrefix = 'test'
+ self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests_2)
+
+ # "The default value is 'test'"
+ def test_testMethodPrefix__default_value(self):
+ loader = unittest.TestLoader()
+ self.failUnless(loader.testMethodPrefix == 'test')
+
+ ################################################################
+ ### /Tests for TestLoader.testMethodPrefix
+
+ ### Tests for TestLoader.sortTestMethodsUsing
+ ################################################################
+
+ # "Function to be used to compare method names when sorting them in
+ # getTestCaseNames() and all the loadTestsFromX() methods"
+ def test_sortTestMethodsUsing__loadTestsFromTestCase(self):
+ def reversed_cmp(x, y):
+ return -cmp(x, y)
+
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = reversed_cmp
+
+ tests = loader.suiteClass([Foo('test_2'), Foo('test_1')])
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
+
+ # "Function to be used to compare method names when sorting them in
+ # getTestCaseNames() and all the loadTestsFromX() methods"
+ def test_sortTestMethodsUsing__loadTestsFromModule(self):
+ def reversed_cmp(x, y):
+ return -cmp(x, y)
+
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ m.Foo = Foo
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = reversed_cmp
+
+ tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])]
+ self.assertEqual(list(loader.loadTestsFromModule(m)), tests)
+
+ # "Function to be used to compare method names when sorting them in
+ # getTestCaseNames() and all the loadTestsFromX() methods"
+ def test_sortTestMethodsUsing__loadTestsFromName(self):
+ def reversed_cmp(x, y):
+ return -cmp(x, y)
+
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ m.Foo = Foo
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = reversed_cmp
+
+ tests = loader.suiteClass([Foo('test_2'), Foo('test_1')])
+ self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
+
+ # "Function to be used to compare method names when sorting them in
+ # getTestCaseNames() and all the loadTestsFromX() methods"
+ def test_sortTestMethodsUsing__loadTestsFromNames(self):
+ def reversed_cmp(x, y):
+ return -cmp(x, y)
+
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ m.Foo = Foo
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = reversed_cmp
+
+ tests = [loader.suiteClass([Foo('test_2'), Foo('test_1')])]
+ self.assertEqual(list(loader.loadTestsFromNames(['Foo'], m)), tests)
+
+ # "Function to be used to compare method names when sorting them in
+ # getTestCaseNames()"
+ #
+ # Does it actually affect getTestCaseNames()?
+ def test_sortTestMethodsUsing__getTestCaseNames(self):
+ def reversed_cmp(x, y):
+ return -cmp(x, y)
+
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = reversed_cmp
+
+ test_names = ['test_2', 'test_1']
+ self.assertEqual(loader.getTestCaseNames(Foo), test_names)
+
+ # "The default value is the built-in cmp() function"
+ def test_sortTestMethodsUsing__default_value(self):
+ loader = unittest.TestLoader()
+ self.failUnless(loader.sortTestMethodsUsing is cmp)
+
+ # "it can be set to None to disable the sort."
+ #
+ # XXX How is this different from reassigning cmp? Are the tests returned
+ # in a random order or something? This behaviour should die
+ def test_sortTestMethodsUsing__None(self):
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = None
+
+ test_names = ['test_2', 'test_1']
+ self.assertEqual(set(loader.getTestCaseNames(Foo)), set(test_names))
+
+ ################################################################
+ ### /Tests for TestLoader.sortTestMethodsUsing
+
+ ### Tests for TestLoader.suiteClass
+ ################################################################
+
+ # "Callable object that constructs a test suite from a list of tests."
+ def test_suiteClass__loadTestsFromTestCase(self):
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+
+ tests = [Foo('test_1'), Foo('test_2')]
+
+ loader = unittest.TestLoader()
+ loader.suiteClass = list
+ self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
+
+ # It is implicit in the documentation for TestLoader.suiteClass that
+ # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
+ def test_suiteClass__loadTestsFromModule(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests = [[Foo('test_1'), Foo('test_2')]]
+
+ loader = unittest.TestLoader()
+ loader.suiteClass = list
+ self.assertEqual(loader.loadTestsFromModule(m), tests)
+
+ # It is implicit in the documentation for TestLoader.suiteClass that
+ # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
+ def test_suiteClass__loadTestsFromName(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests = [Foo('test_1'), Foo('test_2')]
+
+ loader = unittest.TestLoader()
+ loader.suiteClass = list
+ self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
+
+ # It is implicit in the documentation for TestLoader.suiteClass that
+ # all TestLoader.loadTestsFrom* methods respect it. Let's make sure
+ def test_suiteClass__loadTestsFromNames(self):
+ import new
+ m = new.module('m')
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def foo_bar(self): pass
+ m.Foo = Foo
+
+ tests = [[Foo('test_1'), Foo('test_2')]]
+
+ loader = unittest.TestLoader()
+ loader.suiteClass = list
+ self.assertEqual(loader.loadTestsFromNames(['Foo'], m), tests)
+
+ # "The default value is the TestSuite class"
+ def test_suiteClass__default_value(self):
+ loader = unittest.TestLoader()
+ self.failUnless(loader.suiteClass is unittest.TestSuite)
+
+ ################################################################
+ ### /Tests for TestLoader.suiteClass
+
+### Support code for Test_TestSuite
+################################################################
+
+class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+ def test_3(self): pass
+ def runTest(self): pass
+
+def _mk_TestSuite(*names):
+ return unittest.TestSuite(Foo(n) for n in names)
+
+################################################################
+### /Support code for Test_TestSuite
+
+class Test_TestSuite(TestCase, TestEquality):
+
+ ### Set up attributes needed by inherited tests
+ ################################################################
+
+ # Used by TestEquality.test_eq
+ eq_pairs = [(unittest.TestSuite(), unittest.TestSuite())
+ ,(unittest.TestSuite(), unittest.TestSuite([]))
+ ,(_mk_TestSuite('test_1'), _mk_TestSuite('test_1'))]
+
+ # Used by TestEquality.test_ne
+ ne_pairs = [(unittest.TestSuite(), _mk_TestSuite('test_1'))
+ ,(unittest.TestSuite([]), _mk_TestSuite('test_1'))
+ ,(_mk_TestSuite('test_1', 'test_2'), _mk_TestSuite('test_1', 'test_3'))
+ ,(_mk_TestSuite('test_1'), _mk_TestSuite('test_2'))]
+
+ ################################################################
+ ### /Set up attributes needed by inherited tests
+
+ ### Tests for TestSuite.__init__
+ ################################################################
+
+ # "class TestSuite([tests])"
+ #
+ # The tests iterable should be optional
+ def test_init__tests_optional(self):
+ suite = unittest.TestSuite()
+
+ self.assertEqual(suite.countTestCases(), 0)
+
+ # "class TestSuite([tests])"
+ # ...
+ # "If tests is given, it must be an iterable of individual test cases
+ # or other test suites that will be used to build the suite initially"
+ #
+ # TestSuite should deal with empty tests iterables by allowing the
+ # creation of an empty suite
+ def test_init__empty_tests(self):
+ suite = unittest.TestSuite([])
+
+ self.assertEqual(suite.countTestCases(), 0)
+
+ # "class TestSuite([tests])"
+ # ...
+ # "If tests is given, it must be an iterable of individual test cases
+ # or other test suites that will be used to build the suite initially"
+ #
+ # TestSuite should allow any iterable to provide tests
+ def test_init__tests_from_any_iterable(self):
+ def tests():
+ yield unittest.FunctionTestCase(lambda: None)
+ yield unittest.FunctionTestCase(lambda: None)
+
+ suite_1 = unittest.TestSuite(tests())
+ self.assertEqual(suite_1.countTestCases(), 2)
+
+ suite_2 = unittest.TestSuite(suite_1)
+ self.assertEqual(suite_2.countTestCases(), 2)
+
+ suite_3 = unittest.TestSuite(set(suite_1))
+ self.assertEqual(suite_3.countTestCases(), 2)
+
+ # "class TestSuite([tests])"
+ # ...
+ # "If tests is given, it must be an iterable of individual test cases
+ # or other test suites that will be used to build the suite initially"
+ #
+ # Does TestSuite() also allow other TestSuite() instances to be present
+ # in the tests iterable?
+ def test_init__TestSuite_instances_in_tests(self):
+ def tests():
+ ftc = unittest.FunctionTestCase(lambda: None)
+ yield unittest.TestSuite([ftc])
+ yield unittest.FunctionTestCase(lambda: None)
+
+ suite = unittest.TestSuite(tests())
+ self.assertEqual(suite.countTestCases(), 2)
+
+ ################################################################
+ ### /Tests for TestSuite.__init__
+
+ # Container types should support the iter protocol
+ def test_iter(self):
+ test1 = unittest.FunctionTestCase(lambda: None)
+ test2 = unittest.FunctionTestCase(lambda: None)
+ suite = unittest.TestSuite((test1, test2))
+
+ self.assertEqual(list(suite), [test1, test2])
+
+ # "Return the number of tests represented by the this test object.
+ # ...this method is also implemented by the TestSuite class, which can
+ # return larger [greater than 1] values"
+ #
+ # Presumably an empty TestSuite returns 0?
+ def test_countTestCases_zero_simple(self):
+ suite = unittest.TestSuite()
+
+ self.assertEqual(suite.countTestCases(), 0)
+
+ # "Return the number of tests represented by the this test object.
+ # ...this method is also implemented by the TestSuite class, which can
+ # return larger [greater than 1] values"
+ #
+ # Presumably an empty TestSuite (even if it contains other empty
+ # TestSuite instances) returns 0?
+ def test_countTestCases_zero_nested(self):
+ class Test1(unittest.TestCase):
+ def test(self):
+ pass
+
+ suite = unittest.TestSuite([unittest.TestSuite()])
+
+ self.assertEqual(suite.countTestCases(), 0)
+
+ # "Return the number of tests represented by the this test object.
+ # ...this method is also implemented by the TestSuite class, which can
+ # return larger [greater than 1] values"
+ def test_countTestCases_simple(self):
+ test1 = unittest.FunctionTestCase(lambda: None)
+ test2 = unittest.FunctionTestCase(lambda: None)
+ suite = unittest.TestSuite((test1, test2))
+
+ self.assertEqual(suite.countTestCases(), 2)
+
+ # "Return the number of tests represented by the this test object.
+ # ...this method is also implemented by the TestSuite class, which can
+ # return larger [greater than 1] values"
+ #
+ # Make sure this holds for nested TestSuite instances, too
+ def test_countTestCases_nested(self):
+ class Test1(unittest.TestCase):
+ def test1(self): pass
+ def test2(self): pass
+
+ test2 = unittest.FunctionTestCase(lambda: None)
+ test3 = unittest.FunctionTestCase(lambda: None)
+ child = unittest.TestSuite((Test1('test2'), test2))
+ parent = unittest.TestSuite((test3, child, Test1('test1')))
+
+ self.assertEqual(parent.countTestCases(), 4)
+
+ # "Run the tests associated with this suite, collecting the result into
+ # the test result object passed as result."
+ #
+ # And if there are no tests? What then?
+ def test_run__empty_suite(self):
+ events = []
+ result = LoggingResult(events)
+
+ suite = unittest.TestSuite()
+
+ suite.run(result)
+
+ self.assertEqual(events, [])
+
+ # "Note that unlike TestCase.run(), TestSuite.run() requires the
+ # "result object to be passed in."
+ def test_run__requires_result(self):
+ suite = unittest.TestSuite()
+
+ try:
+ suite.run()
+ except TypeError:
+ pass
+ else:
+ self.fail("Failed to raise TypeError")
+
+ # "Run the tests associated with this suite, collecting the result into
+ # the test result object passed as result."
+ def test_run(self):
+ events = []
+ result = LoggingResult(events)
+
+ class LoggingCase(unittest.TestCase):
+ def run(self, result):
+ events.append('run %s' % self._testMethodName)
+
+ def test1(self): pass
+ def test2(self): pass
+
+ tests = [LoggingCase('test1'), LoggingCase('test2')]
+
+ unittest.TestSuite(tests).run(result)
+
+ self.assertEqual(events, ['run test1', 'run test2'])
+
+ # "Add a TestCase ... to the suite"
+ def test_addTest__TestCase(self):
+ class Foo(unittest.TestCase):
+ def test(self): pass
+
+ test = Foo('test')
+ suite = unittest.TestSuite()
+
+ suite.addTest(test)
+
+ self.assertEqual(suite.countTestCases(), 1)
+ self.assertEqual(list(suite), [test])
+
+ # "Add a ... TestSuite to the suite"
+ def test_addTest__TestSuite(self):
+ class Foo(unittest.TestCase):
+ def test(self): pass
+
+ suite_2 = unittest.TestSuite([Foo('test')])
+
+ suite = unittest.TestSuite()
+ suite.addTest(suite_2)
+
+ self.assertEqual(suite.countTestCases(), 1)
+ self.assertEqual(list(suite), [suite_2])
+
+ # "Add all the tests from an iterable of TestCase and TestSuite
+ # instances to this test suite."
+ #
+ # "This is equivalent to iterating over tests, calling addTest() for
+ # each element"
+ def test_addTests(self):
+ class Foo(unittest.TestCase):
+ def test_1(self): pass
+ def test_2(self): pass
+
+ test_1 = Foo('test_1')
+ test_2 = Foo('test_2')
+ inner_suite = unittest.TestSuite([test_2])
+
+ def gen():
+ yield test_1
+ yield test_2
+ yield inner_suite
+
+ suite_1 = unittest.TestSuite()
+ suite_1.addTests(gen())
+
+ self.assertEqual(list(suite_1), list(gen()))
+
+ # "This is equivalent to iterating over tests, calling addTest() for
+ # each element"
+ suite_2 = unittest.TestSuite()
+ for t in gen():
+ suite_2.addTest(t)
+
+ self.assertEqual(suite_1, suite_2)
+
+ # "Add all the tests from an iterable of TestCase and TestSuite
+ # instances to this test suite."
+ #
+ # What happens if it doesn't get an iterable?
+ def test_addTest__noniterable(self):
+ suite = unittest.TestSuite()
+
+ try:
+ suite.addTests(5)
+ except TypeError:
+ pass
+ else:
+ self.fail("Failed to raise TypeError")
+
+ def test_addTest__noncallable(self):
+ suite = unittest.TestSuite()
+ self.assertRaises(TypeError, suite.addTest, 5)
+
+ def test_addTest__casesuiteclass(self):
+ suite = unittest.TestSuite()
+ self.assertRaises(TypeError, suite.addTest, Test_TestSuite)
+ self.assertRaises(TypeError, suite.addTest, unittest.TestSuite)
+
+ def test_addTests__string(self):
+ suite = unittest.TestSuite()
+ self.assertRaises(TypeError, suite.addTests, "foo")
+
+
+class Test_FunctionTestCase(TestCase):
+
+ # "Return the number of tests represented by the this test object. For
+ # TestCase instances, this will always be 1"
+ def test_countTestCases(self):
+ test = unittest.FunctionTestCase(lambda: None)
+
+ self.assertEqual(test.countTestCases(), 1)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if setUp() raises
+ # an exception.
+ def test_run_call_order__error_in_setUp(self):
+ events = []
+ result = LoggingResult(events)
+
+ def setUp():
+ events.append('setUp')
+ raise RuntimeError('raised by setUp')
+
+ def test():
+ events.append('test')
+
+ def tearDown():
+ events.append('tearDown')
+
+ expected = ['startTest', 'setUp', 'addError', 'stopTest']
+ unittest.FunctionTestCase(test, setUp, tearDown).run(result)
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if the test raises
+ # an error (as opposed to a failure).
+ def test_run_call_order__error_in_test(self):
+ events = []
+ result = LoggingResult(events)
+
+ def setUp():
+ events.append('setUp')
+
+ def test():
+ events.append('test')
+ raise RuntimeError('raised by test')
+
+ def tearDown():
+ events.append('tearDown')
+
+ expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown',
+ 'stopTest']
+ unittest.FunctionTestCase(test, setUp, tearDown).run(result)
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if the test signals
+ # a failure (as opposed to an error).
+ def test_run_call_order__failure_in_test(self):
+ events = []
+ result = LoggingResult(events)
+
+ def setUp():
+ events.append('setUp')
+
+ def test():
+ events.append('test')
+ self.fail('raised by test')
+
+ def tearDown():
+ events.append('tearDown')
+
+ expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown',
+ 'stopTest']
+ unittest.FunctionTestCase(test, setUp, tearDown).run(result)
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if tearDown() raises
+ # an exception.
+ def test_run_call_order__error_in_tearDown(self):
+ events = []
+ result = LoggingResult(events)
+
+ def setUp():
+ events.append('setUp')
+
+ def test():
+ events.append('test')
+
+ def tearDown():
+ events.append('tearDown')
+ raise RuntimeError('raised by tearDown')
+
+ expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError',
+ 'stopTest']
+ unittest.FunctionTestCase(test, setUp, tearDown).run(result)
+ self.assertEqual(events, expected)
+
+ # "Return a string identifying the specific test case."
+ #
+ # Because of the vague nature of the docs, I'm not going to lock this
+ # test down too much. Really all that can be asserted is that the id()
+ # will be a string (either 8-byte or unicode -- again, because the docs
+ # just say "string")
+ def test_id(self):
+ test = unittest.FunctionTestCase(lambda: None)
+
+ self.failUnless(isinstance(test.id(), basestring))
+
+ # "Returns a one-line description of the test, or None if no description
+ # has been provided. The default implementation of this method returns
+ # the first line of the test method's docstring, if available, or None."
+ def test_shortDescription__no_docstring(self):
+ test = unittest.FunctionTestCase(lambda: None)
+
+ self.assertEqual(test.shortDescription(), None)
+
+ # "Returns a one-line description of the test, or None if no description
+ # has been provided. The default implementation of this method returns
+ # the first line of the test method's docstring, if available, or None."
+ def test_shortDescription__singleline_docstring(self):
+ desc = "this tests foo"
+ test = unittest.FunctionTestCase(lambda: None, description=desc)
+
+ self.assertEqual(test.shortDescription(), "this tests foo")
+
+class Test_TestResult(TestCase):
+ # Note: there are not separate tests for TestResult.wasSuccessful(),
+ # TestResult.errors, TestResult.failures, TestResult.testsRun or
+ # TestResult.shouldStop because these only have meaning in terms of
+ # other TestResult methods.
+ #
+ # Accordingly, tests for the aforenamed attributes are incorporated
+ # in with the tests for the defining methods.
+ ################################################################
+
+ def test_init(self):
+ result = unittest.TestResult()
+
+ self.failUnless(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 0)
+ self.assertEqual(result.shouldStop, False)
+
+ # "This method can be called to signal that the set of tests being
+ # run should be aborted by setting the TestResult's shouldStop
+ # attribute to True."
+ def test_stop(self):
+ result = unittest.TestResult()
+
+ result.stop()
+
+ self.assertEqual(result.shouldStop, True)
+
+ # "Called when the test case test is about to be run. The default
+ # implementation simply increments the instance's testsRun counter."
+ def test_startTest(self):
+ class Foo(unittest.TestCase):
+ def test_1(self):
+ pass
+
+ test = Foo('test_1')
+
+ result = unittest.TestResult()
+
+ result.startTest(test)
+
+ self.failUnless(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ result.stopTest(test)
+
+ # "Called after the test case test has been executed, regardless of
+ # the outcome. The default implementation does nothing."
+ def test_stopTest(self):
+ class Foo(unittest.TestCase):
+ def test_1(self):
+ pass
+
+ test = Foo('test_1')
+
+ result = unittest.TestResult()
+
+ result.startTest(test)
+
+ self.failUnless(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ result.stopTest(test)
+
+ # Same tests as above; make sure nothing has changed
+ self.failUnless(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ # "addSuccess(test)"
+ # ...
+ # "Called when the test case test succeeds"
+ # ...
+ # "wasSuccessful() - Returns True if all tests run so far have passed,
+ # otherwise returns False"
+ # ...
+ # "testsRun - The total number of tests run so far."
+ # ...
+ # "errors - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test which raised an
+ # unexpected exception. Contains formatted
+ # tracebacks instead of sys.exc_info() results."
+ # ...
+ # "failures - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test where a failure was
+ # explicitly signalled using the TestCase.fail*() or TestCase.assert*()
+ # methods. Contains formatted tracebacks instead
+ # of sys.exc_info() results."
+ def test_addSuccess(self):
+ class Foo(unittest.TestCase):
+ def test_1(self):
+ pass
+
+ test = Foo('test_1')
+
+ result = unittest.TestResult()
+
+ result.startTest(test)
+ result.addSuccess(test)
+ result.stopTest(test)
+
+ self.failUnless(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ # "addFailure(test, err)"
+ # ...
+ # "Called when the test case test signals a failure. err is a tuple of
+ # the form returned by sys.exc_info(): (type, value, traceback)"
+ # ...
+ # "wasSuccessful() - Returns True if all tests run so far have passed,
+ # otherwise returns False"
+ # ...
+ # "testsRun - The total number of tests run so far."
+ # ...
+ # "errors - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test which raised an
+ # unexpected exception. Contains formatted
+ # tracebacks instead of sys.exc_info() results."
+ # ...
+ # "failures - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test where a failure was
+ # explicitly signalled using the TestCase.fail*() or TestCase.assert*()
+ # methods. Contains formatted tracebacks instead
+ # of sys.exc_info() results."
+ def test_addFailure(self):
+ import sys
+
+ class Foo(unittest.TestCase):
+ def test_1(self):
+ pass
+
+ test = Foo('test_1')
+ try:
+ test.fail("foo")
+ except:
+ exc_info_tuple = sys.exc_info()
+
+ result = unittest.TestResult()
+
+ result.startTest(test)
+ result.addFailure(test, exc_info_tuple)
+ result.stopTest(test)
+
+ self.failIf(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ test_case, formatted_exc = result.failures[0]
+ self.failUnless(test_case is test)
+ self.failUnless(isinstance(formatted_exc, str))
+
+ # "addError(test, err)"
+ # ...
+ # "Called when the test case test raises an unexpected exception err
+ # is a tuple of the form returned by sys.exc_info():
+ # (type, value, traceback)"
+ # ...
+ # "wasSuccessful() - Returns True if all tests run so far have passed,
+ # otherwise returns False"
+ # ...
+ # "testsRun - The total number of tests run so far."
+ # ...
+ # "errors - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test which raised an
+ # unexpected exception. Contains formatted
+ # tracebacks instead of sys.exc_info() results."
+ # ...
+ # "failures - A list containing 2-tuples of TestCase instances and
+ # formatted tracebacks. Each tuple represents a test where a failure was
+ # explicitly signalled using the TestCase.fail*() or TestCase.assert*()
+ # methods. Contains formatted tracebacks instead
+ # of sys.exc_info() results."
+ def test_addError(self):
+ import sys
+
+ class Foo(unittest.TestCase):
+ def test_1(self):
+ pass
+
+ test = Foo('test_1')
+ try:
+ raise TypeError()
+ except:
+ exc_info_tuple = sys.exc_info()
+
+ result = unittest.TestResult()
+
+ result.startTest(test)
+ result.addError(test, exc_info_tuple)
+ result.stopTest(test)
+
+ self.failIf(result.wasSuccessful())
+ self.assertEqual(len(result.errors), 1)
+ self.assertEqual(len(result.failures), 0)
+ self.assertEqual(result.testsRun, 1)
+ self.assertEqual(result.shouldStop, False)
+
+ test_case, formatted_exc = result.errors[0]
+ self.failUnless(test_case is test)
+ self.failUnless(isinstance(formatted_exc, str))
+
+### Support code for Test_TestCase
+################################################################
+
+class Foo(unittest.TestCase):
+ def runTest(self): pass
+ def test1(self): pass
+
+class Bar(Foo):
+ def test2(self): pass
+
+################################################################
+### /Support code for Test_TestCase
+
+class Test_TestCase(TestCase, TestEquality, TestHashing):
+
+ ### Set up attributes used by inherited tests
+ ################################################################
+
+ # Used by TestHashing.test_hash and TestEquality.test_eq
+ eq_pairs = [(Foo('test1'), Foo('test1'))]
+
+ # Used by TestEquality.test_ne
+ ne_pairs = [(Foo('test1'), Foo('runTest'))
+ ,(Foo('test1'), Bar('test1'))
+ ,(Foo('test1'), Bar('test2'))]
+
+ ################################################################
+ ### /Set up attributes used by inherited tests
+
+
+ # "class TestCase([methodName])"
+ # ...
+ # "Each instance of TestCase will run a single test method: the
+ # method named methodName."
+ # ...
+ # "methodName defaults to "runTest"."
+ #
+ # Make sure it really is optional, and that it defaults to the proper
+ # thing.
+ def test_init__no_test_name(self):
+ class Test(unittest.TestCase):
+ def runTest(self): raise MyException()
+ def test(self): pass
+
+ self.assertEqual(Test().id()[-13:], '.Test.runTest')
+
+ # "class TestCase([methodName])"
+ # ...
+ # "Each instance of TestCase will run a single test method: the
+ # method named methodName."
+ def test_init__test_name__valid(self):
+ class Test(unittest.TestCase):
+ def runTest(self): raise MyException()
+ def test(self): pass
+
+ self.assertEqual(Test('test').id()[-10:], '.Test.test')
+
+ # "class TestCase([methodName])"
+ # ...
+ # "Each instance of TestCase will run a single test method: the
+ # method named methodName."
+ def test_init__test_name__invalid(self):
+ class Test(unittest.TestCase):
+ def runTest(self): raise MyException()
+ def test(self): pass
+
+ try:
+ Test('testfoo')
+ except ValueError:
+ pass
+ else:
+ self.fail("Failed to raise ValueError")
+
+ # "Return the number of tests represented by the this test object. For
+ # TestCase instances, this will always be 1"
+ def test_countTestCases(self):
+ class Foo(unittest.TestCase):
+ def test(self): pass
+
+ self.assertEqual(Foo('test').countTestCases(), 1)
+
+ # "Return the default type of test result object to be used to run this
+ # test. For TestCase instances, this will always be
+ # unittest.TestResult; subclasses of TestCase should
+ # override this as necessary."
+ def test_defaultTestResult(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ result = Foo().defaultTestResult()
+ self.assertEqual(type(result), unittest.TestResult)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if setUp() raises
+ # an exception.
+ def test_run_call_order__error_in_setUp(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def setUp(self):
+ events.append('setUp')
+ raise RuntimeError('raised by Foo.setUp')
+
+ def test(self):
+ events.append('test')
+
+ def tearDown(self):
+ events.append('tearDown')
+
+ Foo('test').run(result)
+ expected = ['startTest', 'setUp', 'addError', 'stopTest']
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if the test raises
+ # an error (as opposed to a failure).
+ def test_run_call_order__error_in_test(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def setUp(self):
+ events.append('setUp')
+
+ def test(self):
+ events.append('test')
+ raise RuntimeError('raised by Foo.test')
+
+ def tearDown(self):
+ events.append('tearDown')
+
+ expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown',
+ 'stopTest']
+ Foo('test').run(result)
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if the test signals
+ # a failure (as opposed to an error).
+ def test_run_call_order__failure_in_test(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def setUp(self):
+ events.append('setUp')
+
+ def test(self):
+ events.append('test')
+ self.fail('raised by Foo.test')
+
+ def tearDown(self):
+ events.append('tearDown')
+
+ expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown',
+ 'stopTest']
+ Foo('test').run(result)
+ self.assertEqual(events, expected)
+
+ # "When a setUp() method is defined, the test runner will run that method
+ # prior to each test. Likewise, if a tearDown() method is defined, the
+ # test runner will invoke that method after each test. In the example,
+ # setUp() was used to create a fresh sequence for each test."
+ #
+ # Make sure the proper call order is maintained, even if tearDown() raises
+ # an exception.
+ def test_run_call_order__error_in_tearDown(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def setUp(self):
+ events.append('setUp')
+
+ def test(self):
+ events.append('test')
+
+ def tearDown(self):
+ events.append('tearDown')
+ raise RuntimeError('raised by Foo.tearDown')
+
+ Foo('test').run(result)
+ expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError',
+ 'stopTest']
+ self.assertEqual(events, expected)
+
+ # "This class attribute gives the exception raised by the test() method.
+ # If a test framework needs to use a specialized exception, possibly to
+ # carry additional information, it must subclass this exception in
+ # order to ``play fair'' with the framework. The initial value of this
+ # attribute is AssertionError"
+ def test_failureException__default(self):
+ class Foo(unittest.TestCase):
+ def test(self):
+ pass
+
+ self.failUnless(Foo('test').failureException is AssertionError)
+
+ # "This class attribute gives the exception raised by the test() method.
+ # If a test framework needs to use a specialized exception, possibly to
+ # carry additional information, it must subclass this exception in
+ # order to ``play fair'' with the framework."
+ #
+ # Make sure TestCase.run() respects the designated failureException
+ def test_failureException__subclassing__explicit_raise(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def test(self):
+ raise RuntimeError()
+
+ failureException = RuntimeError
+
+ self.failUnless(Foo('test').failureException is RuntimeError)
+
+
+ Foo('test').run(result)
+ expected = ['startTest', 'addFailure', 'stopTest']
+ self.assertEqual(events, expected)
+
+ # "This class attribute gives the exception raised by the test() method.
+ # If a test framework needs to use a specialized exception, possibly to
+ # carry additional information, it must subclass this exception in
+ # order to ``play fair'' with the framework."
+ #
+ # Make sure TestCase.run() respects the designated failureException
+ def test_failureException__subclassing__implicit_raise(self):
+ events = []
+ result = LoggingResult(events)
+
+ class Foo(unittest.TestCase):
+ def test(self):
+ self.fail("foo")
+
+ failureException = RuntimeError
+
+ self.failUnless(Foo('test').failureException is RuntimeError)
+
+
+ Foo('test').run(result)
+ expected = ['startTest', 'addFailure', 'stopTest']
+ self.assertEqual(events, expected)
+
+ # "The default implementation does nothing."
+ def test_setUp(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ # ... and nothing should happen
+ Foo().setUp()
+
+ # "The default implementation does nothing."
+ def test_tearDown(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ # ... and nothing should happen
+ Foo().tearDown()
+
+ # "Return a string identifying the specific test case."
+ #
+ # Because of the vague nature of the docs, I'm not going to lock this
+ # test down too much. Really all that can be asserted is that the id()
+ # will be a string (either 8-byte or unicode -- again, because the docs
+ # just say "string")
+ def test_id(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ self.failUnless(isinstance(Foo().id(), basestring))
+
+ # "Returns a one-line description of the test, or None if no description
+ # has been provided. The default implementation of this method returns
+ # the first line of the test method's docstring, if available, or None."
+ def test_shortDescription__no_docstring(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ pass
+
+ self.assertEqual(Foo().shortDescription(), None)
+
+ # "Returns a one-line description of the test, or None if no description
+ # has been provided. The default implementation of this method returns
+ # the first line of the test method's docstring, if available, or None."
+ def test_shortDescription__singleline_docstring(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ "this tests foo"
+ pass
+
+ self.assertEqual(Foo().shortDescription(), "this tests foo")
+
+ # "Returns a one-line description of the test, or None if no description
+ # has been provided. The default implementation of this method returns
+ # the first line of the test method's docstring, if available, or None."
+ def test_shortDescription__multiline_docstring(self):
+ class Foo(unittest.TestCase):
+ def runTest(self):
+ """this tests foo
+ blah, bar and baz are also tested"""
+ pass
+
+ self.assertEqual(Foo().shortDescription(), "this tests foo")
+
+ # "If result is omitted or None, a temporary result object is created
+ # and used, but is not made available to the caller"
+ def test_run__uses_defaultTestResult(self):
+ events = []
+
+ class Foo(unittest.TestCase):
+ def test(self):
+ events.append('test')
+
+ def defaultTestResult(self):
+ return LoggingResult(events)
-def test_TestSuite_iter():
- """
- >>> test1 = unittest.FunctionTestCase(lambda: None)
- >>> test2 = unittest.FunctionTestCase(lambda: None)
- >>> suite = unittest.TestSuite((test1, test2))
- >>> tests = []
- >>> for test in suite:
- ... tests.append(test)
- >>> tests == [test1, test2]
- True
- """
+ # Make run() find a result object on its own
+ Foo('test').run()
+ expected = ['startTest', 'test', 'stopTest']
+ self.assertEqual(events, expected)
######################################################################
## Main
######################################################################
def test_main():
- from test import test_support, test_unittest
- test_support.run_doctest(test_unittest, verbosity=True)
+ test_support.run_unittest(Test_TestCase, Test_TestLoader,
+ Test_TestSuite, Test_TestResult, Test_FunctionTestCase)
-if __name__ == '__main__':
+if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py
index cd48689..75033ed 100644
--- a/Lib/test/test_unpack.py
+++ b/Lib/test/test_unpack.py
@@ -55,7 +55,7 @@ Unpacking non-sequence
>>> a, b, c = 7
Traceback (most recent call last):
...
- TypeError: unpack non-sequence
+ TypeError: 'int' object is not iterable
Unpacking tuple of wrong size
diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py
index 16c612e..3a37525 100644
--- a/Lib/test/test_urllib.py
+++ b/Lib/test/test_urllib.py
@@ -122,6 +122,15 @@ class urlopen_HttpTests(unittest.TestCase):
finally:
self.unfakehttp()
+ def test_empty_socket(self):
+ """urlopen() raises IOError if the underlying socket does not send any
+ data. (#1680230) """
+ self.fakehttp('')
+ try:
+ self.assertRaises(IOError, urllib.urlopen, 'http://something')
+ finally:
+ self.unfakehttp()
+
class urlretrieve_FileTests(unittest.TestCase):
"""Test urllib.urlretrieve() on local files"""
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 6187dad..10d8c46 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -625,11 +625,11 @@ class HandlerTests(unittest.TestCase):
for url in [
"file://localhost:80%s" % urlpath,
-# XXXX bug: these fail with socket.gaierror, should be URLError
-## "file://%s:80%s/%s" % (socket.gethostbyname('localhost'),
-## os.getcwd(), TESTFN),
-## "file://somerandomhost.ontheinternet.com%s/%s" %
-## (os.getcwd(), TESTFN),
+ "file:///file_does_not_exist.txt",
+ "file://%s:80%s/%s" % (socket.gethostbyname('localhost'),
+ os.getcwd(), TESTFN),
+ "file://somerandomhost.ontheinternet.com%s/%s" %
+ (os.getcwd(), TESTFN),
]:
try:
f = open(TESTFN, "wb")
@@ -765,16 +765,24 @@ class HandlerTests(unittest.TestCase):
url = "http://example.com/"
req = Request(url)
- # 200 OK is passed through
+ # all 2xx are passed through
r = MockResponse(200, "OK", {}, "", url)
newr = h.http_response(req, r)
self.assert_(r is newr)
self.assert_(not hasattr(o, "proto")) # o.error not called
+ r = MockResponse(202, "Accepted", {}, "", url)
+ newr = h.http_response(req, r)
+ self.assert_(r is newr)
+ self.assert_(not hasattr(o, "proto")) # o.error not called
+ r = MockResponse(206, "Partial content", {}, "", url)
+ newr = h.http_response(req, r)
+ self.assert_(r is newr)
+ self.assert_(not hasattr(o, "proto")) # o.error not called
# anything else calls o.error (and MockOpener returns None, here)
- r = MockResponse(201, "Created", {}, "", url)
+ r = MockResponse(502, "Bad gateway", {}, "", url)
self.assert_(h.http_response(req, r) is None)
self.assertEqual(o.proto, "http") # o.error called
- self.assertEqual(o.args, (req, r, 201, "Created", {}))
+ self.assertEqual(o.args, (req, r, 502, "Bad gateway", {}))
def test_cookies(self):
cj = MockCookieJar()
diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py
index 60d5f48..a52c3dd 100644
--- a/Lib/test/test_urllib2net.py
+++ b/Lib/test/test_urllib2net.py
@@ -264,7 +264,8 @@ class OtherNetworkTests(unittest.TestCase):
(expected_err, url, req, err))
self.assert_(isinstance(err, expected_err), msg)
else:
- buf = f.read()
+ with test_support.transient_internet():
+ buf = f.read()
f.close()
debug("read %d bytes" % len(buf))
debug("******** next url coming up...")
diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py
index 500971b..8c72463 100644
--- a/Lib/test/test_userdict.py
+++ b/Lib/test/test_userdict.py
@@ -171,7 +171,7 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
except RuntimeError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("e[42] didn't raise RuntimeError")
+ self.fail("e[42] didn't raise RuntimeError")
class F(UserDict.UserDict):
def __init__(self):
# An instance variable __missing__ should have no effect
@@ -183,7 +183,7 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
except KeyError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("f[42] didn't raise KeyError")
+ self.fail("f[42] didn't raise KeyError")
class G(UserDict.UserDict):
pass
g = G()
@@ -192,7 +192,7 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
except KeyError as err:
self.assertEqual(err.args, (42,))
else:
- self.fail_("g[42] didn't raise KeyError")
+ self.fail("g[42] didn't raise KeyError")
##########################
# Test Dict Mixin
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
index a7ccb6b..283806f 100644
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -3,95 +3,97 @@ import os
import unittest
from test import test_support
-# The warnings module isn't easily tested, because it relies on module
-# globals to store configuration information. setUp() and tearDown()
-# preserve the current settings to avoid bashing them while running tests.
-
-# To capture the warning messages, a replacement for showwarning() is
-# used to save warning information in a global variable.
-
-class WarningMessage:
- "Holds results of latest showwarning() call"
- pass
-
-def showwarning(message, category, filename, lineno, file=None):
- msg.message = str(message)
- msg.category = category.__name__
- msg.filename = os.path.basename(filename)
- msg.lineno = lineno
+import warning_tests
class TestModule(unittest.TestCase):
-
def setUp(self):
- global msg
- msg = WarningMessage()
- self._filters = warnings.filters[:]
- self._showwarning = warnings.showwarning
- warnings.showwarning = showwarning
- self.ignored = [w[2].__name__ for w in self._filters
+ self.ignored = [w[2].__name__ for w in warnings.filters
if w[0]=='ignore' and w[1] is None and w[3] is None]
- def tearDown(self):
- warnings.filters = self._filters[:]
- warnings.showwarning = self._showwarning
-
def test_warn_default_category(self):
- for i in range(4):
- text = 'multi %d' %i # Different text on each call
- warnings.warn(text)
- self.assertEqual(msg.message, text)
- self.assertEqual(msg.category, 'UserWarning')
+ with test_support.catch_warning() as w:
+ for i in range(4):
+ text = 'multi %d' %i # Different text on each call
+ warnings.warn(text)
+ self.assertEqual(str(w.message), text)
+ self.assert_(w.category is UserWarning)
def test_warn_specific_category(self):
- text = 'None'
- for category in [DeprecationWarning, FutureWarning,
- PendingDeprecationWarning, RuntimeWarning,
- SyntaxWarning, UserWarning, Warning]:
- if category.__name__ in self.ignored:
- text = 'filtered out' + category.__name__
- warnings.warn(text, category)
- self.assertNotEqual(msg.message, text)
- else:
- text = 'unfiltered %s' % category.__name__
- warnings.warn(text, category)
- self.assertEqual(msg.message, text)
- self.assertEqual(msg.category, category.__name__)
+ with test_support.catch_warning() as w:
+ text = 'None'
+ for category in [DeprecationWarning, FutureWarning,
+ PendingDeprecationWarning, RuntimeWarning,
+ SyntaxWarning, UserWarning, Warning]:
+ if category.__name__ in self.ignored:
+ text = 'filtered out' + category.__name__
+ warnings.warn(text, category)
+ self.assertNotEqual(w.message, text)
+ else:
+ text = 'unfiltered %s' % category.__name__
+ warnings.warn(text, category)
+ self.assertEqual(str(w.message), text)
+ self.assert_(w.category is category)
def test_filtering(self):
+ with test_support.catch_warning() as w:
+ warnings.filterwarnings("error", "", Warning, "", 0)
+ self.assertRaises(UserWarning, warnings.warn, 'convert to error')
- warnings.filterwarnings("error", "", Warning, "", 0)
- self.assertRaises(UserWarning, warnings.warn, 'convert to error')
-
- warnings.resetwarnings()
- text = 'handle normally'
- warnings.warn(text)
- self.assertEqual(msg.message, text)
- self.assertEqual(msg.category, 'UserWarning')
+ warnings.resetwarnings()
+ text = 'handle normally'
+ warnings.warn(text)
+ self.assertEqual(str(w.message), text)
+ self.assert_(w.category is UserWarning)
- warnings.filterwarnings("ignore", "", Warning, "", 0)
- text = 'filtered out'
- warnings.warn(text)
- self.assertNotEqual(msg.message, text)
+ warnings.filterwarnings("ignore", "", Warning, "", 0)
+ text = 'filtered out'
+ warnings.warn(text)
+ self.assertNotEqual(str(w.message), text)
- warnings.resetwarnings()
- warnings.filterwarnings("error", "hex*", Warning, "", 0)
- self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
- text = 'nonmatching text'
- warnings.warn(text)
- self.assertEqual(msg.message, text)
- self.assertEqual(msg.category, 'UserWarning')
+ warnings.resetwarnings()
+ warnings.filterwarnings("error", "hex*", Warning, "", 0)
+ self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
+ text = 'nonmatching text'
+ warnings.warn(text)
+ self.assertEqual(str(w.message), text)
+ self.assert_(w.category is UserWarning)
def test_options(self):
# Uses the private _setoption() function to test the parsing
# of command-line warning arguments
- self.assertRaises(warnings._OptionError,
- warnings._setoption, '1:2:3:4:5:6')
- self.assertRaises(warnings._OptionError,
- warnings._setoption, 'bogus::Warning')
- self.assertRaises(warnings._OptionError,
- warnings._setoption, 'ignore:2::4:-5')
- warnings._setoption('error::Warning::0')
- self.assertRaises(UserWarning, warnings.warn, 'convert to error')
+ with test_support.guard_warnings_filter():
+ self.assertRaises(warnings._OptionError,
+ warnings._setoption, '1:2:3:4:5:6')
+ self.assertRaises(warnings._OptionError,
+ warnings._setoption, 'bogus::Warning')
+ self.assertRaises(warnings._OptionError,
+ warnings._setoption, 'ignore:2::4:-5')
+ warnings._setoption('error::Warning::0')
+ self.assertRaises(UserWarning, warnings.warn, 'convert to error')
+
+ def test_filename(self):
+ with test_support.catch_warning() as w:
+ warning_tests.inner("spam1")
+ self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
+ warning_tests.outer("spam2")
+ self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
+
+ def test_stacklevel(self):
+ # Test stacklevel argument
+ # make sure all messages are different, so the warning won't be skipped
+ with test_support.catch_warning() as w:
+ warning_tests.inner("spam3", stacklevel=1)
+ self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
+ warning_tests.outer("spam4", stacklevel=1)
+ self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
+
+ warning_tests.inner("spam5", stacklevel=2)
+ self.assertEqual(os.path.basename(w.filename), "test_warnings.py")
+ warning_tests.outer("spam6", stacklevel=2)
+ self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
+
+ warning_tests.inner("spam7", stacklevel=9999)
+ self.assertEqual(os.path.basename(w.filename), "sys")
def test_main(verbose=None):
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 46dd5ff..99a5178a 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -841,7 +841,7 @@ class MappingTestCase(TestBase):
items = dict.items()
for item in dict.items():
items.remove(item)
- self.assert_(len(items) == 0, "iteritems() did not touch all items")
+ self.assert_(len(items) == 0, "items() did not touch all items")
# key iterator, via __iter__():
keys = list(dict.keys())
@@ -1104,7 +1104,7 @@ None
... self.__counter += 1
... ob = (ob, self.__counter)
... return ob
-...
+...
>>> class A: # not in docs from here, just testing the ExtendedRef
... pass
...
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
index d77e861..213c5cf 100755
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -1,5 +1,5 @@
from __future__ import nested_scopes # Backward compat for 2.1
-from unittest import TestSuite, TestCase, makeSuite
+from unittest import TestCase
from wsgiref.util import setup_testing_defaults
from wsgiref.headers import Headers
from wsgiref.handlers import BaseHandler, BaseCGIHandler
@@ -11,6 +11,7 @@ from StringIO import StringIO
from SocketServer import BaseServer
import re, sys
+from test import test_support
class MockServer(WSGIServer):
"""Non-socket HTTP server"""
@@ -575,11 +576,7 @@ class HandlerTests(TestCase):
# This epilogue is needed for compatibility with the Python 2.5 regrtest module
def test_main():
- import unittest
- from test.test_support import run_suite
- run_suite(
- unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__])
- )
+ test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index d6f5534..a6500da 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -4,26 +4,30 @@ try:
except ImportError:
zlib = None
-import zipfile, os, unittest, sys, shutil
+import zipfile, os, unittest, sys, shutil, struct
from StringIO import StringIO
from tempfile import TemporaryFile
+from random import randint, random
+import test.test_support as support
from test.test_support import TESTFN, run_unittest
TESTFN2 = TESTFN + "2"
+FIXEDTEST_SIZE = 10
class TestsWithSourceFile(unittest.TestCase):
def setUp(self):
- line_gen = ("Test of zipfile line %d." % i for i in range(0, 1000))
- self.data = '\n'.join(line_gen)
+ self.line_gen = ("Zipfile test line %d. random float: %f" % (i, random())
+ for i in xrange(FIXEDTEST_SIZE))
+ self.data = '\n'.join(self.line_gen) + '\n'
# Make a source file with some lines
fp = open(TESTFN, "wb")
fp.write(self.data)
fp.close()
- def zipTest(self, f, compression):
+ def makeTestArchive(self, f, compression):
# Create the ZIP archive
zipfp = zipfile.ZipFile(f, "w", compression)
zipfp.write(TESTFN, "another"+os.extsep+"name")
@@ -31,6 +35,9 @@ class TestsWithSourceFile(unittest.TestCase):
zipfp.writestr("strfile", self.data)
zipfp.close()
+ def zipTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
# Read the ZIP archive
zipfp = zipfile.ZipFile(f, "r", compression)
self.assertEqual(zipfp.read(TESTFN), self.data)
@@ -85,22 +92,144 @@ class TestsWithSourceFile(unittest.TestCase):
# Check that testzip doesn't raise an exception
zipfp.testzip()
+ zipfp.close()
+ def testStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipTest(f, zipfile.ZIP_STORED)
+
+ def zipOpenTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r", compression)
+ zipdata1 = []
+ zipopen1 = zipfp.open(TESTFN)
+ while 1:
+ read_data = zipopen1.read(256)
+ if not read_data:
+ break
+ zipdata1.append(read_data)
+
+ zipdata2 = []
+ zipopen2 = zipfp.open("another"+os.extsep+"name")
+ while 1:
+ read_data = zipopen2.read(256)
+ if not read_data:
+ break
+ zipdata2.append(read_data)
+
+ self.assertEqual(''.join(zipdata1), self.data)
+ self.assertEqual(''.join(zipdata2), self.data)
zipfp.close()
+ def testOpenStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipOpenTest(f, zipfile.ZIP_STORED)
+ def zipRandomOpenTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r", compression)
+ zipdata1 = []
+ zipopen1 = zipfp.open(TESTFN)
+ while 1:
+ read_data = zipopen1.read(randint(1, 1024))
+ if not read_data:
+ break
+ zipdata1.append(read_data)
+
+ self.assertEqual(''.join(zipdata1), self.data)
+ zipfp.close()
- def testStored(self):
+ def testRandomOpenStored(self):
for f in (TESTFN2, TemporaryFile(), StringIO()):
- self.zipTest(f, zipfile.ZIP_STORED)
+ self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
+
+ def zipReadlineTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ zipopen = zipfp.open(TESTFN)
+ for line in self.line_gen:
+ linedata = zipopen.readline()
+ self.assertEqual(linedata, line + '\n')
+
+ zipfp.close()
+
+ def zipReadlinesTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ ziplines = zipfp.open(TESTFN).readlines()
+ for line, zipline in zip(self.line_gen, ziplines):
+ self.assertEqual(zipline, line + '\n')
+
+ zipfp.close()
+
+ def zipIterlinesTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
+ self.assertEqual(zipline, line + '\n')
+
+ zipfp.close()
+
+ def testReadlineStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipReadlineTest(f, zipfile.ZIP_STORED)
+
+ def testReadlinesStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipReadlinesTest(f, zipfile.ZIP_STORED)
+
+ def testIterlinesStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipIterlinesTest(f, zipfile.ZIP_STORED)
if zlib:
def testDeflated(self):
for f in (TESTFN2, TemporaryFile(), StringIO()):
self.zipTest(f, zipfile.ZIP_DEFLATED)
+ def testOpenDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
+
+ def testRandomOpenDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
+
+ def testReadlineDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
+
+ def testReadlinesDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
+
+ def testIterlinesDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
+
+ def testLowCompression(self):
+ # Checks for cases where compressed data is larger than original
+ # Create the ZIP archive
+ zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
+ zipfp.writestr("strfile", '12')
+ zipfp.close()
+
+ # Get an open object for strfile
+ zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
+ openobj = zipfp.open("strfile")
+ self.assertEqual(openobj.read(1), '1')
+ self.assertEqual(openobj.read(1), '2')
+
def testAbsoluteArcnames(self):
zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
zipfp.write(TESTFN, "/absolute")
@@ -110,7 +239,6 @@ class TestsWithSourceFile(unittest.TestCase):
self.assertEqual(zipfp.namelist(), ["absolute"])
zipfp.close()
-
def tearDown(self):
os.remove(TESTFN)
os.remove(TESTFN2)
@@ -123,7 +251,7 @@ class TestZip64InSmallFiles(unittest.TestCase):
self._limit = zipfile.ZIP64_LIMIT
zipfile.ZIP64_LIMIT = 5
- line_gen = ("Test of zipfile line %d." % i for i in range(0, 1000))
+ line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE))
self.data = '\n'.join(line_gen)
# Make a source file with some lines
@@ -310,10 +438,10 @@ class OtherTests(unittest.TestCase):
def testCreateNonExistentFileForAppend(self):
if os.path.exists(TESTFN):
os.unlink(TESTFN)
-
+
filename = 'testfile.txt'
content = 'hello, world. this is some content.'
-
+
try:
zf = zipfile.ZipFile(TESTFN, 'a')
zf.writestr(filename, content)
@@ -326,9 +454,7 @@ class OtherTests(unittest.TestCase):
zf = zipfile.ZipFile(TESTFN, 'r')
self.assertEqual(zf.read(filename), content)
zf.close()
-
- os.unlink(TESTFN)
-
+
def testCloseErroneousFile(self):
# This test checks that the ZipFile constructor closes the file object
# it opens if there's an error in the file. If it doesn't, the traceback
@@ -342,7 +468,25 @@ class OtherTests(unittest.TestCase):
try:
zf = zipfile.ZipFile(TESTFN)
except zipfile.BadZipfile:
- os.unlink(TESTFN)
+ pass
+
+ def testIsZipErroneousFile(self):
+ # This test checks that the is_zipfile function correctly identifies
+ # a file that is not a zip file
+ fp = open(TESTFN, "w")
+ fp.write("this is not a legal zip file\n")
+ fp.close()
+ chk = zipfile.is_zipfile(TESTFN)
+ self.assert_(chk is False)
+
+ def testIsZipValidFile(self):
+ # This test checks that the is_zipfile function correctly identifies
+ # a file that is a zip file
+ zipf = zipfile.ZipFile(TESTFN, mode="w")
+ zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+ zipf.close()
+ chk = zipfile.is_zipfile(TESTFN)
+ self.assert_(chk is True)
def testNonExistentFileRaisesIOError(self):
# make sure we don't raise an AttributeError when a partially-constructed
@@ -371,6 +515,9 @@ class OtherTests(unittest.TestCase):
# and report that the first file in the archive was corrupt.
self.assertRaises(RuntimeError, zipf.testzip)
+ def tearDown(self):
+ support.unlink(TESTFN)
+ support.unlink(TESTFN2)
class DecryptionTests(unittest.TestCase):
# This test checks that ZIP decryption works. Since the library does not
@@ -406,15 +553,265 @@ class DecryptionTests(unittest.TestCase):
def testBadPassword(self):
self.zip.setpassword("perl")
self.assertRaises(RuntimeError, self.zip.read, "test.txt")
-
+
def testGoodPassword(self):
self.zip.setpassword("python")
self.assertEquals(self.zip.read("test.txt"), self.plain)
+
+class TestsWithRandomBinaryFiles(unittest.TestCase):
+ def setUp(self):
+ datacount = randint(16, 64)*1024 + randint(1, 1024)
+ self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in xrange(datacount)))
+
+ # Make a source file with some lines
+ fp = open(TESTFN, "wb")
+ fp.write(self.data)
+ fp.close()
+
+ def tearDown(self):
+ support.unlink(TESTFN)
+ support.unlink(TESTFN2)
+
+ def makeTestArchive(self, f, compression):
+ # Create the ZIP archive
+ zipfp = zipfile.ZipFile(f, "w", compression)
+ zipfp.write(TESTFN, "another"+os.extsep+"name")
+ zipfp.write(TESTFN, TESTFN)
+ zipfp.close()
+
+ def zipTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r", compression)
+ testdata = zipfp.read(TESTFN)
+ self.assertEqual(len(testdata), len(self.data))
+ self.assertEqual(testdata, self.data)
+ self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
+ zipfp.close()
+
+ def testStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipTest(f, zipfile.ZIP_STORED)
+
+ def zipOpenTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r", compression)
+ zipdata1 = []
+ zipopen1 = zipfp.open(TESTFN)
+ while 1:
+ read_data = zipopen1.read(256)
+ if not read_data:
+ break
+ zipdata1.append(read_data)
+
+ zipdata2 = []
+ zipopen2 = zipfp.open("another"+os.extsep+"name")
+ while 1:
+ read_data = zipopen2.read(256)
+ if not read_data:
+ break
+ zipdata2.append(read_data)
+
+ testdata1 = ''.join(zipdata1)
+ self.assertEqual(len(testdata1), len(self.data))
+ self.assertEqual(testdata1, self.data)
+
+ testdata2 = ''.join(zipdata2)
+ self.assertEqual(len(testdata1), len(self.data))
+ self.assertEqual(testdata1, self.data)
+ zipfp.close()
+
+ def testOpenStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipOpenTest(f, zipfile.ZIP_STORED)
+
+ def zipRandomOpenTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r", compression)
+ zipdata1 = []
+ zipopen1 = zipfp.open(TESTFN)
+ while 1:
+ read_data = zipopen1.read(randint(1, 1024))
+ if not read_data:
+ break
+ zipdata1.append(read_data)
+
+ testdata = ''.join(zipdata1)
+ self.assertEqual(len(testdata), len(self.data))
+ self.assertEqual(testdata, self.data)
+ zipfp.close()
+
+ def testRandomOpenStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
+
+class TestsWithMultipleOpens(unittest.TestCase):
+ def setUp(self):
+ # Create the ZIP archive
+ zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
+ zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
+ zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
+ zipfp.close()
+
+ def testSameFile(self):
+ # Verify that (when the ZipFile is in control of creating file objects)
+ # multiple open() calls can be made without interfering with each other.
+ zipf = zipfile.ZipFile(TESTFN2, mode="r")
+ zopen1 = zipf.open('ones')
+ zopen2 = zipf.open('ones')
+ data1 = zopen1.read(500)
+ data2 = zopen2.read(500)
+ data1 += zopen1.read(500)
+ data2 += zopen2.read(500)
+ self.assertEqual(data1, data2)
+ zipf.close()
+
+ def testDifferentFile(self):
+ # Verify that (when the ZipFile is in control of creating file objects)
+ # multiple open() calls can be made without interfering with each other.
+ zipf = zipfile.ZipFile(TESTFN2, mode="r")
+ zopen1 = zipf.open('ones')
+ zopen2 = zipf.open('twos')
+ data1 = zopen1.read(500)
+ data2 = zopen2.read(500)
+ data1 += zopen1.read(500)
+ data2 += zopen2.read(500)
+ self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
+ self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
+ zipf.close()
+
+ def testInterleaved(self):
+ # Verify that (when the ZipFile is in control of creating file objects)
+ # multiple open() calls can be made without interfering with each other.
+ zipf = zipfile.ZipFile(TESTFN2, mode="r")
+ zopen1 = zipf.open('ones')
+ data1 = zopen1.read(500)
+ zopen2 = zipf.open('twos')
+ data2 = zopen2.read(500)
+ data1 += zopen1.read(500)
+ data2 += zopen2.read(500)
+ self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
+ self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
+ zipf.close()
+
+ def tearDown(self):
+ os.remove(TESTFN2)
+
+
+class UniversalNewlineTests(unittest.TestCase):
+ def setUp(self):
+ self.line_gen = ["Test of zipfile line %d." % i for i in xrange(FIXEDTEST_SIZE)]
+ self.seps = ('\r', '\r\n', '\n')
+ self.arcdata, self.arcfiles = {}, {}
+ for n, s in enumerate(self.seps):
+ self.arcdata[s] = s.join(self.line_gen) + s
+ self.arcfiles[s] = '%s-%d' % (TESTFN, n)
+ file(self.arcfiles[s], "wb").write(self.arcdata[s])
+
+ def makeTestArchive(self, f, compression):
+ # Create the ZIP archive
+ zipfp = zipfile.ZipFile(f, "w", compression)
+ for fn in self.arcfiles.values():
+ zipfp.write(fn, fn)
+ zipfp.close()
+
+ def readTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ for sep, fn in self.arcfiles.items():
+ zipdata = zipfp.open(fn, "rU").read()
+ self.assertEqual(self.arcdata[sep], zipdata)
+
+ zipfp.close()
+
+ def readlineTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ for sep, fn in self.arcfiles.items():
+ zipopen = zipfp.open(fn, "rU")
+ for line in self.line_gen:
+ linedata = zipopen.readline()
+ self.assertEqual(linedata, line + '\n')
+
+ zipfp.close()
+
+ def readlinesTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ for sep, fn in self.arcfiles.items():
+ ziplines = zipfp.open(fn, "rU").readlines()
+ for line, zipline in zip(self.line_gen, ziplines):
+ self.assertEqual(zipline, line + '\n')
+
+ zipfp.close()
+
+ def iterlinesTest(self, f, compression):
+ self.makeTestArchive(f, compression)
+
+ # Read the ZIP archive
+ zipfp = zipfile.ZipFile(f, "r")
+ for sep, fn in self.arcfiles.items():
+ for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
+ self.assertEqual(zipline, line + '\n')
+
+ zipfp.close()
+
+ def testReadStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readTest(f, zipfile.ZIP_STORED)
+
+ def testReadlineStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readlineTest(f, zipfile.ZIP_STORED)
+
+ def testReadlinesStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readlinesTest(f, zipfile.ZIP_STORED)
+
+ def testIterlinesStored(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.iterlinesTest(f, zipfile.ZIP_STORED)
+
+ if zlib:
+ def testReadDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readTest(f, zipfile.ZIP_DEFLATED)
+
+ def testReadlineDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readlineTest(f, zipfile.ZIP_DEFLATED)
+
+ def testReadlinesDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.readlinesTest(f, zipfile.ZIP_DEFLATED)
+
+ def testIterlinesDeflated(self):
+ for f in (TESTFN2, TemporaryFile(), StringIO()):
+ self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
+
+ def tearDown(self):
+ for sep, fn in self.arcfiles.items():
+ os.remove(fn)
+ support.unlink(TESTFN)
+ support.unlink(TESTFN2)
+
+
def test_main():
- run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
- PyZipFileTests, DecryptionTests)
- #run_unittest(TestZip64InSmallFiles)
+ run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
+ PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
+ UniversalNewlineTests, TestsWithRandomBinaryFiles)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py
index 0be9668..dc4a7d8 100644
--- a/Lib/test/test_zlib.py
+++ b/Lib/test/test_zlib.py
@@ -3,22 +3,6 @@ from test import test_support
import zlib
import random
-# print test_support.TESTFN
-
-def getbuf():
- # This was in the original. Avoid non-repeatable sources.
- # Left here (unused) in case something wants to be done with it.
- import imp
- try:
- t = imp.find_module('test_zlib')
- file = t[0]
- except ImportError:
- file = open(__file__)
- buf = file.read() * 8
- file.close()
- return buf
-
-
class ChecksumTestCase(unittest.TestCase):
# checksum test cases
@@ -461,21 +445,3 @@ def test_main():
if __name__ == "__main__":
test_main()
-
-def test(tests=''):
- if not tests: tests = 'o'
- testcases = []
- if 'k' in tests: testcases.append(ChecksumTestCase)
- if 'x' in tests: testcases.append(ExceptionTestCase)
- if 'c' in tests: testcases.append(CompressTestCase)
- if 'o' in tests: testcases.append(CompressObjectTestCase)
- test_support.run_unittest(*testcases)
-
-if False:
- import sys
- sys.path.insert(1, '/Py23Src/python/dist/src/Lib/test')
- import test_zlib as tz
- ts, ut = tz.test_support, tz.unittest
- su = ut.TestSuite()
- su.addTest(ut.makeSuite(tz.CompressTestCase))
- ts.run_suite(su)
diff --git a/Lib/test/testtar.tar b/Lib/test/testtar.tar
index 1f4493f..c4c82b8 100644
--- a/Lib/test/testtar.tar
+++ b/Lib/test/testtar.tar
Binary files differ
diff --git a/Lib/test/warning_tests.py b/Lib/test/warning_tests.py
new file mode 100644
index 0000000..d0519ef
--- /dev/null
+++ b/Lib/test/warning_tests.py
@@ -0,0 +1,9 @@
+# Helper module for testing the skipmodules argument of warnings.warn()
+
+import warnings
+
+def outer(message, stacklevel=1):
+ inner(message, stacklevel)
+
+def inner(message, stacklevel=1):
+ warnings.warn(message, stacklevel=stacklevel)