Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5a794c1

Browse files
committed
Issue #22060: Clean up/simplify test_ctypes, use test discovery
1 parent 79a1ffd commit 5a794c1

9 files changed

Lines changed: 74 additions & 302 deletions

File tree

Lib/ctypes/test/__init__.py

Lines changed: 7 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,216 +1,14 @@
1-
import os, sys, unittest, getopt, time
1+
import os
2+
import unittest
3+
from test import support
24

3-
use_resources = []
4-
5-
import ctypes
5+
# skip tests if _ctypes was not built
6+
ctypes = support.import_module('ctypes')
67
ctypes_symbols = dir(ctypes)
78

89
def need_symbol(name):
910
return unittest.skipUnless(name in ctypes_symbols,
1011
'{!r} is required'.format(name))
1112

12-
13-
class ResourceDenied(unittest.SkipTest):
14-
"""Test skipped because it requested a disallowed resource.
15-
16-
This is raised when a test calls requires() for a resource that
17-
has not be enabled. Resources are defined by test modules.
18-
"""
19-
20-
def is_resource_enabled(resource):
21-
"""Test whether a resource is enabled.
22-
23-
If the caller's module is __main__ then automatically return True."""
24-
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
25-
return True
26-
result = use_resources is not None and \
27-
(resource in use_resources or "*" in use_resources)
28-
if not result:
29-
_unavail[resource] = None
30-
return result
31-
32-
_unavail = {}
33-
def requires(resource, msg=None):
34-
"""Raise ResourceDenied if the specified resource is not available.
35-
36-
If the caller's module is __main__ then automatically return True."""
37-
# see if the caller's module is __main__ - if so, treat as if
38-
# the resource was set
39-
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
40-
return
41-
if not is_resource_enabled(resource):
42-
if msg is None:
43-
msg = "Use of the `%s' resource not enabled" % resource
44-
raise ResourceDenied(msg)
45-
46-
def find_package_modules(package, mask):
47-
import fnmatch
48-
if (package.__loader__ is not None and
49-
hasattr(package.__loader__, '_files')):
50-
path = package.__name__.replace(".", os.path.sep)
51-
mask = os.path.join(path, mask)
52-
for fnm in package.__loader__._files.keys():
53-
if fnmatch.fnmatchcase(fnm, mask):
54-
yield os.path.splitext(fnm)[0].replace(os.path.sep, ".")
55-
else:
56-
path = package.__path__[0]
57-
for fnm in os.listdir(path):
58-
if fnmatch.fnmatchcase(fnm, mask):
59-
yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0])
60-
61-
def get_tests(package, mask, verbosity, exclude=()):
62-
"""Return a list of skipped test modules, and a list of test cases."""
63-
tests = []
64-
skipped = []
65-
for modname in find_package_modules(package, mask):
66-
if modname.split(".")[-1] in exclude:
67-
skipped.append(modname)
68-
if verbosity > 1:
69-
print("Skipped %s: excluded" % modname, file=sys.stderr)
70-
continue
71-
try:
72-
mod = __import__(modname, globals(), locals(), ['*'])
73-
except (ResourceDenied, unittest.SkipTest) as detail:
74-
skipped.append(modname)
75-
if verbosity > 1:
76-
print("Skipped %s: %s" % (modname, detail), file=sys.stderr)
77-
continue
78-
for name in dir(mod):
79-
if name.startswith("_"):
80-
continue
81-
o = getattr(mod, name)
82-
if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase):
83-
tests.append(o)
84-
return skipped, tests
85-
86-
def usage():
87-
print(__doc__)
88-
return 1
89-
90-
def test_with_refcounts(runner, verbosity, testcase):
91-
"""Run testcase several times, tracking reference counts."""
92-
import gc
93-
import ctypes
94-
ptc = ctypes._pointer_type_cache.copy()
95-
cfc = ctypes._c_functype_cache.copy()
96-
wfc = ctypes._win_functype_cache.copy()
97-
98-
# when searching for refcount leaks, we have to manually reset any
99-
# caches that ctypes has.
100-
def cleanup():
101-
ctypes._pointer_type_cache = ptc.copy()
102-
ctypes._c_functype_cache = cfc.copy()
103-
ctypes._win_functype_cache = wfc.copy()
104-
gc.collect()
105-
106-
test = unittest.makeSuite(testcase)
107-
for i in range(5):
108-
rc = sys.gettotalrefcount()
109-
runner.run(test)
110-
cleanup()
111-
COUNT = 5
112-
refcounts = [None] * COUNT
113-
for i in range(COUNT):
114-
rc = sys.gettotalrefcount()
115-
runner.run(test)
116-
cleanup()
117-
refcounts[i] = sys.gettotalrefcount() - rc
118-
if filter(None, refcounts):
119-
print("%s leaks:\n\t" % testcase, refcounts)
120-
elif verbosity:
121-
print("%s: ok." % testcase)
122-
123-
class TestRunner(unittest.TextTestRunner):
124-
def run(self, test, skipped):
125-
"Run the given test case or test suite."
126-
# Same as unittest.TextTestRunner.run, except that it reports
127-
# skipped tests.
128-
result = self._makeResult()
129-
startTime = time.time()
130-
test(result)
131-
stopTime = time.time()
132-
timeTaken = stopTime - startTime
133-
result.printErrors()
134-
self.stream.writeln(result.separator2)
135-
run = result.testsRun
136-
if _unavail: #skipped:
137-
requested = list(_unavail.keys())
138-
requested.sort()
139-
self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" %
140-
(run, run != 1 and "s" or "", timeTaken,
141-
len(skipped),
142-
len(skipped) != 1 and "s" or ""))
143-
self.stream.writeln("Unavailable resources: %s" % ", ".join(requested))
144-
else:
145-
self.stream.writeln("Ran %d test%s in %.3fs" %
146-
(run, run != 1 and "s" or "", timeTaken))
147-
self.stream.writeln()
148-
if not result.wasSuccessful():
149-
self.stream.write("FAILED (")
150-
failed, errored = map(len, (result.failures, result.errors))
151-
if failed:
152-
self.stream.write("failures=%d" % failed)
153-
if errored:
154-
if failed: self.stream.write(", ")
155-
self.stream.write("errors=%d" % errored)
156-
self.stream.writeln(")")
157-
else:
158-
self.stream.writeln("OK")
159-
return result
160-
161-
162-
def main(*packages):
163-
try:
164-
opts, args = getopt.getopt(sys.argv[1:], "rqvu:x:")
165-
except getopt.error:
166-
return usage()
167-
168-
verbosity = 1
169-
search_leaks = False
170-
exclude = []
171-
for flag, value in opts:
172-
if flag == "-q":
173-
verbosity -= 1
174-
elif flag == "-v":
175-
verbosity += 1
176-
elif flag == "-r":
177-
try:
178-
sys.gettotalrefcount
179-
except AttributeError:
180-
print("-r flag requires Python debug build", file=sys.stderr)
181-
return -1
182-
search_leaks = True
183-
elif flag == "-u":
184-
use_resources.extend(value.split(","))
185-
elif flag == "-x":
186-
exclude.extend(value.split(","))
187-
188-
mask = "test_*.py"
189-
if args:
190-
mask = args[0]
191-
192-
for package in packages:
193-
run_tests(package, mask, verbosity, search_leaks, exclude)
194-
195-
196-
def run_tests(package, mask, verbosity, search_leaks, exclude):
197-
skipped, testcases = get_tests(package, mask, verbosity, exclude)
198-
runner = TestRunner(verbosity=verbosity)
199-
200-
suites = [unittest.makeSuite(o) for o in testcases]
201-
suite = unittest.TestSuite(suites)
202-
result = runner.run(suite, skipped)
203-
204-
if search_leaks:
205-
# hunt for refcount leaks
206-
runner = BasicTestRunner()
207-
for t in testcases:
208-
test_with_refcounts(runner, verbosity, t)
209-
210-
return bool(result.errors)
211-
212-
class BasicTestRunner:
213-
def run(self, test):
214-
result = unittest.TestResult()
215-
test(result)
216-
return result
13+
def load_tests(*args):
14+
return support.load_package_tests(os.path.dirname(__file__), *args)

Lib/ctypes/test/__main__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from ctypes.test import load_tests
2+
import unittest
3+
4+
unittest.main()

Lib/ctypes/test/runtests.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

Lib/ctypes/test/test_find.py

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,58 @@
11
import unittest
22
import os
33
import sys
4+
import test.support
45
from ctypes import *
56
from ctypes.util import find_library
6-
from ctypes.test import is_resource_enabled
7-
8-
if sys.platform == "win32":
9-
lib_gl = find_library("OpenGL32")
10-
lib_glu = find_library("Glu32")
11-
lib_gle = None
12-
elif sys.platform == "darwin":
13-
lib_gl = lib_glu = find_library("OpenGL")
14-
lib_gle = None
15-
else:
16-
lib_gl = find_library("GL")
17-
lib_glu = find_library("GLU")
18-
lib_gle = find_library("gle")
19-
20-
## print, for debugging
21-
if is_resource_enabled("printing"):
22-
if lib_gl or lib_glu or lib_gle:
23-
print("OpenGL libraries:")
24-
for item in (("GL", lib_gl),
25-
("GLU", lib_glu),
26-
("gle", lib_gle)):
27-
print("\t", item)
28-
297

308
# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode.
319
class Test_OpenGL_libs(unittest.TestCase):
32-
def setUp(self):
33-
self.gl = self.glu = self.gle = None
10+
@classmethod
11+
def setUpClass(cls):
12+
lib_gl = lib_glu = lib_gle = None
13+
if sys.platform == "win32":
14+
lib_gl = find_library("OpenGL32")
15+
lib_glu = find_library("Glu32")
16+
elif sys.platform == "darwin":
17+
lib_gl = lib_glu = find_library("OpenGL")
18+
else:
19+
lib_gl = find_library("GL")
20+
lib_glu = find_library("GLU")
21+
lib_gle = find_library("gle")
22+
23+
## print, for debugging
24+
if test.support.verbose:
25+
print("OpenGL libraries:")
26+
for item in (("GL", lib_gl),
27+
("GLU", lib_glu),
28+
("gle", lib_gle)):
29+
print("\t", item)
30+
31+
cls.gl = cls.glu = cls.gle = None
3432
if lib_gl:
35-
self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL)
33+
cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL)
3634
if lib_glu:
37-
self.glu = CDLL(lib_glu, RTLD_GLOBAL)
35+
cls.glu = CDLL(lib_glu, RTLD_GLOBAL)
3836
if lib_gle:
3937
try:
40-
self.gle = CDLL(lib_gle)
38+
cls.gle = CDLL(lib_gle)
4139
except OSError:
4240
pass
4341

44-
@unittest.skipUnless(lib_gl, 'lib_gl not available')
4542
def test_gl(self):
46-
if self.gl:
47-
self.gl.glClearIndex
43+
if self.gl is None:
44+
self.skipTest('lib_gl not available')
45+
self.gl.glClearIndex
4846

49-
@unittest.skipUnless(lib_glu, 'lib_glu not available')
5047
def test_glu(self):
51-
if self.glu:
52-
self.glu.gluBeginCurve
48+
if self.glu is None:
49+
self.skipTest('lib_glu not available')
50+
self.glu.gluBeginCurve
5351

54-
@unittest.skipUnless(lib_gle, 'lib_gle not available')
5552
def test_gle(self):
56-
if self.gle:
57-
self.gle.gleGetJoinStyle
53+
if self.gle is None:
54+
self.skipTest('lib_gle not available')
55+
self.gle.gleGetJoinStyle
5856

5957
# On platforms where the default shared library suffix is '.so',
6058
# at least some libraries can be loaded as attributes of the cdll

0 commit comments

Comments
 (0)