summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_tools
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2019-09-27 14:53:34 (GMT)
committerGitHub <noreply@github.com>2019-09-27 14:53:34 (GMT)
commit6693f730e0eb77d9453f73a3da33b78a97e996ee (patch)
tree767d8adedbf3db4c89a1b74d030d1b563e4199fb /Lib/test/test_tools
parent90558158093c0ad893102158fd3c2dd9f864e82e (diff)
downloadcpython-6693f730e0eb77d9453f73a3da33b78a97e996ee.zip
cpython-6693f730e0eb77d9453f73a3da33b78a97e996ee.tar.gz
cpython-6693f730e0eb77d9453f73a3da33b78a97e996ee.tar.bz2
bpo-38187: Fix a refleak in Tools/c-analyzer. (gh-16304)
The "Slot" helper (descriptor) is leaking references due to its caching mechanism. The change includes a partial fix to Slot, but also adds Variable.storage to replace the problematic use of Slot. https://bugs.python.org/issue38187
Diffstat (limited to 'Lib/test/test_tools')
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py3
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py5
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py108
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py6
7 files changed, 100 insertions, 40 deletions
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py
index e69de29..bc502ef 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py
@@ -0,0 +1,6 @@
+import os.path
+from test.support import load_package_tests
+
+
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py
index 93100e0..215023d 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py
@@ -15,9 +15,6 @@ class FromFileTests(unittest.TestCase):
_return_read_tsv = ()
- def tearDown(self):
- Variable._isglobal.instances.clear()
-
@property
def calls(self):
try:
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py
index e69de29..bc502ef 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py
@@ -0,0 +1,6 @@
+import os.path
+from test.support import load_package_tests
+
+
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py
index b29f966..8288992 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py
@@ -64,7 +64,9 @@ class StaticsFromBinaryTests(_Base):
**self.kwargs))
self.assertEqual(found, [
+ info.Variable.from_parts('dir1/spam.c', None, 'var1', 'int'),
info.Variable.from_parts('dir1/spam.c', None, 'var2', 'static int'),
+ info.Variable.from_parts('dir1/spam.c', None, 'var3', 'char *'),
info.Variable.from_parts('dir1/eggs.c', None, 'var1', 'static int'),
info.Variable.from_parts('dir1/eggs.c', 'func1', 'var2', 'static char *'),
])
@@ -299,7 +301,7 @@ class StaticsTest(_Base):
info.Variable.from_parts('src1/spam.c', None, 'var1', 'static const char *'),
info.Variable.from_parts('src1/spam.c', None, 'var1b', 'const char *'),
info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'),
- info.Variable.from_parts('src1/spam.c', 'ham', 'result', 'int'),
+ info.Variable.from_parts('src1/spam.c', 'ham', 'result', 'int'), # skipped
info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'),
info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'),
info.Variable.from_parts('src1/spam.c', None, 'freelist', 'static (PyTupleObject *)[10]'),
@@ -318,6 +320,7 @@ class StaticsTest(_Base):
self.assertEqual(found, [
info.Variable.from_parts('src1/spam.c', None, 'var1', 'static const char *'),
+ info.Variable.from_parts('src1/spam.c', None, 'var1b', 'const char *'),
info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'),
info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'),
info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'),
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py
index e69de29..bc502ef 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py
@@ -0,0 +1,6 @@
+import os.path
+from test.support import load_package_tests
+
+
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py
index 1dfe5d0..d1a966c 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py
@@ -4,7 +4,7 @@ import unittest
from ..util import PseudoStr, StrProxy, Object
from .. import tool_imports_for_tests
with tool_imports_for_tests():
- from c_analyzer_common.info import ID
+ from c_analyzer_common.info import ID, UNKNOWN
from c_parser.info import (
normalize_vartype, Variable,
)
@@ -31,38 +31,47 @@ class VariableTests(unittest.TestCase):
VALID_ARGS = (
('x/y/z/spam.c', 'func', 'eggs'),
+ 'static',
'int',
)
VALID_KWARGS = dict(zip(Variable._fields, VALID_ARGS))
VALID_EXPECTED = VALID_ARGS
def test_init_typical_global(self):
- static = Variable(
- id=ID(
- filename='x/y/z/spam.c',
- funcname=None,
- name='eggs',
- ),
- vartype='int',
- )
+ for storage in ('static', 'extern', 'implicit'):
+ with self.subTest(storage):
+ static = Variable(
+ id=ID(
+ filename='x/y/z/spam.c',
+ funcname=None,
+ name='eggs',
+ ),
+ storage=storage,
+ vartype='int',
+ )
- self.assertEqual(static, (
- ('x/y/z/spam.c', None, 'eggs'),
- 'int',
- ))
+ self.assertEqual(static, (
+ ('x/y/z/spam.c', None, 'eggs'),
+ storage,
+ 'int',
+ ))
def test_init_typical_local(self):
- static = Variable(
- id=ID(
- filename='x/y/z/spam.c',
- funcname='func',
- name='eggs',
- ),
- vartype='int',
- )
+ for storage in ('static', 'local'):
+ with self.subTest(storage):
+ static = Variable(
+ id=ID(
+ filename='x/y/z/spam.c',
+ funcname='func',
+ name='eggs',
+ ),
+ storage=storage,
+ vartype='int',
+ )
self.assertEqual(static, (
('x/y/z/spam.c', 'func', 'eggs'),
+ storage,
'int',
))
@@ -71,12 +80,14 @@ class VariableTests(unittest.TestCase):
with self.subTest(repr(value)):
static = Variable(
id=value,
+ storage=value,
vartype=value,
)
self.assertEqual(static, (
None,
None,
+ None,
))
def test_init_all_coerced(self):
@@ -89,34 +100,42 @@ class VariableTests(unittest.TestCase):
PseudoStr('func'),
PseudoStr('spam'),
),
+ storage=PseudoStr('static'),
vartype=PseudoStr('int'),
),
(id,
+ 'static',
'int',
)),
('non-str 1',
dict(
id=id,
+ storage=Object(),
vartype=Object(),
),
(id,
'<object>',
+ '<object>',
)),
('non-str 2',
dict(
id=id,
+ storage=StrProxy('static'),
vartype=StrProxy('variable'),
),
(id,
+ 'static',
'variable',
)),
('non-str',
dict(
id=id,
- vartype=('a', 'b', 'c'),
+ storage=('a', 'b', 'c'),
+ vartype=('x', 'y', 'z'),
),
(id,
"('a', 'b', 'c')",
+ "('x', 'y', 'z')",
)),
]
for summary, kwargs, expected in tests:
@@ -134,36 +153,43 @@ class VariableTests(unittest.TestCase):
def test_iterable(self):
static = Variable(**self.VALID_KWARGS)
- id, vartype = static
+ id, storage, vartype = static
- values = (id, vartype)
+ values = (id, storage, vartype)
for value, expected in zip(values, self.VALID_EXPECTED):
self.assertEqual(value, expected)
def test_fields(self):
- static = Variable(('a', 'b', 'z'), 'x')
+ static = Variable(('a', 'b', 'z'), 'x', 'y')
self.assertEqual(static.id, ('a', 'b', 'z'))
- self.assertEqual(static.vartype, 'x')
+ self.assertEqual(static.storage, 'x')
+ self.assertEqual(static.vartype, 'y')
def test___getattr__(self):
- static = Variable(('a', 'b', 'z'), 'x')
+ static = Variable(('a', 'b', 'z'), 'x', 'y')
self.assertEqual(static.filename, 'a')
self.assertEqual(static.funcname, 'b')
self.assertEqual(static.name, 'z')
def test_validate_typical(self):
- static = Variable(
- id=ID(
- filename='x/y/z/spam.c',
- funcname='func',
- name='eggs',
- ),
- vartype='int',
- )
+ validstorage = ('static', 'extern', 'implicit', 'local')
+ self.assertEqual(set(validstorage), set(Variable.STORAGE))
+
+ for storage in validstorage:
+ with self.subTest(storage):
+ static = Variable(
+ id=ID(
+ filename='x/y/z/spam.c',
+ funcname='func',
+ name='eggs',
+ ),
+ storage=storage,
+ vartype='int',
+ )
- static.validate() # This does not fail.
+ static.validate() # This does not fail.
def test_validate_missing_field(self):
for field in Variable._fields:
@@ -173,6 +199,13 @@ class VariableTests(unittest.TestCase):
with self.assertRaises(TypeError):
static.validate()
+ for field in ('storage', 'vartype'):
+ with self.subTest(field):
+ static = Variable(**self.VALID_KWARGS)
+ static = static._replace(**{field: UNKNOWN})
+
+ with self.assertRaises(TypeError):
+ static.validate()
def test_validate_bad_field(self):
badch = tuple(c for c in string.punctuation + string.digits)
@@ -185,6 +218,7 @@ class VariableTests(unittest.TestCase):
) + badch
tests = [
('id', ()), # Any non-empty str is okay.
+ ('storage', ('external', 'global') + notnames),
('vartype', ()), # Any non-empty str is okay.
]
seen = set()
@@ -199,6 +233,8 @@ class VariableTests(unittest.TestCase):
static.validate()
for field, invalid in tests:
+ if field == 'id':
+ continue
valid = seen - set(invalid)
for value in valid:
with self.subTest(f'{field}={value!r}'):
diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py
index e69de29..bc502ef 100644
--- a/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py
+++ b/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py
@@ -0,0 +1,6 @@
+import os.path
+from test.support import load_package_tests
+
+
+def load_tests(*args):
+ return load_package_tests(os.path.dirname(__file__), *args)