diff options
Diffstat (limited to 'Lib/test')
-rwxr-xr-x | Lib/test/regrtest.py | 133 | ||||
-rw-r--r-- | Lib/test/test_bsddb3.py | 2 | ||||
-rw-r--r-- | Lib/test/test_builtin.py | 2 | ||||
-rw-r--r-- | Lib/test/test_class.py | 34 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 15 | ||||
-rw-r--r-- | Lib/test/test_doctest.py | 57 | ||||
-rw-r--r-- | Lib/test/test_exceptions.py | 49 | ||||
-rw-r--r-- | Lib/test/test_file.py | 655 | ||||
-rw-r--r-- | Lib/test/test_functools.py | 109 | ||||
-rw-r--r-- | Lib/test/test_generators.py | 6 | ||||
-rw-r--r-- | Lib/test/test_socket.py | 12 | ||||
-rw-r--r-- | Lib/test/test_struct.py | 67 | ||||
-rw-r--r-- | Lib/test/test_tempfile.py | 2 |
13 files changed, 627 insertions, 516 deletions
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 314e7e1..ca4a3b5 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -503,6 +503,7 @@ def runtest(test, generate, verbose, quiet, testdir=None, huntrleaks=False): quiet -- if true, don't print 'skipped' messages (probably redundant) testdir -- test directory """ + test_support.unload(test) if not testdir: testdir = findtestdir() @@ -512,11 +513,7 @@ def runtest(test, generate, verbose, quiet, testdir=None, huntrleaks=False): cfp = None else: cfp = cStringIO.StringIO() - if huntrleaks: - if not hasattr(sys, 'gettotalrefcount'): - raise Exception("Tracking reference leaks requires a debug build " - "of Python") - refrep = open(huntrleaks[2], "a") + try: save_stdout = sys.stdout try: @@ -538,60 +535,7 @@ def runtest(test, generate, verbose, quiet, testdir=None, huntrleaks=False): if indirect_test is not None: indirect_test() if huntrleaks: - # This code *is* hackish and inelegant, yes. - # But it seems to do the job. - import copy_reg - fs = warnings.filters[:] - ps = copy_reg.dispatch_table.copy() - pic = sys.path_importer_cache.copy() - import gc - def cleanup(): - import _strptime, linecache, warnings, dircache - import urlparse, urllib, urllib2, mimetypes, doctest - import struct - from distutils.dir_util import _path_created - _path_created.clear() - warnings.filters[:] = fs - gc.collect() - re.purge() - _strptime._regex_cache.clear() - urlparse.clear_cache() - urllib.urlcleanup() - urllib2.install_opener(None) - copy_reg.dispatch_table.clear() - copy_reg.dispatch_table.update(ps) - sys.path_importer_cache.clear() - sys.path_importer_cache.update(pic) - dircache.reset() - linecache.clearcache() - mimetypes._default_mime_types() - struct._cache.clear() - doctest.master = None - if indirect_test: - def run_the_test(): - indirect_test() - else: - def run_the_test(): - reload(the_module) - deltas = [] - repcount = huntrleaks[0] + huntrleaks[1] - print >> sys.stderr, "beginning", repcount, "repetitions" - print >> sys.stderr, \ - ("1234567890"*(repcount//10 + 1))[:repcount] - cleanup() - for i in range(repcount): - rc = sys.gettotalrefcount() - run_the_test() - sys.stderr.write('.') - cleanup() - deltas.append(sys.gettotalrefcount() - rc - 2) - print >>sys.stderr - if max(map(abs, deltas[-huntrleaks[1]:])) > 0: - print >>sys.stderr, test, 'leaked', \ - deltas[-huntrleaks[1]:], 'references' - print >>refrep, test, 'leaked', \ - deltas[-huntrleaks[1]:], 'references' - # The end of the huntrleaks hackishness. + dash_R(the_module, test, indirect_test, huntrleaks) finally: sys.stdout = save_stdout except test_support.ResourceDenied, msg: @@ -651,6 +595,77 @@ def runtest(test, generate, verbose, quiet, testdir=None, huntrleaks=False): sys.stdout.flush() return 0 +def dash_R(the_module, test, indirect_test, huntrleaks): + # This code is hackish and inelegant, but it seems to do the job. + import copy_reg + + if not hasattr(sys, 'gettotalrefcount'): + raise Exception("Tracking reference leaks requires a debug build " + "of Python") + + # Save current values for dash_R_cleanup() to restore. + fs = warnings.filters[:] + ps = copy_reg.dispatch_table.copy() + pic = sys.path_importer_cache.copy() + + if indirect_test: + def run_the_test(): + indirect_test() + else: + def run_the_test(): + reload(the_module) + + deltas = [] + nwarmup, ntracked, fname = huntrleaks + repcount = nwarmup + ntracked + print >> sys.stderr, "beginning", repcount, "repetitions" + print >> sys.stderr, ("1234567890"*(repcount//10 + 1))[:repcount] + dash_R_cleanup(fs, ps, pic) + for i in range(repcount): + rc = sys.gettotalrefcount() + run_the_test() + sys.stderr.write('.') + dash_R_cleanup(fs, ps, pic) + if i >= nwarmup: + deltas.append(sys.gettotalrefcount() - rc - 2) + print >> sys.stderr + if any(deltas): + print >> sys.stderr, test, 'leaked', deltas, 'references' + refrep = open(fname, "a") + print >> refrep, test, 'leaked', deltas, 'references' + refrep.close() + +def dash_R_cleanup(fs, ps, pic): + import gc, copy_reg + import _strptime, linecache, warnings, dircache + import urlparse, urllib, urllib2, mimetypes, doctest + import struct, filecmp + from distutils.dir_util import _path_created + + # Restore some original values. + warnings.filters[:] = fs + copy_reg.dispatch_table.clear() + copy_reg.dispatch_table.update(ps) + sys.path_importer_cache.clear() + sys.path_importer_cache.update(pic) + + # Clear assorted module caches. + _path_created.clear() + re.purge() + _strptime._regex_cache.clear() + urlparse.clear_cache() + urllib.urlcleanup() + urllib2.install_opener(None) + dircache.reset() + linecache.clearcache() + mimetypes._default_mime_types() + struct._cache.clear() + filecmp._cache.clear() + doctest.master = None + + # Collect cyclic trash. + gc.collect() + def reportdiff(expected, output): import difflib print "*" * 70 diff --git a/Lib/test/test_bsddb3.py b/Lib/test/test_bsddb3.py index 2d1bff7..8b0c50c 100644 --- a/Lib/test/test_bsddb3.py +++ b/Lib/test/test_bsddb3.py @@ -44,6 +44,8 @@ def suite(): 'test_queue', 'test_recno', 'test_thread', + 'test_sequence', + 'test_cursor_pget_bug', ] alltests = unittest.TestSuite() diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 71e2b0a..e6e4440 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -336,7 +336,7 @@ class BuiltinTest(unittest.TestCase): _cells = {} def __setitem__(self, key, formula): self._cells[key] = formula - def __getitem__(self, key ): + def __getitem__(self, key): return eval(self._cells[key], globals(), self) ss = SpreadSheet() diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 601b8b4..d872357 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -363,3 +363,37 @@ except AttributeError, x: pass else: print "attribute error for I.__init__ got masked" + + +# Test comparison and hash of methods +class A: + def __init__(self, x): + self.x = x + def f(self): + pass + def g(self): + pass + def __eq__(self, other): + return self.x == other.x + def __hash__(self): + return self.x +class B(A): + pass + +a1 = A(1) +a2 = A(2) +assert a1.f == a1.f +assert a1.f != a2.f +assert a1.f != a1.g +assert a1.f == A(1).f +assert hash(a1.f) == hash(a1.f) +assert hash(a1.f) == hash(A(1).f) + +assert A.f != a1.f +assert A.f != A.g +assert B.f == A.f +assert hash(B.f) == hash(A.f) + +# the following triggers a SystemError in 2.4 +a = A(hash(A.f.im_func)^(-1)) +hash(a.f) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 89cebb0..8ee431b 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3866,11 +3866,24 @@ def methodwrapper(): l = [] vereq(l.__add__, l.__add__) - verify(l.__add__ != [].__add__) + vereq(l.__add__, [].__add__) + verify(l.__add__ != [5].__add__) + verify(l.__add__ != l.__mul__) verify(l.__add__.__name__ == '__add__') verify(l.__add__.__self__ is l) verify(l.__add__.__objclass__ is list) vereq(l.__add__.__doc__, list.__add__.__doc__) + try: + hash(l.__add__) + except TypeError: + pass + else: + raise TestFailed("no TypeError from hash([].__add__)") + + t = () + t += (7,) + vereq(t.__add__, (7,).__add__) + vereq(hash(t.__add__), hash((7,).__add__)) def notimplemented(): # all binary methods should be able to return a NotImplemented diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 92d2d74..01f7acd 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -512,15 +512,11 @@ will only be generated for it once: >>> tests[1].name.split('.')[-1] in ['f', 'g'] True -Filter Functions -~~~~~~~~~~~~~~~~ -A filter function can be used to restrict which objects get examined, -but this is temporary, undocumented internal support for testmod's -deprecated isprivate gimmick. - - >>> def namefilter(prefix, base): - ... return base.startswith('a_') - >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass) +Empty Tests +~~~~~~~~~~~ +By default, an object with no doctests doesn't create any tests: + + >>> tests = doctest.DocTestFinder().find(SampleClass) >>> tests.sort() >>> for t in tests: ... print '%2s %s' % (len(t.examples), t.name) @@ -528,6 +524,9 @@ deprecated isprivate gimmick. 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ 1 SampleClass.__init__ + 2 SampleClass.a_classmethod + 1 SampleClass.a_property + 1 SampleClass.a_staticmethod 1 SampleClass.double 1 SampleClass.get @@ -536,8 +535,7 @@ tells it to include (empty) tests for objects with no doctests. This feature is really to support backward compatibility in what doctest.master.summarize() displays. - >>> tests = doctest.DocTestFinder(_namefilter=namefilter, - ... exclude_empty=False).find(SampleClass) + >>> tests = doctest.DocTestFinder(exclude_empty=False).find(SampleClass) >>> tests.sort() >>> for t in tests: ... print '%2s %s' % (len(t.examples), t.name) @@ -547,35 +545,12 @@ displays. 0 SampleClass.NestedClass.get 0 SampleClass.NestedClass.square 1 SampleClass.__init__ - 1 SampleClass.double - 1 SampleClass.get - -If a given object is filtered out, then none of the objects that it -contains will be added either: - - >>> def namefilter(prefix, base): - ... return base == 'NestedClass' - >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass) - >>> tests.sort() - >>> for t in tests: - ... print '%2s %s' % (len(t.examples), t.name) - 3 SampleClass - 1 SampleClass.__init__ 2 SampleClass.a_classmethod 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double 1 SampleClass.get -The filter function apply to contained objects, and *not* to the -object explicitly passed to DocTestFinder: - - >>> def namefilter(prefix, base): - ... return base == 'SampleClass' - >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass) - >>> len(tests) - 9 - Turning off Recursion ~~~~~~~~~~~~~~~~~~~~~ DocTestFinder can be told not to look for tests in contained objects @@ -1913,20 +1888,6 @@ def test_DocTestSuite(): modified the test globals, which are a copy of the sample_doctest module dictionary. The test globals are automatically cleared for us after a test. - - Finally, you can provide an alternate test finder. Here we'll - use a custom test_finder to to run just the test named bar. - However, the test in the module docstring, and the two tests - in the module __test__ dict, aren't filtered, so we actually - run three tests besides bar's. The filtering mechanisms are - poorly conceived, and will go away someday. - - >>> finder = doctest.DocTestFinder( - ... _namefilter=lambda prefix, base: base!='bar') - >>> suite = doctest.DocTestSuite('test.sample_doctest', - ... test_finder=finder) - >>> suite.run(unittest.TestResult()) - <unittest.TestResult run=4 errors=0 failures=1> """ def test_DocFileSuite(): diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index ebab913..ebe60c1 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1,9 +1,12 @@ # Python test set -- part 5, built-in exceptions -from test.test_support import TESTFN, unlink, run_unittest -import warnings -import sys, traceback, os +import os +import sys import unittest +import warnings +import pickle, cPickle + +from test.test_support import TESTFN, unlink, run_unittest # XXX This is not really enough, each *operation* should be tested! @@ -191,11 +194,15 @@ class ExceptionTests(unittest.TestCase): def testAttributes(self): # test that exception attributes are happy - try: str(u'Hello \u00E1') - except Exception, e: sampleUnicodeEncodeError = e + try: + str(u'Hello \u00E1') + except Exception, e: + sampleUnicodeEncodeError = e - try: unicode('\xff') - except Exception, e: sampleUnicodeDecodeError = e + try: + unicode('\xff') + except Exception, e: + sampleUnicodeDecodeError = e exceptionList = [ (BaseException, (), {'message' : '', 'args' : ()}), @@ -260,19 +267,20 @@ class ExceptionTests(unittest.TestCase): 'strerror' : 'strErrorStr', 'winerror' : 1, 'errno' : 22, 'filename' : 'filenameStr'}) ) - except NameError: pass - - import pickle, random + except NameError: + pass for args in exceptionList: expected = args[-1] try: exc = args[0] - if len(args) == 2: raise exc - else: raise exc(*args[1]) + if len(args) == 2: + raise exc + else: + raise exc(*args[1]) except BaseException, e: if (e is not exc and # needed for sampleUnicode errors - type(e) is not exc): + type(e) is not exc): raise # Verify no ref leaks in Exc_str() s = str(e) @@ -283,12 +291,15 @@ class ExceptionTests(unittest.TestCase): (repr(e), checkArgName)) # test for pickling support - new = pickle.loads(pickle.dumps(e, random.randint(0, 2))) - for checkArgName in expected: - self.assertEquals(repr(getattr(e, checkArgName)), - repr(expected[checkArgName]), - 'pickled exception "%s", attribute "%s' % - (repr(e), checkArgName)) + for p in pickle, cPickle: + for protocol in range(p.HIGHEST_PROTOCOL + 1): + new = p.loads(p.dumps(e, protocol)) + for checkArgName in expected: + got = repr(getattr(new, checkArgName)) + want = repr(expected[checkArgName]) + self.assertEquals(got, want, + 'pickled "%r", attribute "%s' % + (e, checkArgName)) def testKeywordArgs(self): # test that builtin exception don't take keyword args, diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index ca1c6ba..dcfa265 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -1,356 +1,325 @@ import sys import os +import unittest from array import array from weakref import proxy -from test.test_support import verify, TESTFN, TestFailed, findfile +from test.test_support import TESTFN, findfile, run_unittest from UserList import UserList -# verify weak references -f = file(TESTFN, 'w') -p = proxy(f) -p.write('teststring') -verify(f.tell(), p.tell()) -f.close() -f = None -try: - p.tell() -except ReferenceError: - pass -else: - raise TestFailed('file proxy still exists when the file is gone') - -# verify expected attributes exist -f = file(TESTFN, 'w') -softspace = f.softspace -f.name # merely shouldn't blow up -f.mode # ditto -f.closed # ditto - -# verify softspace is writable -f.softspace = softspace # merely shouldn't blow up - -# verify the others aren't -for attr in 'name', 'mode', 'closed': - try: - setattr(f, attr, 'oops') - except (AttributeError, TypeError): - pass - else: - raise TestFailed('expected exception setting file attr %r' % attr) -f.close() - -# check invalid mode strings -for mode in ("", "aU", "wU+"): - try: - f = file(TESTFN, mode) - except ValueError: - pass - else: - f.close() - raise TestFailed('%r is an invalid file mode' % mode) - -# verify writelines with instance sequence -l = UserList(['1', '2']) -f = open(TESTFN, 'wb') -f.writelines(l) -f.close() -f = open(TESTFN, 'rb') -buf = f.read() -f.close() -verify(buf == '12') - -# verify readinto -a = array('c', 'x'*10) -f = open(TESTFN, 'rb') -n = f.readinto(a) -f.close() -verify(buf == a.tostring()[:n]) - -# verify readinto refuses text files -a = array('c', 'x'*10) -f = open(TESTFN, 'r') -try: - f.readinto(a) - raise TestFailed("readinto shouldn't work in text mode") -except TypeError: - pass -finally: - f.close() - -# verify writelines with integers -f = open(TESTFN, 'wb') -try: - f.writelines([1, 2, 3]) -except TypeError: - pass -else: - print "writelines accepted sequence of integers" -f.close() - -# verify writelines with integers in UserList -f = open(TESTFN, 'wb') -l = UserList([1,2,3]) -try: - f.writelines(l) -except TypeError: - pass -else: - print "writelines accepted sequence of integers" -f.close() - -# verify writelines with non-string object -class NonString: pass - -f = open(TESTFN, 'wb') -try: - f.writelines([NonString(), NonString()]) -except TypeError: - pass -else: - print "writelines accepted sequence of non-string objects" -f.close() - -# This causes the interpreter to exit on OSF1 v5.1. -if sys.platform != 'osf1V5': - try: - sys.stdin.seek(-1) - except IOError: - pass - else: - print "should not be able to seek on sys.stdin" -else: - print >>sys.__stdout__, ( - ' Skipping sys.stdin.seek(-1), it may crash the interpreter.' - ' Test manually.') - -try: - sys.stdin.truncate() -except IOError: - pass -else: - print "should not be able to truncate on sys.stdin" - -# verify repr works -f = open(TESTFN) -if not repr(f).startswith("<open file '" + TESTFN): - print "repr(file) failed" -f.close() - -# verify repr works for unicode too -f = open(unicode(TESTFN)) -if not repr(f).startswith("<open file u'" + TESTFN): - print "repr(file with unicode name) failed" -f.close() - -# verify that we get a sensible error message for bad mode argument -bad_mode = "qwerty" -try: - open(TESTFN, bad_mode) -except ValueError, msg: - if msg[0] != 0: - s = str(msg) - if s.find(TESTFN) != -1 or s.find(bad_mode) == -1: - print "bad error message for invalid mode: %s" % s - # if msg[0] == 0, we're probably on Windows where there may be - # no obvious way to discover why open() failed. -else: - print "no error for invalid mode: %s" % bad_mode - -f = open(TESTFN) -if f.name != TESTFN: - raise TestFailed, 'file.name should be "%s"' % TESTFN -if f.isatty(): - raise TestFailed, 'file.isatty() should be false' - -if f.closed: - raise TestFailed, 'file.closed should be false' - -try: - f.readinto("") -except TypeError: - pass -else: - raise TestFailed, 'file.readinto("") should raise a TypeError' - -f.close() -if not f.closed: - raise TestFailed, 'file.closed should be true' - -# make sure that explicitly setting the buffer size doesn't cause -# misbehaviour especially with repeated close() calls -for s in (-1, 0, 1, 512): - try: - f = open(TESTFN, 'w', s) - f.write(str(s)) - f.close() - f.close() - f = open(TESTFN, 'r', s) - d = int(f.read()) - f.close() - f.close() - except IOError, msg: - raise TestFailed, 'error setting buffer size %d: %s' % (s, str(msg)) - if d != s: - raise TestFailed, 'readback failure using buffer size %d' - -methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto', - 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', - '__iter__'] -if sys.platform.startswith('atheos'): - methods.remove('truncate') - -for methodname in methods: - method = getattr(f, methodname) - try: - method() - except ValueError: - pass - else: - raise TestFailed, 'file.%s() on a closed file should raise a ValueError' % methodname - -try: - f.writelines([]) -except ValueError: - pass -else: - raise TestFailed, 'file.writelines([]) on a closed file should raise a ValueError' - -os.unlink(TESTFN) - -def bug801631(): - # SF bug <http://www.python.org/sf/801631> - # "file.truncate fault on windows" - f = file(TESTFN, 'wb') - f.write('12345678901') # 11 bytes - f.close() - - f = file(TESTFN,'rb+') - data = f.read(5) - if data != '12345': - raise TestFailed("Read on file opened for update failed %r" % data) - if f.tell() != 5: - raise TestFailed("File pos after read wrong %d" % f.tell()) - - f.truncate() - if f.tell() != 5: - raise TestFailed("File pos after ftruncate wrong %d" % f.tell()) - - f.close() - size = os.path.getsize(TESTFN) - if size != 5: - raise TestFailed("File size after ftruncate wrong %d" % size) - -try: - bug801631() -finally: - os.unlink(TESTFN) - -# Test the complex interaction when mixing file-iteration and the various -# read* methods. Ostensibly, the mixture could just be tested to work -# when it should work according to the Python language, instead of fail -# when it should fail according to the current CPython implementation. -# People don't always program Python the way they should, though, and the -# implemenation might change in subtle ways, so we explicitly test for -# errors, too; the test will just have to be updated when the -# implementation changes. -dataoffset = 16384 -filler = "ham\n" -assert not dataoffset % len(filler), \ - "dataoffset must be multiple of len(filler)" -nchunks = dataoffset // len(filler) -testlines = [ - "spam, spam and eggs\n", - "eggs, spam, ham and spam\n", - "saussages, spam, spam and eggs\n", - "spam, ham, spam and eggs\n", - "spam, spam, spam, spam, spam, ham, spam\n", - "wonderful spaaaaaam.\n" -] -methods = [("readline", ()), ("read", ()), ("readlines", ()), - ("readinto", (array("c", " "*100),))] - -try: - # Prepare the testfile - bag = open(TESTFN, "wb") - bag.write(filler * nchunks) - bag.writelines(testlines) - bag.close() - # Test for appropriate errors mixing read* and iteration - for methodname, args in methods: - f = open(TESTFN, 'rb') - if f.next() != filler: - raise TestFailed, "Broken testfile" - meth = getattr(f, methodname) +class AutoFileTests(unittest.TestCase): + # file tests for which a test file is automatically set up + + def setUp(self): + self.f = file(TESTFN, 'wb') + + def tearDown(self): try: - meth(*args) - except ValueError: + if self.f: + self.f.close() + except IOError: pass + + def testWeakRefs(self): + # verify weak references + p = proxy(self.f) + p.write('teststring') + self.assertEquals(self.f.tell(), p.tell()) + self.f.close() + self.f = None + self.assertRaises(ReferenceError, getattr, p, 'tell') + + def testAttributes(self): + # verify expected attributes exist + f = self.f + softspace = f.softspace + f.name # merely shouldn't blow up + f.mode # ditto + f.closed # ditto + + # verify softspace is writable + f.softspace = softspace # merely shouldn't blow up + + # verify the others aren't + for attr in 'name', 'mode', 'closed': + self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops') + + def testReadinto(self): + # verify readinto + self.f.write('12') + self.f.close() + a = array('c', 'x'*10) + self.f = open(TESTFN, 'rb') + n = self.f.readinto(a) + self.assertEquals('12', a.tostring()[:n]) + + def testReadinto_text(self): + # verify readinto refuses text files + a = array('c', 'x'*10) + self.f.close() + self.f = open(TESTFN, 'r') + self.assertRaises(TypeError, self.f.readinto, a) + + def testWritelinesUserList(self): + # verify writelines with instance sequence + l = UserList(['1', '2']) + self.f.writelines(l) + self.f.close() + self.f = open(TESTFN, 'rb') + buf = self.f.read() + self.assertEquals(buf, '12') + + def testWritelinesIntegers(self): + # verify writelines with integers + self.assertRaises(TypeError, self.f.writelines, [1, 2, 3]) + + def testWritelinesIntegersUserList(self): + # verify writelines with integers in UserList + l = UserList([1,2,3]) + self.assertRaises(TypeError, self.f.writelines, l) + + def testWritelinesNonString(self): + # verify writelines with non-string object + class NonString: pass + + self.assertRaises(TypeError, self.f.writelines, [NonString(), NonString()]) + + def testRepr(self): + # verify repr works + self.assert_(repr(self.f).startswith("<open file '" + TESTFN)) + + def testErrors(self): + f = self.f + self.assertEquals(f.name, TESTFN) + self.assert_(not f.isatty()) + self.assert_(not f.closed) + + self.assertRaises(TypeError, f.readinto, "") + f.close() + self.assert_(f.closed) + + def testMethods(self): + methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto', + 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', + '__iter__'] + if sys.platform.startswith('atheos'): + methods.remove('truncate') + + self.f.close() + + for methodname in methods: + method = getattr(self.f, methodname) + # should raise on closed file + self.assertRaises(ValueError, method) + self.assertRaises(ValueError, self.f.writelines, []) + + +class OtherFileTests(unittest.TestCase): + + def testModeStrings(self): + # check invalid mode strings + for mode in ("", "aU", "wU+"): + try: + f = file(TESTFN, mode) + except ValueError: + pass + else: + f.close() + self.fail('%r is an invalid file mode' % mode) + + def testStdin(self): + # This causes the interpreter to exit on OSF1 v5.1. + if sys.platform != 'osf1V5': + self.assertRaises(IOError, sys.stdin.seek, -1) else: - raise TestFailed("%s%r after next() didn't raise ValueError" % - (methodname, args)) + print >>sys.__stdout__, ( + ' Skipping sys.stdin.seek(-1), it may crash the interpreter.' + ' Test manually.') + self.assertRaises(IOError, sys.stdin.truncate) + + def testUnicodeOpen(self): + # verify repr works for unicode too + f = open(unicode(TESTFN), "w") + self.assert_(repr(f).startswith("<open file u'" + TESTFN)) f.close() - # Test to see if harmless (by accident) mixing of read* and iteration - # still works. This depends on the size of the internal iteration - # buffer (currently 8192,) but we can test it in a flexible manner. - # Each line in the bag o' ham is 4 bytes ("h", "a", "m", "\n"), so - # 4096 lines of that should get us exactly on the buffer boundary for - # any power-of-2 buffersize between 4 and 16384 (inclusive). - f = open(TESTFN, 'rb') - for i in range(nchunks): - f.next() - testline = testlines.pop(0) - try: - line = f.readline() - except ValueError: - raise TestFailed("readline() after next() with supposedly empty " - "iteration-buffer failed anyway") - if line != testline: - raise TestFailed("readline() after next() with empty buffer " - "failed. Got %r, expected %r" % (line, testline)) - testline = testlines.pop(0) - buf = array("c", "\x00" * len(testline)) - try: - f.readinto(buf) - except ValueError: - raise TestFailed("readinto() after next() with supposedly empty " - "iteration-buffer failed anyway") - line = buf.tostring() - if line != testline: - raise TestFailed("readinto() after next() with empty buffer " - "failed. Got %r, expected %r" % (line, testline)) - - testline = testlines.pop(0) - try: - line = f.read(len(testline)) - except ValueError: - raise TestFailed("read() after next() with supposedly empty " - "iteration-buffer failed anyway") - if line != testline: - raise TestFailed("read() after next() with empty buffer " - "failed. Got %r, expected %r" % (line, testline)) - try: - lines = f.readlines() - except ValueError: - raise TestFailed("readlines() after next() with supposedly empty " - "iteration-buffer failed anyway") - if lines != testlines: - raise TestFailed("readlines() after next() with empty buffer " - "failed. Got %r, expected %r" % (line, testline)) - # Reading after iteration hit EOF shouldn't hurt either - f = open(TESTFN, 'rb') - try: - for line in f: - pass + def testBadModeArgument(self): + # verify that we get a sensible error message for bad mode argument + bad_mode = "qwerty" try: - f.readline() - f.readinto(buf) - f.read() - f.readlines() - except ValueError: - raise TestFailed("read* failed after next() consumed file") - finally: - f.close() -finally: - os.unlink(TESTFN) + f = open(TESTFN, bad_mode) + except ValueError, msg: + if msg[0] != 0: + s = str(msg) + if s.find(TESTFN) != -1 or s.find(bad_mode) == -1: + self.fail("bad error message for invalid mode: %s" % s) + # if msg[0] == 0, we're probably on Windows where there may be + # no obvious way to discover why open() failed. + else: + f.close() + self.fail("no error for invalid mode: %s" % bad_mode) + + def testSetBufferSize(self): + # make sure that explicitly setting the buffer size doesn't cause + # misbehaviour especially with repeated close() calls + for s in (-1, 0, 1, 512): + try: + f = open(TESTFN, 'w', s) + f.write(str(s)) + f.close() + f.close() + f = open(TESTFN, 'r', s) + d = int(f.read()) + f.close() + f.close() + except IOError, msg: + self.fail('error setting buffer size %d: %s' % (s, str(msg))) + self.assertEquals(d, s) + + def testTruncateOnWindows(self): + os.unlink(TESTFN) + + def bug801631(): + # SF bug <http://www.python.org/sf/801631> + # "file.truncate fault on windows" + f = file(TESTFN, 'wb') + f.write('12345678901') # 11 bytes + f.close() + + f = file(TESTFN,'rb+') + data = f.read(5) + if data != '12345': + self.fail("Read on file opened for update failed %r" % data) + if f.tell() != 5: + self.fail("File pos after read wrong %d" % f.tell()) + + f.truncate() + if f.tell() != 5: + self.fail("File pos after ftruncate wrong %d" % f.tell()) + + f.close() + size = os.path.getsize(TESTFN) + if size != 5: + self.fail("File size after ftruncate wrong %d" % size) + + try: + bug801631() + finally: + os.unlink(TESTFN) + + def testIteration(self): + # Test the complex interaction when mixing file-iteration and the various + # read* methods. Ostensibly, the mixture could just be tested to work + # when it should work according to the Python language, instead of fail + # when it should fail according to the current CPython implementation. + # People don't always program Python the way they should, though, and the + # implemenation might change in subtle ways, so we explicitly test for + # errors, too; the test will just have to be updated when the + # implementation changes. + dataoffset = 16384 + filler = "ham\n" + assert not dataoffset % len(filler), \ + "dataoffset must be multiple of len(filler)" + nchunks = dataoffset // len(filler) + testlines = [ + "spam, spam and eggs\n", + "eggs, spam, ham and spam\n", + "saussages, spam, spam and eggs\n", + "spam, ham, spam and eggs\n", + "spam, spam, spam, spam, spam, ham, spam\n", + "wonderful spaaaaaam.\n" + ] + methods = [("readline", ()), ("read", ()), ("readlines", ()), + ("readinto", (array("c", " "*100),))] + + try: + # Prepare the testfile + bag = open(TESTFN, "wb") + bag.write(filler * nchunks) + bag.writelines(testlines) + bag.close() + # Test for appropriate errors mixing read* and iteration + for methodname, args in methods: + f = open(TESTFN, 'rb') + if f.next() != filler: + self.fail, "Broken testfile" + meth = getattr(f, methodname) + try: + meth(*args) + except ValueError: + pass + else: + self.fail("%s%r after next() didn't raise ValueError" % + (methodname, args)) + f.close() + + # Test to see if harmless (by accident) mixing of read* and iteration + # still works. This depends on the size of the internal iteration + # buffer (currently 8192,) but we can test it in a flexible manner. + # Each line in the bag o' ham is 4 bytes ("h", "a", "m", "\n"), so + # 4096 lines of that should get us exactly on the buffer boundary for + # any power-of-2 buffersize between 4 and 16384 (inclusive). + f = open(TESTFN, 'rb') + for i in range(nchunks): + f.next() + testline = testlines.pop(0) + try: + line = f.readline() + except ValueError: + self.fail("readline() after next() with supposedly empty " + "iteration-buffer failed anyway") + if line != testline: + self.fail("readline() after next() with empty buffer " + "failed. Got %r, expected %r" % (line, testline)) + testline = testlines.pop(0) + buf = array("c", "\x00" * len(testline)) + try: + f.readinto(buf) + except ValueError: + self.fail("readinto() after next() with supposedly empty " + "iteration-buffer failed anyway") + line = buf.tostring() + if line != testline: + self.fail("readinto() after next() with empty buffer " + "failed. Got %r, expected %r" % (line, testline)) + + testline = testlines.pop(0) + try: + line = f.read(len(testline)) + except ValueError: + self.fail("read() after next() with supposedly empty " + "iteration-buffer failed anyway") + if line != testline: + self.fail("read() after next() with empty buffer " + "failed. Got %r, expected %r" % (line, testline)) + try: + lines = f.readlines() + except ValueError: + self.fail("readlines() after next() with supposedly empty " + "iteration-buffer failed anyway") + if lines != testlines: + self.fail("readlines() after next() with empty buffer " + "failed. Got %r, expected %r" % (line, testline)) + # Reading after iteration hit EOF shouldn't hurt either + f = open(TESTFN, 'rb') + try: + for line in f: + pass + try: + f.readline() + f.readinto(buf) + f.read() + f.readlines() + except ValueError: + self.fail("read* failed after next() consumed file") + finally: + f.close() + finally: + os.unlink(TESTFN) + + +def test_main(): + run_unittest(AutoFileTests, OtherFileTests) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 609e8f4..8dc185b 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -152,6 +152,113 @@ class TestPythonPartial(TestPartial): thetype = PythonPartial +class TestUpdateWrapper(unittest.TestCase): + + def check_wrapper(self, wrapper, wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + # Check attributes were assigned + for name in assigned: + self.failUnless(getattr(wrapper, name) is getattr(wrapped, name)) + # Check attributes were updated + for name in updated: + wrapper_attr = getattr(wrapper, name) + wrapped_attr = getattr(wrapped, name) + for key in wrapped_attr: + self.failUnless(wrapped_attr[key] is wrapper_attr[key]) + + def test_default_update(self): + def f(): + """This is a test""" + pass + f.attr = 'This is also a test' + def wrapper(): + pass + functools.update_wrapper(wrapper, f) + self.check_wrapper(wrapper, f) + self.assertEqual(wrapper.__name__, 'f') + self.assertEqual(wrapper.__doc__, 'This is a test') + self.assertEqual(wrapper.attr, 'This is also a test') + + def test_no_update(self): + def f(): + """This is a test""" + pass + f.attr = 'This is also a test' + def wrapper(): + pass + functools.update_wrapper(wrapper, f, (), ()) + self.check_wrapper(wrapper, f, (), ()) + self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__doc__, None) + self.failIf(hasattr(wrapper, 'attr')) + + def test_selective_update(self): + def f(): + pass + f.attr = 'This is a different test' + f.dict_attr = dict(a=1, b=2, c=3) + def wrapper(): + pass + wrapper.dict_attr = {} + assign = ('attr',) + update = ('dict_attr',) + functools.update_wrapper(wrapper, f, assign, update) + self.check_wrapper(wrapper, f, assign, update) + self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__doc__, None) + self.assertEqual(wrapper.attr, 'This is a different test') + self.assertEqual(wrapper.dict_attr, f.dict_attr) + + +class TestWraps(TestUpdateWrapper): + + def test_default_update(self): + def f(): + """This is a test""" + pass + f.attr = 'This is also a test' + @functools.wraps(f) + def wrapper(): + pass + self.check_wrapper(wrapper, f) + self.assertEqual(wrapper.__name__, 'f') + self.assertEqual(wrapper.__doc__, 'This is a test') + self.assertEqual(wrapper.attr, 'This is also a test') + + def test_no_update(self): + def f(): + """This is a test""" + pass + f.attr = 'This is also a test' + @functools.wraps(f, (), ()) + def wrapper(): + pass + self.check_wrapper(wrapper, f, (), ()) + self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__doc__, None) + self.failIf(hasattr(wrapper, 'attr')) + + def test_selective_update(self): + def f(): + pass + f.attr = 'This is a different test' + f.dict_attr = dict(a=1, b=2, c=3) + def add_dict_attr(f): + f.dict_attr = {} + return f + assign = ('attr',) + update = ('dict_attr',) + @functools.wraps(f, assign, update) + @add_dict_attr + def wrapper(): + pass + self.check_wrapper(wrapper, f, assign, update) + self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__doc__, None) + self.assertEqual(wrapper.attr, 'This is a different test') + self.assertEqual(wrapper.dict_attr, f.dict_attr) + def test_main(verbose=None): @@ -160,6 +267,8 @@ def test_main(verbose=None): TestPartial, TestPartialSubclass, TestPythonPartial, + TestUpdateWrapper, + TestWraps ) test_support.run_unittest(*test_classes) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index a60a768..a184a8b 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -733,7 +733,7 @@ syntax_tests = """ ... yield 1 Traceback (most recent call last): .. -SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2) +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3) >>> def f(): ... yield 1 @@ -876,9 +876,9 @@ These are fine: ... if 0: ... return 3 # but *this* sucks (line 8) ... if 0: -... yield 2 # because it's a generator +... yield 2 # because it's a generator (line 10) Traceback (most recent call last): -SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 8) +SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 10) This one caused a crash (see SF bug 567538): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 2246fb6..01b9b5b 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -860,25 +860,25 @@ class BufferIOTest(SocketConnectedTest): def __init__(self, methodName='runTest'): SocketConnectedTest.__init__(self, methodName=methodName) - def testRecvBuf(self): + def testRecvInto(self): buf = array.array('c', ' '*1024) - nbytes = self.cli_conn.recv_buf(buf) + nbytes = self.cli_conn.recv_into(buf) self.assertEqual(nbytes, len(MSG)) msg = buf.tostring()[:len(MSG)] self.assertEqual(msg, MSG) - def _testRecvBuf(self): + def _testRecvInto(self): buf = buffer(MSG) self.serv_conn.send(buf) - def testRecvFromBuf(self): + def testRecvFromInto(self): buf = array.array('c', ' '*1024) - nbytes, addr = self.cli_conn.recvfrom_buf(buf) + nbytes, addr = self.cli_conn.recvfrom_into(buf) self.assertEqual(nbytes, len(MSG)) msg = buf.tostring()[:len(MSG)] self.assertEqual(msg, MSG) - def _testRecvFromBuf(self): + def _testRecvFromInto(self): buf = buffer(MSG) self.serv_conn.send(buf) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index af835f7..aa458e6 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -1,4 +1,4 @@ -from test.test_support import TestFailed, verbose, verify +from test.test_support import TestFailed, verbose, verify, vereq import test.test_support import struct import array @@ -16,13 +16,11 @@ except ImportError: PY_STRUCT_RANGE_CHECKING = 0 PY_STRUCT_OVERFLOW_MASKING = 1 else: - PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0) - PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0) + PY_STRUCT_RANGE_CHECKING = _struct._PY_STRUCT_RANGE_CHECKING + PY_STRUCT_OVERFLOW_MASKING = _struct._PY_STRUCT_OVERFLOW_MASKING def string_reverse(s): - chars = list(s) - chars.reverse() - return "".join(chars) + return "".join(reversed(s)) def bigendian_to_native(value): if ISBIGENDIAN: @@ -504,7 +502,7 @@ def assertRaises(excClass, callableObj, *args, **kwargs): except excClass: return else: - raise RuntimeError("%s not raised." % excClass) + raise TestFailed("%s not raised." % excClass) def test_unpack_from(): test_string = 'abcd01234' @@ -512,68 +510,67 @@ def test_unpack_from(): s = struct.Struct(fmt) for cls in (str, buffer): data = cls(test_string) - assert s.unpack_from(data) == ('abcd',) - assert s.unpack_from(data, 2) == ('cd01',) - assert s.unpack_from(data, 4) == ('0123',) + vereq(s.unpack_from(data), ('abcd',)) + vereq(s.unpack_from(data, 2), ('cd01',)) + vereq(s.unpack_from(data, 4), ('0123',)) for i in xrange(6): - assert s.unpack_from(data, i) == (data[i:i+4],) + vereq(s.unpack_from(data, i), (data[i:i+4],)) for i in xrange(6, len(test_string) + 1): simple_err(s.unpack_from, data, i) for cls in (str, buffer): data = cls(test_string) - assert struct.unpack_from(fmt, data) == ('abcd',) - assert struct.unpack_from(fmt, data, 2) == ('cd01',) - assert struct.unpack_from(fmt, data, 4) == ('0123',) + vereq(struct.unpack_from(fmt, data), ('abcd',)) + vereq(struct.unpack_from(fmt, data, 2), ('cd01',)) + vereq(struct.unpack_from(fmt, data, 4), ('0123',)) for i in xrange(6): - assert (struct.unpack_from(fmt, data, i) == (data[i:i+4],)) + vereq(struct.unpack_from(fmt, data, i), (data[i:i+4],)) for i in xrange(6, len(test_string) + 1): simple_err(struct.unpack_from, fmt, data, i) -def test_pack_to(): +def test_pack_into(): test_string = 'Reykjavik rocks, eow!' writable_buf = array.array('c', ' '*100) fmt = '21s' s = struct.Struct(fmt) # Test without offset - s.pack_to(writable_buf, 0, test_string) + s.pack_into(writable_buf, 0, test_string) from_buf = writable_buf.tostring()[:len(test_string)] - assert from_buf == test_string + vereq(from_buf, test_string) # Test with offset. - s.pack_to(writable_buf, 10, test_string) + s.pack_into(writable_buf, 10, test_string) from_buf = writable_buf.tostring()[:len(test_string)+10] - assert from_buf == (test_string[:10] + test_string) + vereq(from_buf, test_string[:10] + test_string) # Go beyond boundaries. small_buf = array.array('c', ' '*10) - assertRaises(struct.error, s.pack_to, small_buf, 0, test_string) - assertRaises(struct.error, s.pack_to, small_buf, 2, test_string) + assertRaises(struct.error, s.pack_into, small_buf, 0, test_string) + assertRaises(struct.error, s.pack_into, small_buf, 2, test_string) -def test_pack_to_fn(): +def test_pack_into_fn(): test_string = 'Reykjavik rocks, eow!' writable_buf = array.array('c', ' '*100) fmt = '21s' - pack_to = lambda *args: struct.pack_to(fmt, *args) + pack_into = lambda *args: struct.pack_into(fmt, *args) - # Test without offset - pack_to(writable_buf, 0, test_string) + # Test without offset. + pack_into(writable_buf, 0, test_string) from_buf = writable_buf.tostring()[:len(test_string)] - assert from_buf == test_string + vereq(from_buf, test_string) # Test with offset. - pack_to(writable_buf, 10, test_string) + pack_into(writable_buf, 10, test_string) from_buf = writable_buf.tostring()[:len(test_string)+10] - assert from_buf == (test_string[:10] + test_string) + vereq(from_buf, test_string[:10] + test_string) # Go beyond boundaries. small_buf = array.array('c', ' '*10) - assertRaises(struct.error, pack_to, small_buf, 0, test_string) - assertRaises(struct.error, pack_to, small_buf, 2, test_string) + assertRaises(struct.error, pack_into, small_buf, 0, test_string) + assertRaises(struct.error, pack_into, small_buf, 2, test_string) + - # Test methods to pack and unpack from buffers rather than strings. test_unpack_from() -test_pack_to() -test_pack_to_fn() - +test_pack_into() +test_pack_into_fn() diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index e274c5b..aeaa77e 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -390,7 +390,7 @@ test_classes.append(test_gettempdir) class test_mkstemp(TC): """Test mkstemp().""" - def do_create(self, dir=None, pre="", suf="", ): + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir() try: |