cpython: efade142ef01 (original) (raw)
--- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -23,6 +23,9 @@ import time import sysconfig import fnmatch import logging.handlers +import struct +import tempfile +import _testcapi try: import _thread, threading @@ -984,6 +987,31 @@ def python_is_optimized(): return final_opt and final_opt != '-O0' +_header = '2P' +if hasattr(sys, "gettotalrefcount"):
+_vheader = _header + 'P' + +def calcobjsize(fmt):
+ + +_TPFLAGS_HAVE_GC = 1<<14 +_TPFLAGS_HEAPTYPE = 1<<9 + +def check_sizeof(test, o, size):
- result = sys.getsizeof(o)
add GC header size
- if ((type(o) == type) and (o.flags & _TPFLAGS_HEAPTYPE) or[](#l1.35)
((type(o) != type) and (type(o).__flags__ & _TPFLAGS_HAVE_GC))):[](#l1.36)
size += _testcapi.SIZEOF_PYGC_HEAD[](#l1.37)
- msg = 'wrong size for %s: got %d, expected %d' [](#l1.38)
% (type(o), result, size)[](#l1.39)
- test.assertEqual(result, size, msg)
+ #=======================================================================
Decorator for running a function in a different locale, correctly resetting
it afterwards.
--- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -3,7 +3,7 @@ import unittest import struct import sys -from test.support import run_unittest, cpython_only +from test import support ISBIGENDIAN = sys.byteorder == "big" IS32BIT = sys.maxsize == 0x7fffffff @@ -30,32 +30,6 @@ def bigendian_to_native(value): return string_reverse(value) class StructTest(unittest.TestCase):
- def setUp(self):
# due to missing size_t information from struct, it is assumed that[](#l2.17)
# sizeof(Py_ssize_t) = sizeof(void*)[](#l2.18)
self.header = 'PP'[](#l2.19)
if hasattr(sys, "gettotalrefcount"):[](#l2.20)
self.header += '2P'[](#l2.21)
- def check_sizeof(self, format_str, number_of_codes):
def size(fmt):[](#l2.24)
"""Wrapper around struct.calcsize which enforces the alignment[](#l2.25)
of the end of a structure to the alignment requirement of pointer.[](#l2.26)
Note: This wrapper should only be used if a pointer member is[](#l2.28)
included and no member with a size larger than a pointer exists.[](#l2.29)
"""[](#l2.30)
return struct.calcsize(fmt + '0P')[](#l2.31)
struct_obj = struct.Struct(format_str)[](#l2.33)
# The size of 'PyStructObject'[](#l2.34)
totalsize = size(self.header + '5P')[](#l2.35)
# The size taken up by the 'formatcode' dynamic array[](#l2.36)
totalsize += size('3P') * (number_of_codes + 1)[](#l2.37)
result = sys.getsizeof(struct_obj)[](#l2.38)
msg = 'wrong size for %s: got %d, expected %d' \[](#l2.39)
% (type(struct_obj), result, totalsize)[](#l2.40)
self.assertEqual(result, totalsize, msg)[](#l2.41)
def test_isbigendian(self): self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN) @@ -583,7 +557,14 @@ class StructTest(unittest.TestCase): s = struct.Struct('i') s.init('ii')
- def check_sizeof(self, format_str, number_of_codes):
# The size of 'PyStructObject'[](#l2.51)
totalsize = support.calcobjsize('5P')[](#l2.52)
# The size taken up by the 'formatcode' dynamic array[](#l2.53)
totalsize += struct.calcsize('3P') * (number_of_codes + 1)[](#l2.54)
support.check_sizeof(self, struct.Struct(format_str), totalsize)[](#l2.55)
- @support.cpython_only def test__sizeof__(self): for code in integer_codes: self.check_sizeof(code, 1)
@@ -598,7 +579,7 @@ class StructTest(unittest.TestCase): self.check_sizeof('0c', 0) def test_main():
if name == 'main': test_main()
--- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -570,22 +570,8 @@ class SysModuleTest(unittest.TestCase): class SizeofTest(unittest.TestCase):
self.c = len(struct.pack('c', b' '))[](#l3.11)
self.H = len(struct.pack('H', 0))[](#l3.12)
self.i = len(struct.pack('i', 0))[](#l3.13)
self.l = len(struct.pack('l', 0))[](#l3.14)
self.P = len(struct.pack('P', 0))[](#l3.15)
# due to missing size_t information from struct, it is assumed that[](#l3.16)
# sizeof(Py_ssize_t) = sizeof(void*)[](#l3.17)
self.header = 'PP'[](#l3.18)
self.vheader = self.header + 'P'[](#l3.19)
if hasattr(sys, "gettotalrefcount"):[](#l3.20)
self.header += '2P'[](#l3.21)
self.vheader += '2P'[](#l3.22)
self.P = struct.calcsize('P')[](#l3.23) self.longdigit = sys.int_info.sizeof_digit[](#l3.24) import _testcapi[](#l3.25) self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD[](#l3.26)
@@ -595,123 +581,102 @@ class SizeofTest(unittest.TestCase): self.file.close() test.support.unlink(test.support.TESTFN)
- def check_sizeof(self, o, size):
result = sys.getsizeof(o)[](#l3.32)
# add GC header size[](#l3.33)
if ((type(o) == type) and (o.__flags__ & self.TPFLAGS_HEAPTYPE) or\[](#l3.34)
((type(o) != type) and (type(o).__flags__ & self.TPFLAGS_HAVE_GC))):[](#l3.35)
size += self.gc_headsize[](#l3.36)
msg = 'wrong size for %s: got %d, expected %d' \[](#l3.37)
% (type(o), result, size)[](#l3.38)
self.assertEqual(result, size, msg)[](#l3.39)
- def calcsize(self, fmt):
"""Wrapper around struct.calcsize which enforces the alignment of the[](#l3.42)
end of a structure to the alignment requirement of pointer.[](#l3.43)
Note: This wrapper should only be used if a pointer member is included[](#l3.45)
and no member with a size larger than a pointer exists.[](#l3.46)
"""[](#l3.47)
return struct.calcsize(fmt + '0P')[](#l3.48)
def test_gc_head_size(self): # Check that the gc header size is added to objects tracked by the gc.
h = self.header[](#l3.53)
vh = self.vheader[](#l3.54)
size = self.calcsize[](#l3.55)
vsize = test.support.calcvobjsize[](#l3.56) gc_header_size = self.gc_headsize[](#l3.57) # bool objects are not gc tracked[](#l3.58)
self.assertEqual(sys.getsizeof(True), size(vh) + self.longdigit)[](#l3.59)
self.assertEqual(sys.getsizeof(True), vsize('') + self.longdigit)[](#l3.60) # but lists are[](#l3.61)
self.assertEqual(sys.getsizeof([]), size(vh + 'PP') + gc_header_size)[](#l3.62)
self.assertEqual(sys.getsizeof([]), vsize('PP') + gc_header_size)[](#l3.63)
h = self.header[](#l3.66)
vh = self.vheader[](#l3.67)
size = self.calcsize[](#l3.68)
self.assertEqual(sys.getsizeof(True), size(vh) + self.longdigit)[](#l3.69)
self.assertEqual(sys.getsizeof(True, -1), size(vh) + self.longdigit)[](#l3.70)
vsize = test.support.calcvobjsize[](#l3.71)
self.assertEqual(sys.getsizeof(True), vsize('') + self.longdigit)[](#l3.72)
self.assertEqual(sys.getsizeof(True, -1), vsize('') + self.longdigit)[](#l3.73)
def test_objecttypes(self): # check all types defined in Objects/
h = self.header[](#l3.77)
vh = self.vheader[](#l3.78)
size = self.calcsize[](#l3.79)
size = test.support.calcobjsize[](#l3.80)
vsize = test.support.calcvobjsize[](#l3.81) check = self.check_sizeof[](#l3.82) # bool[](#l3.83)
check(True, size(vh) + self.longdigit)[](#l3.84)
check(True, vsize('') + self.longdigit)[](#l3.85) # buffer[](#l3.86) # XXX[](#l3.87) # builtin_function_or_method[](#l3.88)
check(len, size(h + '3P'))[](#l3.89)
check(len, size('3P')) # XXX check layout[](#l3.90) # bytearray[](#l3.91) samples = [b'', b'u'*100000][](#l3.92) for sample in samples:[](#l3.93) x = bytearray(sample)[](#l3.94)
check(x, size(vh + 'iPP') + x.__alloc__() * self.c)[](#l3.95)
check(x, vsize('iPP') + x.__alloc__())[](#l3.96) # bytearray_iterator[](#l3.97)
check(iter(bytearray()), size(h + 'PP'))[](#l3.98)
check(iter(bytearray()), size('PP'))[](#l3.99) # cell[](#l3.100) def get_cell():[](#l3.101) x = 42[](#l3.102) def inner():[](#l3.103) return x[](#l3.104) return inner[](#l3.105)
check(get_cell().__closure__[0], size(h + 'P'))[](#l3.106)
check(get_cell().__closure__[0], size('P'))[](#l3.107) # code[](#l3.108)
check(get_cell().__code__, size(h + '5i8Pi3P'))[](#l3.109)
check(get_cell().__code__, size('5i8Pi3P'))[](#l3.110) # complex[](#l3.111)
check(complex(0,1), size(h + '2d'))[](#l3.112)
check(complex(0,1), size('2d'))[](#l3.113) # method_descriptor (descriptor object)[](#l3.114)
check(str.lower, size(h + '2PP'))[](#l3.115)
check(str.lower, size('2PP'))[](#l3.116) # classmethod_descriptor (descriptor object)[](#l3.117) # XXX[](#l3.118) # member_descriptor (descriptor object)[](#l3.119) import datetime[](#l3.120)
check(datetime.timedelta.days, size(h + '2PP'))[](#l3.121)
check(datetime.timedelta.days, size('2PP'))[](#l3.122) # getset_descriptor (descriptor object)[](#l3.123) import collections[](#l3.124)
check(collections.defaultdict.default_factory, size(h + '2PP'))[](#l3.125)
check(collections.defaultdict.default_factory, size('2PP'))[](#l3.126) # wrapper_descriptor (descriptor object)[](#l3.127)
check(int.__add__, size(h + '2P2P'))[](#l3.128)
check(int.__add__, size('2P2P'))[](#l3.129) # method-wrapper (descriptor object)[](#l3.130)
check({}.__iter__, size(h + '2P'))[](#l3.131)
check({}.__iter__, size('2P'))[](#l3.132) # dict[](#l3.133)
check({}, size(h + '3P2P' + 8*'P2P'))[](#l3.134)
check({}, size('3P2P' + 8*'P2P'))[](#l3.135) longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8}[](#l3.136)
check(longdict, size(h + '3P2P' + 8*'P2P') + 16*size('P2P'))[](#l3.137)
check(longdict, size('3P2P' + 8*'P2P') + 16*struct.calcsize('P2P'))[](#l3.138) # dictionary-keyiterator[](#l3.139)
check({}.keys(), size(h + 'P'))[](#l3.140)
check({}.keys(), size('P'))[](#l3.141) # dictionary-valueiterator[](#l3.142)
check({}.values(), size(h + 'P'))[](#l3.143)
check({}.values(), size('P'))[](#l3.144) # dictionary-itemiterator[](#l3.145)
check({}.items(), size(h + 'P'))[](#l3.146)
check({}.items(), size('P'))[](#l3.147)
# dictionary iterator[](#l3.148)
check(iter({}), size('P2PPP'))[](#l3.149) # dictproxy[](#l3.150) class C(object): pass[](#l3.151)
check(C.__dict__, size(h + 'P'))[](#l3.152)
check(C.__dict__, size('P'))[](#l3.153) # BaseException[](#l3.154)
check(BaseException(), size(h + '5P'))[](#l3.155)
check(BaseException(), size('5P'))[](#l3.156) # UnicodeEncodeError[](#l3.157)
check(UnicodeEncodeError("", "", 0, 0, ""), size(h + '5P 2P2PP'))[](#l3.158)
check(UnicodeEncodeError("", "", 0, 0, ""), size('5P 2P2PP'))[](#l3.159) # UnicodeDecodeError[](#l3.160)
# XXX[](#l3.161)
-# check(UnicodeDecodeError("", "", 0, 0, ""), size(h + '5P2PP'))
check(UnicodeDecodeError("", b"", 0, 0, ""), size('5P 2P2PP'))[](#l3.163) # UnicodeTranslateError[](#l3.164)
check(UnicodeTranslateError("", 0, 1, ""), size(h + '5P 2P2PP'))[](#l3.165)
check(UnicodeTranslateError("", 0, 1, ""), size('5P 2P2PP'))[](#l3.166) # ellipses[](#l3.167)
check(Ellipsis, size(h + ''))[](#l3.168)
check(Ellipsis, size(''))[](#l3.169) # EncodingMap[](#l3.170) import codecs, encodings.iso8859_3[](#l3.171) x = codecs.charmap_build(encodings.iso8859_3.decoding_table)[](#l3.172)
check(x, size(h + '32B2iB'))[](#l3.173)
check(x, size('32B2iB'))[](#l3.174) # enumerate[](#l3.175)
check(enumerate([]), size(h + 'l3P'))[](#l3.176)
check(enumerate([]), size('l3P'))[](#l3.177) # reverse[](#l3.178)
check(reversed(''), size(h + 'PP'))[](#l3.179)
check(reversed(''), size('PP'))[](#l3.180) # float[](#l3.181)
check(float(0), size(h + 'd'))[](#l3.182)
check(float(0), size('d'))[](#l3.183) # sys.floatinfo[](#l3.184)
check(sys.float_info, size(vh) + self.P * len(sys.float_info))[](#l3.185)
check(sys.float_info, vsize('') + self.P * len(sys.float_info))[](#l3.186) # frame[](#l3.187) import inspect[](#l3.188) CO_MAXBLOCKS = 20[](#l3.189)
@@ -720,10 +685,10 @@ class SizeofTest(unittest.TestCase): nfrees = len(x.f_code.co_freevars) extras = x.f_code.co_stacksize + x.f_code.co_nlocals +[](#l3.192) ncells + nfrees - 1
check(x, size(vh + '12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))[](#l3.194)
check(x, vsize('12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))[](#l3.195) # function[](#l3.196) def func(): pass[](#l3.197)
check(func, size(h + '11P'))[](#l3.198)
check(func, size('11P'))[](#l3.199) class c():[](#l3.200) @staticmethod[](#l3.201) def foo():[](#l3.202)
@@ -732,68 +697,68 @@ class SizeofTest(unittest.TestCase): def bar(cls): pass # staticmethod
check(foo, size(h + 'P'))[](#l3.207)
check(foo, size('P'))[](#l3.208) # classmethod[](#l3.209)
check(bar, size(h + 'P'))[](#l3.210)
check(bar, size('P'))[](#l3.211) # generator[](#l3.212) def get_gen(): yield 1[](#l3.213)
check(get_gen(), size(h + 'Pi2P'))[](#l3.214)
check(get_gen(), size('Pi2P'))[](#l3.215) # iterator[](#l3.216)
check(iter('abc'), size(h + 'lP'))[](#l3.217)
check(iter('abc'), size('lP'))[](#l3.218) # callable-iterator[](#l3.219) import re[](#l3.220)
check(re.finditer('',''), size(h + '2P'))[](#l3.221)
check(re.finditer('',''), size('2P'))[](#l3.222) # list[](#l3.223) samples = [[], [1,2,3], ['1', '2', '3']][](#l3.224) for sample in samples:[](#l3.225)
check(sample, size(vh + 'PP') + len(sample)*self.P)[](#l3.226)
check(sample, vsize('PP') + len(sample)*self.P)[](#l3.227) # sortwrapper (list)[](#l3.228) # XXX[](#l3.229) # cmpwrapper (list)[](#l3.230) # XXX[](#l3.231) # listiterator (list)[](#l3.232)
check(iter([]), size(h + 'lP'))[](#l3.233)
check(iter([]), size('lP'))[](#l3.234) # listreverseiterator (list)[](#l3.235)
check(reversed([]), size(h + 'lP'))[](#l3.236)
check(reversed([]), size('lP'))[](#l3.237) # long[](#l3.238)
check(0, size(vh))[](#l3.239)
check(1, size(vh) + self.longdigit)[](#l3.240)
check(-1, size(vh) + self.longdigit)[](#l3.241)
check(0, vsize(''))[](#l3.242)
check(1, vsize('') + self.longdigit)[](#l3.243)
check(-1, vsize('') + self.longdigit)[](#l3.244) PyLong_BASE = 2**sys.int_info.bits_per_digit[](#l3.245)
check(int(PyLong_BASE), size(vh) + 2*self.longdigit)[](#l3.246)
check(int(PyLong_BASE**2-1), size(vh) + 2*self.longdigit)[](#l3.247)
check(int(PyLong_BASE**2), size(vh) + 3*self.longdigit)[](#l3.248)
# memory[](#l3.249)
check(memoryview(b''), size(h + 'PP2P2i7P'))[](#l3.250)
check(int(PyLong_BASE), vsize('') + 2*self.longdigit)[](#l3.251)
check(int(PyLong_BASE**2-1), vsize('') + 2*self.longdigit)[](#l3.252)
check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit)[](#l3.253)
# memoryview[](#l3.254)
check(memoryview(b''), size('PP2P2i7P'))[](#l3.255) # module[](#l3.256)
check(unittest, size(h + '3P'))[](#l3.257)
check(unittest, size('3P'))[](#l3.258) # None[](#l3.259)
check(None, size(h + ''))[](#l3.260)
check(None, size(''))[](#l3.261) # NotImplementedType[](#l3.262)
check(NotImplemented, size(h))[](#l3.263)
check(NotImplemented, size(''))[](#l3.264) # object[](#l3.265)
check(object(), size(h + ''))[](#l3.266)
check(object(), size(''))[](#l3.267) # property (descriptor object)[](#l3.268) class C(object):[](#l3.269) def getx(self): return self.__x[](#l3.270) def setx(self, value): self.__x = value[](#l3.271) def delx(self): del self.__x[](#l3.272) x = property(getx, setx, delx, "")[](#l3.273)
check(x, size(h + '4Pi'))[](#l3.274)
check(x, size('4Pi'))[](#l3.275) # PyCapsule[](#l3.276) # XXX[](#l3.277) # rangeiterator[](#l3.278)
check(iter(range(1)), size(h + '4l'))[](#l3.279)
check(iter(range(1)), size('4l'))[](#l3.280) # reverse[](#l3.281)
check(reversed(''), size(h + 'PP'))[](#l3.282)
check(reversed(''), size('PP'))[](#l3.283) # range[](#l3.284)
check(range(1), size(h + '4P'))[](#l3.285)
check(range(66000), size(h + '4P'))[](#l3.286)
check(range(1), size('4P'))[](#l3.287)
check(range(66000), size('4P'))[](#l3.288) # set[](#l3.289) # frozenset[](#l3.290) PySet_MINSIZE = 8[](#l3.291) samples = [[], range(10), range(50)][](#l3.292)
s = size(h + '3P2P' + PySet_MINSIZE*'lP' + 'lP')[](#l3.293)
s = size('3P2P' + PySet_MINSIZE*'PP' + 'PP')[](#l3.294) for sample in samples:[](#l3.295) minused = len(sample)[](#l3.296) if minused == 0: tmp = 1[](#l3.297)
@@ -810,18 +775,18 @@ class SizeofTest(unittest.TestCase): check(set(sample), s + newsizestruct.calcsize('lP')) check(frozenset(sample), s + newsizestruct.calcsize('lP')) # setiterator
check(iter(set()), size(h + 'P3P'))[](#l3.302)
check(iter(set()), size('P3P'))[](#l3.303) # slice[](#l3.304)
check(slice(0), size(h + '3P'))[](#l3.305)
check(slice(0), size('3P'))[](#l3.306) # super[](#l3.307)
check(super(int), size(h + '3P'))[](#l3.308)
check(super(int), size('3P'))[](#l3.309) # tuple[](#l3.310)
check((), size(vh))[](#l3.311)
check((1,2,3), size(vh) + 3*self.P)[](#l3.312)
check((), vsize(''))[](#l3.313)
check((1,2,3), vsize('') + 3*self.P)[](#l3.314) # type[](#l3.315) # (PyTypeObject + PyNumberMethods + PyMappingMethods +[](#l3.316) # PySequenceMethods + PyBufferProcs)[](#l3.317)
s = size(vh + 'P2P15Pl4PP9PP11PI') + size('16Pi17P 3P 10P 2P 2P')[](#l3.318)
s = vsize('P2P15Pl4PP9PP11PI') + struct.calcsize('16Pi17P 3P 10P 2P 2P')[](#l3.319) check(int, s)[](#l3.320) # class[](#l3.321) class newstyleclass(object): pass[](#l3.322)
@@ -832,39 +797,38 @@ class SizeofTest(unittest.TestCase): # we need to test for both sizes, because we don't know if the string # has been cached for s in samples:
basicsize = size(h + 'PPPiP') + usize * (len(s) + 1)[](#l3.327)
basicsize = size('PPPiP') + usize * (len(s) + 1)[](#l3.328) check(s, basicsize)[](#l3.329) # weakref[](#l3.330) import weakref[](#l3.331)
check(weakref.ref(int), size(h + '2Pl2P'))[](#l3.332)
check(weakref.ref(int), size('2Pl2P'))[](#l3.333) # weakproxy[](#l3.334) # XXX[](#l3.335) # weakcallableproxy[](#l3.336)
check(weakref.proxy(int), size(h + '2Pl2P'))[](#l3.337)
check(weakref.proxy(int), size('2Pl2P'))[](#l3.338)
def test_pythontypes(self): # check all types defined in Python/
h = self.header[](#l3.342)
vh = self.vheader[](#l3.343)
size = self.calcsize[](#l3.344)
size = test.support.calcobjsize[](#l3.345)
vsize = test.support.calcvobjsize[](#l3.346) check = self.check_sizeof[](#l3.347) # _ast.AST[](#l3.348) import _ast[](#l3.349)
check(_ast.AST(), size(h + ''))[](#l3.350)
check(_ast.AST(), size(''))[](#l3.351) # imp.NullImporter[](#l3.352) import imp[](#l3.353)
check(imp.NullImporter(self.file.name), size(h + ''))[](#l3.354)
check(imp.NullImporter(self.file.name), size(''))[](#l3.355) try:[](#l3.356) raise TypeError[](#l3.357) except TypeError:[](#l3.358) tb = sys.exc_info()[2][](#l3.359) # traceback[](#l3.360) if tb != None:[](#l3.361)
check(tb, size(h + '2P2i'))[](#l3.362)
check(tb, size('2P2i'))[](#l3.363) # symtable entry[](#l3.364) # XXX[](#l3.365) # sys.flags[](#l3.366)
check(sys.flags, size(vh) + self.P * len(sys.flags))[](#l3.367)
check(sys.flags, vsize('') + self.P * len(sys.flags))[](#l3.368)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -383,6 +383,9 @@ Extension Modules Tests ----- +- Issue #15467: Move helpers for sizeof tests into test_support.