aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_tools/test_c_analyzer')
-rw-r--r--Lib/test/test_tools/test_c_analyzer/__init__.py15
-rw-r--r--Lib/test/test_tools/test_c_analyzer/__main__.py5
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_common/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_common/test_files.py470
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_common/test_info.py197
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_common/test_show.py54
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_cpython/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_cpython/test___main__.py296
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_cpython/test_functional.py34
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_cpython/test_supported.py98
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_parser/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_parser/test_declarations.py795
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_parser/test_preprocessor.py1561
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_symbols/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_symbols/test_info.py192
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_variables/__init__.py6
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_variables/test_find.py124
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_variables/test_info.py244
-rw-r--r--Lib/test/test_tools/test_c_analyzer/test_variables/test_known.py139
-rw-r--r--Lib/test/test_tools/test_c_analyzer/util.py60
20 files changed, 0 insertions, 4314 deletions
diff --git a/Lib/test/test_tools/test_c_analyzer/__init__.py b/Lib/test/test_tools/test_c_analyzer/__init__.py
deleted file mode 100644
index d0b4c045104..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import contextlib
-import os.path
-import test.test_tools
-from test.support import load_package_tests
-
-
-@contextlib.contextmanager
-def tool_imports_for_tests():
- test.test_tools.skip_if_missing('c-analyzer')
- with test.test_tools.imports_under_tool('c-analyzer'):
- yield
-
-
-def load_tests(*args):
- return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_tools/test_c_analyzer/__main__.py b/Lib/test/test_tools/test_c_analyzer/__main__.py
deleted file mode 100644
index b5b017de8a8..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/__main__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from . import load_tests
-import unittest
-
-
-unittest.main()
diff --git a/Lib/test/test_tools/test_c_analyzer/test_common/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_common/__init__.py
deleted file mode 100644
index bc502ef32d2..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_common/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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_common/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_common/test_files.py
deleted file mode 100644
index 0c97d2a0bbf..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_common/test_files.py
+++ /dev/null
@@ -1,470 +0,0 @@
-import os.path
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.common.files import (
- iter_files, _walk_tree, glob_tree,
- )
-
-
-def fixpath(filename):
- return filename.replace('/', os.path.sep)
-
-
-class IterFilesTests(unittest.TestCase):
-
- maxDiff = None
-
- _return_walk = None
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
- def set_files(self, *filesperroot):
- roots = []
- result = []
- for root, files in filesperroot:
- root = fixpath(root)
- roots.append(root)
- result.append([os.path.join(root, fixpath(f))
- for f in files])
- self._return_walk = result
- return roots
-
- def _walk(self, root, *, suffix=None, walk=None):
- self.calls.append(('_walk', (root, suffix, walk)))
- return iter(self._return_walk.pop(0))
-
- def _glob(self, root, *, suffix=None):
- self.calls.append(('_glob', (root, suffix)))
- return iter(self._return_walk.pop(0))
-
- def test_typical(self):
- dirnames = self.set_files(
- ('spam', ['file1.c', 'file2.c']),
- ('eggs', ['ham/file3.h']),
- )
- suffixes = ('.c', '.h')
-
- files = list(iter_files(dirnames, suffixes,
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- fixpath('eggs/ham/file3.h'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', None, _walk_tree)),
- ('_walk', ('eggs', None, _walk_tree)),
- ])
-
- def test_single_root(self):
- self._return_walk = [
- [fixpath('spam/file1.c'), fixpath('spam/file2.c')],
- ]
-
- files = list(iter_files('spam', '.c',
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', '.c', _walk_tree)),
- ])
-
- def test_one_root(self):
- self._return_walk = [
- [fixpath('spam/file1.c'), fixpath('spam/file2.c')],
- ]
-
- files = list(iter_files(['spam'], '.c',
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', '.c', _walk_tree)),
- ])
-
- def test_multiple_roots(self):
- dirnames = self.set_files(
- ('spam', ['file1.c', 'file2.c']),
- ('eggs', ['ham/file3.c']),
- )
-
- files = list(iter_files(dirnames, '.c',
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- fixpath('eggs/ham/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', '.c', _walk_tree)),
- ('_walk', ('eggs', '.c', _walk_tree)),
- ])
-
- def test_no_roots(self):
- files = list(iter_files([], '.c',
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [])
- self.assertEqual(self.calls, [])
-
- def test_single_suffix(self):
- self._return_walk = [
- [fixpath('spam/file1.c'),
- fixpath('spam/eggs/file3.c'),
- ],
- ]
-
- files = list(iter_files('spam', '.c',
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/eggs/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', '.c', _walk_tree)),
- ])
-
- def test_one_suffix(self):
- self._return_walk = [
- [fixpath('spam/file1.c'),
- fixpath('spam/file1.h'),
- fixpath('spam/file1.o'),
- fixpath('spam/eggs/file3.c'),
- ],
- ]
-
- files = list(iter_files('spam', ['.c'],
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/eggs/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', None, _walk_tree)),
- ])
-
- def test_multiple_suffixes(self):
- self._return_walk = [
- [fixpath('spam/file1.c'),
- fixpath('spam/file1.h'),
- fixpath('spam/file1.o'),
- fixpath('spam/eggs/file3.c'),
- ],
- ]
-
- files = list(iter_files('spam', ('.c', '.h'),
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file1.h'),
- fixpath('spam/eggs/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', None, _walk_tree)),
- ])
-
- def test_no_suffix(self):
- expected = [fixpath('spam/file1.c'),
- fixpath('spam/file1.h'),
- fixpath('spam/file1.o'),
- fixpath('spam/eggs/file3.c'),
- ]
- for suffix in (None, '', ()):
- with self.subTest(suffix):
- self.calls.clear()
- self._return_walk = [list(expected)]
-
- files = list(iter_files('spam', suffix,
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, expected)
- self.assertEqual(self.calls, [
- ('_walk', ('spam', suffix, _walk_tree)),
- ])
-
- def test_relparent(self):
- dirnames = self.set_files(
- ('/x/y/z/spam', ['file1.c', 'file2.c']),
- ('/x/y/z/eggs', ['ham/file3.c']),
- )
-
- files = list(iter_files(dirnames, '.c', fixpath('/x/y'),
- _glob=self._glob,
- _walk=self._walk))
-
- self.assertEqual(files, [
- fixpath('z/spam/file1.c'),
- fixpath('z/spam/file2.c'),
- fixpath('z/eggs/ham/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', (fixpath('/x/y/z/spam'), '.c', _walk_tree)),
- ('_walk', (fixpath('/x/y/z/eggs'), '.c', _walk_tree)),
- ])
-
- def test_glob(self):
- dirnames = self.set_files(
- ('spam', ['file1.c', 'file2.c']),
- ('eggs', ['ham/file3.c']),
- )
-
- files = list(iter_files(dirnames, '.c',
- get_files=glob_tree,
- _walk=self._walk,
- _glob=self._glob))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- fixpath('eggs/ham/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_glob', ('spam', '.c')),
- ('_glob', ('eggs', '.c')),
- ])
-
-
- def test_alt_walk_func(self):
- dirnames = self.set_files(
- ('spam', ['file1.c', 'file2.c']),
- ('eggs', ['ham/file3.c']),
- )
- def get_files(root):
- return None
-
- files = list(iter_files(dirnames, '.c',
- get_files=get_files,
- _walk=self._walk,
- _glob=self._glob))
-
- self.assertEqual(files, [
- fixpath('spam/file1.c'),
- fixpath('spam/file2.c'),
- fixpath('eggs/ham/file3.c'),
- ])
- self.assertEqual(self.calls, [
- ('_walk', ('spam', '.c', get_files)),
- ('_walk', ('eggs', '.c', get_files)),
- ])
-
-
-
-
-
-
-# def test_no_dirnames(self):
-# dirnames = []
-# filter_by_name = None
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [])
-# self.assertEqual(self.calls, [])
-#
-# def test_no_filter(self):
-# self._return_walk = [
-# [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# ]
-# filter_by_name = None
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [
-# fixpath('spam/file1'),
-# fixpath('spam/file2.c'),
-# fixpath('spam/file3.h'),
-# fixpath('spam/file4.o'),
-# ])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ])
-#
-# def test_no_files(self):
-# self._return_walk = [
-# [('spam', (), ()),
-# ],
-# [(fixpath('eggs/ham'), (), ()),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# fixpath('eggs/ham'),
-# ]
-# filter_by_name = None
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ('_walk', (fixpath('eggs/ham'),)),
-# ])
-#
-# def test_tree(self):
-# self._return_walk = [
-# [('spam', ('sub1', 'sub2', 'sub3'), ('file1',)),
-# (fixpath('spam/sub1'), ('sub1sub1',), ('file2', 'file3')),
-# (fixpath('spam/sub1/sub1sub1'), (), ('file4',)),
-# (fixpath('spam/sub2'), (), ()),
-# (fixpath('spam/sub3'), (), ('file5',)),
-# ],
-# [(fixpath('eggs/ham'), (), ('file6',)),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# fixpath('eggs/ham'),
-# ]
-# filter_by_name = None
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [
-# fixpath('spam/file1'),
-# fixpath('spam/sub1/file2'),
-# fixpath('spam/sub1/file3'),
-# fixpath('spam/sub1/sub1sub1/file4'),
-# fixpath('spam/sub3/file5'),
-# fixpath('eggs/ham/file6'),
-# ])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ('_walk', (fixpath('eggs/ham'),)),
-# ])
-#
-# def test_filter_suffixes(self):
-# self._return_walk = [
-# [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# ]
-# filter_by_name = ('.c', '.h')
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [
-# fixpath('spam/file2.c'),
-# fixpath('spam/file3.h'),
-# ])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ])
-#
-# def test_some_filtered(self):
-# self._return_walk = [
-# [('spam', (), ('file1', 'file2', 'file3', 'file4')),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# ]
-# def filter_by_name(filename, results=[False, True, False, True]):
-# self.calls.append(('filter_by_name', (filename,)))
-# return results.pop(0)
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [
-# fixpath('spam/file2'),
-# fixpath('spam/file4'),
-# ])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ('filter_by_name', ('file1',)),
-# ('filter_by_name', ('file2',)),
-# ('filter_by_name', ('file3',)),
-# ('filter_by_name', ('file4',)),
-# ])
-#
-# def test_none_filtered(self):
-# self._return_walk = [
-# [('spam', (), ('file1', 'file2', 'file3', 'file4')),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# ]
-# def filter_by_name(filename, results=[True, True, True, True]):
-# self.calls.append(('filter_by_name', (filename,)))
-# return results.pop(0)
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [
-# fixpath('spam/file1'),
-# fixpath('spam/file2'),
-# fixpath('spam/file3'),
-# fixpath('spam/file4'),
-# ])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ('filter_by_name', ('file1',)),
-# ('filter_by_name', ('file2',)),
-# ('filter_by_name', ('file3',)),
-# ('filter_by_name', ('file4',)),
-# ])
-#
-# def test_all_filtered(self):
-# self._return_walk = [
-# [('spam', (), ('file1', 'file2', 'file3', 'file4')),
-# ],
-# ]
-# dirnames = [
-# 'spam',
-# ]
-# def filter_by_name(filename, results=[False, False, False, False]):
-# self.calls.append(('filter_by_name', (filename,)))
-# return results.pop(0)
-#
-# files = list(iter_files(dirnames, filter_by_name,
-# _walk=self._walk))
-#
-# self.assertEqual(files, [])
-# self.assertEqual(self.calls, [
-# ('_walk', ('spam',)),
-# ('filter_by_name', ('file1',)),
-# ('filter_by_name', ('file2',)),
-# ('filter_by_name', ('file3',)),
-# ('filter_by_name', ('file4',)),
-# ])
diff --git a/Lib/test/test_tools/test_c_analyzer/test_common/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_common/test_info.py
deleted file mode 100644
index 69dbb582c6b..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_common/test_info.py
+++ /dev/null
@@ -1,197 +0,0 @@
-import string
-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 (
- UNKNOWN,
- ID,
- )
-
-
-class IDTests(unittest.TestCase):
-
- VALID_ARGS = (
- 'x/y/z/spam.c',
- 'func',
- 'eggs',
- )
- VALID_KWARGS = dict(zip(ID._fields, VALID_ARGS))
- VALID_EXPECTED = VALID_ARGS
-
- def test_from_raw(self):
- tests = [
- ('', None),
- (None, None),
- ('spam', (None, None, 'spam')),
- (('spam',), (None, None, 'spam')),
- (('x/y/z/spam.c', 'spam'), ('x/y/z/spam.c', None, 'spam')),
- (self.VALID_ARGS, self.VALID_EXPECTED),
- (self.VALID_KWARGS, self.VALID_EXPECTED),
- ]
- for raw, expected in tests:
- with self.subTest(raw):
- id = ID.from_raw(raw)
-
- self.assertEqual(id, expected)
-
- def test_minimal(self):
- id = ID(
- filename=None,
- funcname=None,
- name='eggs',
- )
-
- self.assertEqual(id, (
- None,
- None,
- 'eggs',
- ))
-
- def test_init_typical_global(self):
- id = ID(
- filename='x/y/z/spam.c',
- funcname=None,
- name='eggs',
- )
-
- self.assertEqual(id, (
- 'x/y/z/spam.c',
- None,
- 'eggs',
- ))
-
- def test_init_typical_local(self):
- id = ID(
- filename='x/y/z/spam.c',
- funcname='func',
- name='eggs',
- )
-
- self.assertEqual(id, (
- 'x/y/z/spam.c',
- 'func',
- 'eggs',
- ))
-
- def test_init_all_missing(self):
- for value in ('', None):
- with self.subTest(repr(value)):
- id = ID(
- filename=value,
- funcname=value,
- name=value,
- )
-
- self.assertEqual(id, (
- None,
- None,
- None,
- ))
-
- def test_init_all_coerced(self):
- tests = [
- ('str subclass',
- dict(
- filename=PseudoStr('x/y/z/spam.c'),
- funcname=PseudoStr('func'),
- name=PseudoStr('eggs'),
- ),
- ('x/y/z/spam.c',
- 'func',
- 'eggs',
- )),
- ('non-str',
- dict(
- filename=StrProxy('x/y/z/spam.c'),
- funcname=Object(),
- name=('a', 'b', 'c'),
- ),
- ('x/y/z/spam.c',
- '<object>',
- "('a', 'b', 'c')",
- )),
- ]
- for summary, kwargs, expected in tests:
- with self.subTest(summary):
- id = ID(**kwargs)
-
- for field in ID._fields:
- value = getattr(id, field)
- self.assertIs(type(value), str)
- self.assertEqual(tuple(id), expected)
-
- def test_iterable(self):
- id = ID(**self.VALID_KWARGS)
-
- filename, funcname, name = id
-
- values = (filename, funcname, name)
- for value, expected in zip(values, self.VALID_EXPECTED):
- self.assertEqual(value, expected)
-
- def test_fields(self):
- id = ID('a', 'b', 'z')
-
- self.assertEqual(id.filename, 'a')
- self.assertEqual(id.funcname, 'b')
- self.assertEqual(id.name, 'z')
-
- def test_validate_typical(self):
- id = ID(
- filename='x/y/z/spam.c',
- funcname='func',
- name='eggs',
- )
-
- id.validate() # This does not fail.
-
- def test_validate_missing_field(self):
- for field in ID._fields:
- with self.subTest(field):
- id = ID(**self.VALID_KWARGS)
- id = id._replace(**{field: None})
-
- if field == 'funcname':
- id.validate() # The field can be missing (not set).
- id = id._replace(filename=None)
- id.validate() # Both fields can be missing (not set).
- continue
-
- with self.assertRaises(TypeError):
- id.validate()
-
- def test_validate_bad_field(self):
- badch = tuple(c for c in string.punctuation + string.digits)
- notnames = (
- '1a',
- 'a.b',
- 'a-b',
- '&a',
- 'a++',
- ) + badch
- tests = [
- ('filename', ()), # Any non-empty str is okay.
- ('funcname', notnames),
- ('name', notnames),
- ]
- seen = set()
- for field, invalid in tests:
- for value in invalid:
- seen.add(value)
- with self.subTest(f'{field}={value!r}'):
- id = ID(**self.VALID_KWARGS)
- id = id._replace(**{field: value})
-
- with self.assertRaises(ValueError):
- id.validate()
-
- for field, invalid in tests:
- valid = seen - set(invalid)
- for value in valid:
- with self.subTest(f'{field}={value!r}'):
- id = ID(**self.VALID_KWARGS)
- id = id._replace(**{field: value})
-
- id.validate() # This does not fail.
diff --git a/Lib/test/test_tools/test_c_analyzer/test_common/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_common/test_show.py
deleted file mode 100644
index 91ca2f3b344..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_common/test_show.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.variables import info
- from c_analyzer.common.show import (
- basic,
- )
-
-
-TYPICAL = [
- info.Variable.from_parts('src1/spam.c', None, 'var1', 'static 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'),
- info.Variable.from_parts('src1/spam.c', None, 'freelist', 'static (PyTupleObject *)[10]'),
- info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'static const char const *'),
- info.Variable.from_parts('src2/jam.c', None, 'var1', 'static int'),
- info.Variable.from_parts('src2/jam.c', None, 'var2', 'static MyObject *'),
- info.Variable.from_parts('Include/spam.h', None, 'data', 'static const int'),
- ]
-
-
-class BasicTests(unittest.TestCase):
-
- maxDiff = None
-
- def setUp(self):
- self.lines = []
-
- def print(self, line):
- self.lines.append(line)
-
- def test_typical(self):
- basic(TYPICAL,
- _print=self.print)
-
- self.assertEqual(self.lines, [
- 'src1/spam.c:var1 static const char *',
- 'src1/spam.c:ham():initialized static int',
- 'src1/spam.c:var2 static PyObject *',
- 'src1/eggs.c:tofu():ready static int',
- 'src1/spam.c:freelist static (PyTupleObject *)[10]',
- 'src1/sub/ham.c:var1 static const char const *',
- 'src2/jam.c:var1 static int',
- 'src2/jam.c:var2 static MyObject *',
- 'Include/spam.h:data static const int',
- ])
-
- def test_no_rows(self):
- basic([],
- _print=self.print)
-
- self.assertEqual(self.lines, [])
diff --git a/Lib/test/test_tools/test_c_analyzer/test_cpython/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_cpython/__init__.py
deleted file mode 100644
index bc502ef32d2..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_cpython/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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_cpython/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_cpython/test___main__.py
deleted file mode 100644
index 6d69ed7525b..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_cpython/test___main__.py
+++ /dev/null
@@ -1,296 +0,0 @@
-import sys
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.variables import info
- from cpython import SOURCE_DIRS
- from cpython.supported import IGNORED_FILE
- from cpython.known import DATA_FILE as KNOWN_FILE
- from cpython.__main__ import (
- cmd_check, cmd_show, parse_args, main,
- )
-
-
-TYPICAL = [
- (info.Variable.from_parts('src1/spam.c', None, 'var1', 'const char *'),
- True,
- ),
- (info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'int'),
- True,
- ),
- (info.Variable.from_parts('src1/spam.c', None, 'var2', 'PyObject *'),
- False,
- ),
- (info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'int'),
- True,
- ),
- (info.Variable.from_parts('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'),
- False,
- ),
- (info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'const char const *'),
- True,
- ),
- (info.Variable.from_parts('src2/jam.c', None, 'var1', 'int'),
- True,
- ),
- (info.Variable.from_parts('src2/jam.c', None, 'var2', 'MyObject *'),
- False,
- ),
- (info.Variable.from_parts('Include/spam.h', None, 'data', 'const int'),
- True,
- ),
- ]
-
-
-class CMDBase(unittest.TestCase):
-
- maxDiff = None
-
-# _return_known_from_file = None
-# _return_ignored_from_file = None
- _return_find = ()
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
-# def _known_from_file(self, *args):
-# self.calls.append(('_known_from_file', args))
-# return self._return_known_from_file or {}
-#
-# def _ignored_from_file(self, *args):
-# self.calls.append(('_ignored_from_file', args))
-# return self._return_ignored_from_file or {}
-
- def _find(self, known, ignored, skip_objects=False):
- self.calls.append(('_find', (known, ignored, skip_objects)))
- return self._return_find
-
- def _show(self, *args):
- self.calls.append(('_show', args))
-
- def _print(self, *args):
- self.calls.append(('_print', args))
-
-
-class CheckTests(CMDBase):
-
- def test_defaults(self):
- self._return_find = []
-
- cmd_check('check',
- _find=self._find,
- _show=self._show,
- _print=self._print,
- )
-
- self.assertEqual(
- self.calls[0],
- ('_find', (KNOWN_FILE, IGNORED_FILE, False)),
- )
-
- def test_all_supported(self):
- self._return_find = [(v, s) for v, s in TYPICAL if s]
- dirs = ['src1', 'src2', 'Include']
-
- cmd_check('check',
- known='known.tsv',
- ignored='ignored.tsv',
- _find=self._find,
- _show=self._show,
- _print=self._print,
- )
-
- self.assertEqual(self.calls, [
- ('_find', ('known.tsv', 'ignored.tsv', False)),
- #('_print', ('okay',)),
- ])
-
- def test_some_unsupported(self):
- self._return_find = TYPICAL
-
- with self.assertRaises(SystemExit) as cm:
- cmd_check('check',
- known='known.tsv',
- ignored='ignored.tsv',
- _find=self._find,
- _show=self._show,
- _print=self._print,
- )
-
- unsupported = [v for v, s in TYPICAL if not s]
- self.assertEqual(self.calls, [
- ('_find', ('known.tsv', 'ignored.tsv', False)),
- ('_print', ('ERROR: found unsupported global variables',)),
- ('_print', ()),
- ('_show', (sorted(unsupported),)),
- ('_print', (' (3 total)',)),
- ])
- self.assertEqual(cm.exception.code, 1)
-
-
-class ShowTests(CMDBase):
-
- def test_defaults(self):
- self._return_find = []
-
- cmd_show('show',
- _find=self._find,
- _show=self._show,
- _print=self._print,
- )
-
- self.assertEqual(
- self.calls[0],
- ('_find', (KNOWN_FILE, IGNORED_FILE, False)),
- )
-
- def test_typical(self):
- self._return_find = TYPICAL
-
- cmd_show('show',
- known='known.tsv',
- ignored='ignored.tsv',
- _find=self._find,
- _show=self._show,
- _print=self._print,
- )
-
- supported = [v for v, s in TYPICAL if s]
- unsupported = [v for v, s in TYPICAL if not s]
- self.assertEqual(self.calls, [
- ('_find', ('known.tsv', 'ignored.tsv', False)),
- ('_print', ('supported:',)),
- ('_print', ('----------',)),
- ('_show', (sorted(supported),)),
- ('_print', (' (6 total)',)),
- ('_print', ()),
- ('_print', ('unsupported:',)),
- ('_print', ('------------',)),
- ('_show', (sorted(unsupported),)),
- ('_print', (' (3 total)',)),
- ])
-
-
-class ParseArgsTests(unittest.TestCase):
-
- maxDiff = None
-
- def test_no_args(self):
- self.errmsg = None
- def fail(msg):
- self.errmsg = msg
- sys.exit(msg)
-
- with self.assertRaises(SystemExit):
- parse_args('cg', [], _fail=fail)
-
- self.assertEqual(self.errmsg, 'missing command')
-
- def test_check_no_args(self):
- cmd, cmdkwargs = parse_args('cg', [
- 'check',
- ])
-
- self.assertEqual(cmd, 'check')
- self.assertEqual(cmdkwargs, {
- 'ignored': IGNORED_FILE,
- 'known': KNOWN_FILE,
- #'dirs': SOURCE_DIRS,
- })
-
- def test_check_full_args(self):
- cmd, cmdkwargs = parse_args('cg', [
- 'check',
- '--ignored', 'spam.tsv',
- '--known', 'eggs.tsv',
- #'dir1',
- #'dir2',
- #'dir3',
- ])
-
- self.assertEqual(cmd, 'check')
- self.assertEqual(cmdkwargs, {
- 'ignored': 'spam.tsv',
- 'known': 'eggs.tsv',
- #'dirs': ['dir1', 'dir2', 'dir3']
- })
-
- def test_show_no_args(self):
- cmd, cmdkwargs = parse_args('cg', [
- 'show',
- ])
-
- self.assertEqual(cmd, 'show')
- self.assertEqual(cmdkwargs, {
- 'ignored': IGNORED_FILE,
- 'known': KNOWN_FILE,
- #'dirs': SOURCE_DIRS,
- 'skip_objects': False,
- })
-
- def test_show_full_args(self):
- cmd, cmdkwargs = parse_args('cg', [
- 'show',
- '--ignored', 'spam.tsv',
- '--known', 'eggs.tsv',
- #'dir1',
- #'dir2',
- #'dir3',
- ])
-
- self.assertEqual(cmd, 'show')
- self.assertEqual(cmdkwargs, {
- 'ignored': 'spam.tsv',
- 'known': 'eggs.tsv',
- #'dirs': ['dir1', 'dir2', 'dir3'],
- 'skip_objects': False,
- })
-
-
-def new_stub_commands(*names):
- calls = []
- def cmdfunc(cmd, **kwargs):
- calls.append((cmd, kwargs))
- commands = {name: cmdfunc for name in names}
- return commands, calls
-
-
-class MainTests(unittest.TestCase):
-
- def test_no_command(self):
- with self.assertRaises(ValueError):
- main(None, {})
-
- def test_check(self):
- commands, calls = new_stub_commands('check', 'show')
-
- cmdkwargs = {
- 'ignored': 'spam.tsv',
- 'known': 'eggs.tsv',
- 'dirs': ['dir1', 'dir2', 'dir3'],
- }
- main('check', cmdkwargs, _COMMANDS=commands)
-
- self.assertEqual(calls, [
- ('check', cmdkwargs),
- ])
-
- def test_show(self):
- commands, calls = new_stub_commands('check', 'show')
-
- cmdkwargs = {
- 'ignored': 'spam.tsv',
- 'known': 'eggs.tsv',
- 'dirs': ['dir1', 'dir2', 'dir3'],
- }
- main('show', cmdkwargs, _COMMANDS=commands)
-
- self.assertEqual(calls, [
- ('show', cmdkwargs),
- ])
diff --git a/Lib/test/test_tools/test_c_analyzer/test_cpython/test_functional.py b/Lib/test/test_tools/test_c_analyzer/test_cpython/test_functional.py
deleted file mode 100644
index 92797904844..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_cpython/test_functional.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- pass
-
-
-class SelfCheckTests(unittest.TestCase):
-
- @unittest.expectedFailure
- def test_known(self):
- # Make sure known macros & vartypes aren't hiding unknown local types.
- # XXX finish!
- raise NotImplementedError
-
- @unittest.expectedFailure
- def test_compare_nm_results(self):
- # Make sure the "show" results match the statics found by "nm" command.
- # XXX Skip if "nm" is not available.
- # XXX finish!
- raise NotImplementedError
-
-
-class DummySourceTests(unittest.TestCase):
-
- @unittest.expectedFailure
- def test_check(self):
- # XXX finish!
- raise NotImplementedError
-
- @unittest.expectedFailure
- def test_show(self):
- # XXX finish!
- raise NotImplementedError
diff --git a/Lib/test/test_tools/test_c_analyzer/test_cpython/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_cpython/test_supported.py
deleted file mode 100644
index a244b97e1fc..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_cpython/test_supported.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import re
-import textwrap
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.common.info import ID
- from c_analyzer.variables.info import Variable
- from cpython.supported import (
- is_supported, ignored_from_file,
- )
-
-
-class IsSupportedTests(unittest.TestCase):
-
- @unittest.expectedFailure
- def test_supported(self):
- statics = [
- Variable('src1/spam.c', None, 'var1', 'const char *'),
- Variable('src1/spam.c', None, 'var1', 'int'),
- ]
- for static in statics:
- with self.subTest(static):
- result = is_supported(static)
-
- self.assertTrue(result)
-
- @unittest.expectedFailure
- def test_not_supported(self):
- statics = [
- Variable('src1/spam.c', None, 'var1', 'PyObject *'),
- Variable('src1/spam.c', None, 'var1', 'PyObject[10]'),
- ]
- for static in statics:
- with self.subTest(static):
- result = is_supported(static)
-
- self.assertFalse(result)
-
-
-class IgnoredFromFileTests(unittest.TestCase):
-
- maxDiff = None
-
- _return_read_tsv = ()
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
- def _read_tsv(self, *args):
- self.calls.append(('_read_tsv', args))
- return self._return_read_tsv
-
- def test_typical(self):
- lines = textwrap.dedent('''
- filename funcname name kind reason
- file1.c - var1 variable ...
- file1.c func1 local1 variable |
- file1.c - var2 variable ???
- file1.c func2 local2 variable |
- file2.c - var1 variable reasons
- ''').strip().splitlines()
- lines = [re.sub(r'\s{1,8}', '\t', line, 4).replace('|', '')
- for line in lines]
- self._return_read_tsv = [tuple(v.strip() for v in line.split('\t'))
- for line in lines[1:]]
-
- ignored = ignored_from_file('spam.c', _read_tsv=self._read_tsv)
-
- self.assertEqual(ignored, {
- 'variables': {
- ID('file1.c', '', 'var1'): '...',
- ID('file1.c', 'func1', 'local1'): '',
- ID('file1.c', '', 'var2'): '???',
- ID('file1.c', 'func2', 'local2'): '',
- ID('file2.c', '', 'var1'): 'reasons',
- },
- })
- self.assertEqual(self.calls, [
- ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\treason')),
- ])
-
- def test_empty(self):
- self._return_read_tsv = []
-
- ignored = ignored_from_file('spam.c', _read_tsv=self._read_tsv)
-
- self.assertEqual(ignored, {
- 'variables': {},
- })
- self.assertEqual(self.calls, [
- ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\treason')),
- ])
diff --git a/Lib/test/test_tools/test_c_analyzer/test_parser/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_parser/__init__.py
deleted file mode 100644
index bc502ef32d2..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_parser/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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_parser/test_declarations.py b/Lib/test/test_tools/test_c_analyzer/test_parser/test_declarations.py
deleted file mode 100644
index 674fcb1af1c..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_parser/test_declarations.py
+++ /dev/null
@@ -1,795 +0,0 @@
-import textwrap
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.parser.declarations import (
- iter_global_declarations, iter_local_statements,
- parse_func, _parse_var, parse_compound,
- iter_variables,
- )
-
-
-class TestCaseBase(unittest.TestCase):
-
- maxDiff = None
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
-
-class IterGlobalDeclarationsTests(TestCaseBase):
-
- def test_functions(self):
- tests = [
- (textwrap.dedent('''
- void func1() {
- return;
- }
- '''),
- textwrap.dedent('''
- void func1() {
- return;
- }
- ''').strip(),
- ),
- (textwrap.dedent('''
- static unsigned int * _func1(
- const char *arg1,
- int *arg2
- long long arg3
- )
- {
- return _do_something(arg1, arg2, arg3);
- }
- '''),
- textwrap.dedent('''
- static unsigned int * _func1( const char *arg1, int *arg2 long long arg3 ) {
- return _do_something(arg1, arg2, arg3);
- }
- ''').strip(),
- ),
- (textwrap.dedent('''
- static PyObject *
- _func1(const char *arg1, PyObject *arg2)
- {
- static int initialized = 0;
- if (!initialized) {
- initialized = 1;
- _init(arg1);
- }
-
- PyObject *result = _do_something(arg1, arg2);
- Py_INCREF(result);
- return result;
- }
- '''),
- textwrap.dedent('''
- static PyObject * _func1(const char *arg1, PyObject *arg2) {
- static int initialized = 0;
- if (!initialized) {
- initialized = 1;
- _init(arg1);
- }
- PyObject *result = _do_something(arg1, arg2);
- Py_INCREF(result);
- return result;
- }
- ''').strip(),
- ),
- ]
- for lines, expected in tests:
- body = textwrap.dedent(
- expected.partition('{')[2].rpartition('}')[0]
- ).strip()
- expected = (expected, body)
- with self.subTest(lines):
- lines = lines.splitlines()
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [expected])
-
- @unittest.expectedFailure
- def test_declarations(self):
- tests = [
- 'int spam;',
- 'long long spam;',
- 'static const int const *spam;',
- 'int spam;',
- 'typedef int myint;',
- 'typedef PyObject * (*unaryfunc)(PyObject *);',
- # typedef struct
- # inline struct
- # enum
- # inline enum
- ]
- for text in tests:
- expected = (text,
- ' '.join(l.strip() for l in text.splitlines()))
- with self.subTest(lines):
- lines = lines.splitlines()
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [expected])
-
- @unittest.expectedFailure
- def test_declaration_multiple_vars(self):
- lines = ['static const int const *spam, *ham=NULL, eggs = 3;']
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [
- ('static const int const *spam;', None),
- ('static const int *ham=NULL;', None),
- ('static const int eggs = 3;', None),
- ])
-
- def test_mixed(self):
- lines = textwrap.dedent('''
- int spam;
- static const char const *eggs;
-
- PyObject * start(void) {
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- }
-
- char* ham;
-
- static int stop(char *reason) {
- ham = reason;
- return _stop();
- }
- ''').splitlines()
- expected = [
- (textwrap.dedent('''
- PyObject * start(void) {
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- }
- ''').strip(),
- textwrap.dedent('''
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- ''').strip(),
- ),
- (textwrap.dedent('''
- static int stop(char *reason) {
- ham = reason;
- return _stop();
- }
- ''').strip(),
- textwrap.dedent('''
- ham = reason;
- return _stop();
- ''').strip(),
- ),
- ]
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, expected)
- #self.assertEqual([stmt for stmt, _ in stmts],
- # [stmt for stmt, _ in expected])
- #self.assertEqual([body for _, body in stmts],
- # [body for _, body in expected])
-
- def test_no_statements(self):
- lines = []
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [])
-
- def test_bogus(self):
- tests = [
- (textwrap.dedent('''
- int spam;
- static const char const *eggs;
-
- PyObject * start(void) {
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- }
-
- char* ham;
-
- static int _stop(void) {
- // missing closing bracket
-
- static int stop(char *reason) {
- ham = reason;
- return _stop();
- }
- '''),
- [(textwrap.dedent('''
- PyObject * start(void) {
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- }
- ''').strip(),
- textwrap.dedent('''
- static int initialized = 0;
- if (initialized) {
- initialized = 1;
- init();
- }
- return _start();
- ''').strip(),
- ),
- # Neither "stop()" nor "_stop()" are here.
- ],
- ),
- ]
- for lines, expected in tests:
- with self.subTest(lines):
- lines = lines.splitlines()
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, expected)
- #self.assertEqual([stmt for stmt, _ in stmts],
- # [stmt for stmt, _ in expected])
- #self.assertEqual([body for _, body in stmts],
- # [body for _, body in expected])
-
- def test_ignore_comments(self):
- tests = [
- ('// msg', None),
- ('// int stmt;', None),
- (' // ... ', None),
- ('// /*', None),
- ('/* int stmt; */', None),
- ("""
- /**
- * ...
- * int stmt;
- */
- """, None),
- ]
- for lines, expected in tests:
- with self.subTest(lines):
- lines = lines.splitlines()
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [expected] if expected else [])
-
-
-class IterLocalStatementsTests(TestCaseBase):
-
- def test_vars(self):
- tests = [
- # POTS
- 'int spam;',
- 'unsigned int spam;',
- 'char spam;',
- 'float spam;',
-
- # typedefs
- 'uint spam;',
- 'MyType spam;',
-
- # complex
- 'struct myspam spam;',
- 'union choice spam;',
- # inline struct
- # inline union
- # enum?
- ]
- # pointers
- tests.extend([
- # POTS
- 'int * spam;',
- 'unsigned int * spam;',
- 'char *spam;',
- 'char const *spam = "spamspamspam...";',
- # typedefs
- 'MyType *spam;',
- # complex
- 'struct myspam *spam;',
- 'union choice *spam;',
- # packed with details
- 'const char const *spam;',
- # void pointer
- 'void *data = NULL;',
- # function pointers
- 'int (* func)(char *arg1);',
- 'char * (* func)(void);',
- ])
- # storage class
- tests.extend([
- 'static int spam;',
- 'extern int spam;',
- 'static unsigned int spam;',
- 'static struct myspam spam;',
- ])
- # type qualifier
- tests.extend([
- 'const int spam;',
- 'const unsigned int spam;',
- 'const struct myspam spam;',
- ])
- # combined
- tests.extend([
- 'const char *spam = eggs;',
- 'static const char const *spam = "spamspamspam...";',
- 'extern const char const *spam;',
- 'static void *data = NULL;',
- 'static int (const * func)(char *arg1) = func1;',
- 'static char * (* func)(void);',
- ])
- for line in tests:
- expected = line
- with self.subTest(line):
- stmts = list(iter_local_statements([line]))
-
- self.assertEqual(stmts, [(expected, None)])
-
- @unittest.expectedFailure
- def test_vars_multiline_var(self):
- lines = textwrap.dedent('''
- PyObject *
- spam
- = NULL;
- ''').splitlines()
- expected = 'PyObject * spam = NULL;'
-
- stmts = list(iter_local_statements(lines))
-
- self.assertEqual(stmts, [(expected, None)])
-
- @unittest.expectedFailure
- def test_declaration_multiple_vars(self):
- lines = ['static const int const *spam, *ham=NULL, ham2[]={1, 2, 3}, ham3[2]={1, 2}, eggs = 3;']
-
- stmts = list(iter_global_declarations(lines))
-
- self.assertEqual(stmts, [
- ('static const int const *spam;', None),
- ('static const int *ham=NULL;', None),
- ('static const int ham[]={1, 2, 3};', None),
- ('static const int ham[2]={1, 2};', None),
- ('static const int eggs = 3;', None),
- ])
-
- @unittest.expectedFailure
- def test_other_simple(self):
- raise NotImplementedError
-
- @unittest.expectedFailure
- def test_compound(self):
- raise NotImplementedError
-
- @unittest.expectedFailure
- def test_mixed(self):
- raise NotImplementedError
-
- def test_no_statements(self):
- lines = []
-
- stmts = list(iter_local_statements(lines))
-
- self.assertEqual(stmts, [])
-
- @unittest.expectedFailure
- def test_bogus(self):
- raise NotImplementedError
-
- def test_ignore_comments(self):
- tests = [
- ('// msg', None),
- ('// int stmt;', None),
- (' // ... ', None),
- ('// /*', None),
- ('/* int stmt; */', None),
- ("""
- /**
- * ...
- * int stmt;
- */
- """, None),
- # mixed with statements
- ('int stmt; // ...', ('int stmt;', None)),
- ( 'int stmt; /* ... */', ('int stmt;', None)),
- ( '/* ... */ int stmt;', ('int stmt;', None)),
- ]
- for lines, expected in tests:
- with self.subTest(lines):
- lines = lines.splitlines()
-
- stmts = list(iter_local_statements(lines))
-
- self.assertEqual(stmts, [expected] if expected else [])
-
-
-class ParseFuncTests(TestCaseBase):
-
- def test_typical(self):
- tests = [
- ('PyObject *\nspam(char *a)\n{\nreturn _spam(a);\n}',
- 'return _spam(a);',
- ('spam', 'PyObject * spam(char *a)'),
- ),
- ]
- for stmt, body, expected in tests:
- with self.subTest(stmt):
- name, signature = parse_func(stmt, body)
-
- self.assertEqual((name, signature), expected)
-
-
-class ParseVarTests(TestCaseBase):
-
- def test_typical(self):
- tests = [
- # POTS
- ('int spam;', ('spam', 'int')),
- ('unsigned int spam;', ('spam', 'unsigned int')),
- ('char spam;', ('spam', 'char')),
- ('float spam;', ('spam', 'float')),
-
- # typedefs
- ('uint spam;', ('spam', 'uint')),
- ('MyType spam;', ('spam', 'MyType')),
-
- # complex
- ('struct myspam spam;', ('spam', 'struct myspam')),
- ('union choice spam;', ('spam', 'union choice')),
- # inline struct
- # inline union
- # enum?
- ]
- # pointers
- tests.extend([
- # POTS
- ('int * spam;', ('spam', 'int *')),
- ('unsigned int * spam;', ('spam', 'unsigned int *')),
- ('char *spam;', ('spam', 'char *')),
- ('char const *spam = "spamspamspam...";', ('spam', 'char const *')),
- # typedefs
- ('MyType *spam;', ('spam', 'MyType *')),
- # complex
- ('struct myspam *spam;', ('spam', 'struct myspam *')),
- ('union choice *spam;', ('spam', 'union choice *')),
- # packed with details
- ('const char const *spam;', ('spam', 'const char const *')),
- # void pointer
- ('void *data = NULL;', ('data', 'void *')),
- # function pointers
- ('int (* func)(char *);', ('func', 'int (*)(char *)')),
- ('char * (* func)(void);', ('func', 'char * (*)(void)')),
- ])
- # storage class
- tests.extend([
- ('static int spam;', ('spam', 'static int')),
- ('extern int spam;', ('spam', 'extern int')),
- ('static unsigned int spam;', ('spam', 'static unsigned int')),
- ('static struct myspam spam;', ('spam', 'static struct myspam')),
- ])
- # type qualifier
- tests.extend([
- ('const int spam;', ('spam', 'const int')),
- ('const unsigned int spam;', ('spam', 'const unsigned int')),
- ('const struct myspam spam;', ('spam', 'const struct myspam')),
- ])
- # combined
- tests.extend([
- ('const char *spam = eggs;', ('spam', 'const char *')),
- ('static const char const *spam = "spamspamspam...";',
- ('spam', 'static const char const *')),
- ('extern const char const *spam;',
- ('spam', 'extern const char const *')),
- ('static void *data = NULL;', ('data', 'static void *')),
- ('static int (const * func)(char *) = func1;',
- ('func', 'static int (const *)(char *)')),
- ('static char * (* func)(void);',
- ('func', 'static char * (*)(void)')),
- ])
- for stmt, expected in tests:
- with self.subTest(stmt):
- name, vartype = _parse_var(stmt)
-
- self.assertEqual((name, vartype), expected)
-
-
-@unittest.skip('not finished')
-class ParseCompoundTests(TestCaseBase):
-
- def test_typical(self):
- headers, bodies = parse_compound(stmt, blocks)
- ...
-
-
-class IterVariablesTests(TestCaseBase):
-
- _return_iter_source_lines = None
- _return_iter_global = None
- _return_iter_local = None
- _return_parse_func = None
- _return_parse_var = None
- _return_parse_compound = None
-
- def _iter_source_lines(self, filename):
- self.calls.append(
- ('_iter_source_lines', (filename,)))
- return self._return_iter_source_lines.splitlines()
-
- def _iter_global(self, lines):
- self.calls.append(
- ('_iter_global', (lines,)))
- try:
- return self._return_iter_global.pop(0)
- except IndexError:
- return ('???', None)
-
- def _iter_local(self, lines):
- self.calls.append(
- ('_iter_local', (lines,)))
- try:
- return self._return_iter_local.pop(0)
- except IndexError:
- return ('???', None)
-
- def _parse_func(self, stmt, body):
- self.calls.append(
- ('_parse_func', (stmt, body)))
- try:
- return self._return_parse_func.pop(0)
- except IndexError:
- return ('???', '???')
-
- def _parse_var(self, lines):
- self.calls.append(
- ('_parse_var', (lines,)))
- try:
- return self._return_parse_var.pop(0)
- except IndexError:
- return ('???', '???')
-
- def _parse_compound(self, stmt, blocks):
- self.calls.append(
- ('_parse_compound', (stmt, blocks)))
- try:
- return self._return_parse_compound.pop(0)
- except IndexError:
- return (['???'], ['???'])
-
- def test_empty_file(self):
- self._return_iter_source_lines = ''
- self._return_iter_global = [
- [],
- ]
- self._return_parse_func = None
- self._return_parse_var = None
- self._return_parse_compound = None
-
- srcvars = list(iter_variables('spam.c',
- _iter_source_lines=self._iter_source_lines,
- _iter_global=self._iter_global,
- _iter_local=self._iter_local,
- _parse_func=self._parse_func,
- _parse_var=self._parse_var,
- _parse_compound=self._parse_compound,
- ))
-
- self.assertEqual(srcvars, [])
- self.assertEqual(self.calls, [
- ('_iter_source_lines', ('spam.c',)),
- ('_iter_global', ([],)),
- ])
-
- def test_no_statements(self):
- content = textwrap.dedent('''
- ...
- ''')
- self._return_iter_source_lines = content
- self._return_iter_global = [
- [],
- ]
- self._return_parse_func = None
- self._return_parse_var = None
- self._return_parse_compound = None
-
- srcvars = list(iter_variables('spam.c',
- _iter_source_lines=self._iter_source_lines,
- _iter_global=self._iter_global,
- _iter_local=self._iter_local,
- _parse_func=self._parse_func,
- _parse_var=self._parse_var,
- _parse_compound=self._parse_compound,
- ))
-
- self.assertEqual(srcvars, [])
- self.assertEqual(self.calls, [
- ('_iter_source_lines', ('spam.c',)),
- ('_iter_global', (content.splitlines(),)),
- ])
-
- def test_typical(self):
- content = textwrap.dedent('''
- ...
- ''')
- self._return_iter_source_lines = content
- self._return_iter_global = [
- [('<lines 1>', None), # var1
- ('<lines 2>', None), # non-var
- ('<lines 3>', None), # var2
- ('<lines 4>', '<body 1>'), # func1
- ('<lines 9>', None), # var4
- ],
- ]
- self._return_iter_local = [
- # func1
- [('<lines 5>', None), # var3
- ('<lines 6>', [('<header 1>', '<block 1>')]), # if
- ('<lines 8>', None), # non-var
- ],
- # if
- [('<lines 7>', None), # var2 ("collision" with global var)
- ],
- ]
- self._return_parse_func = [
- ('func1', '<sig 1>'),
- ]
- self._return_parse_var = [
- ('var1', '<vartype 1>'),
- (None, None),
- ('var2', '<vartype 2>'),
- ('var3', '<vartype 3>'),
- ('var2', '<vartype 2b>'),
- ('var4', '<vartype 4>'),
- (None, None),
- (None, None),
- (None, None),
- ('var5', '<vartype 5>'),
- ]
- self._return_parse_compound = [
- ([[
- 'if (',
- '<simple>',
- ')',
- ],
- ],
- ['<block 1>']),
- ]
-
- srcvars = list(iter_variables('spam.c',
- _iter_source_lines=self._iter_source_lines,
- _iter_global=self._iter_global,
- _iter_local=self._iter_local,
- _parse_func=self._parse_func,
- _parse_var=self._parse_var,
- _parse_compound=self._parse_compound,
- ))
-
- self.assertEqual(srcvars, [
- (None, 'var1', '<vartype 1>'),
- (None, 'var2', '<vartype 2>'),
- ('func1', 'var3', '<vartype 3>'),
- ('func1', 'var2', '<vartype 2b>'),
- ('func1', 'var4', '<vartype 4>'),
- (None, 'var5', '<vartype 5>'),
- ])
- self.assertEqual(self.calls, [
- ('_iter_source_lines', ('spam.c',)),
- ('_iter_global', (content.splitlines(),)),
- ('_parse_var', ('<lines 1>',)),
- ('_parse_var', ('<lines 2>',)),
- ('_parse_var', ('<lines 3>',)),
- ('_parse_func', ('<lines 4>', '<body 1>')),
- ('_iter_local', (['<body 1>'],)),
- ('_parse_var', ('<lines 5>',)),
- ('_parse_compound', ('<lines 6>', [('<header 1>', '<block 1>')])),
- ('_parse_var', ('if (',)),
- ('_parse_var', ('<simple>',)),
- ('_parse_var', (')',)),
- ('_parse_var', ('<lines 8>',)),
- ('_iter_local', (['<block 1>'],)),
- ('_parse_var', ('<lines 7>',)),
- ('_parse_var', ('<lines 9>',)),
- ])
-
- def test_no_locals(self):
- content = textwrap.dedent('''
- ...
- ''')
- self._return_iter_source_lines = content
- self._return_iter_global = [
- [('<lines 1>', None), # var1
- ('<lines 2>', None), # non-var
- ('<lines 3>', None), # var2
- ('<lines 4>', '<body 1>'), # func1
- ],
- ]
- self._return_iter_local = [
- # func1
- [('<lines 5>', None), # non-var
- ('<lines 6>', [('<header 1>', '<block 1>')]), # if
- ('<lines 8>', None), # non-var
- ],
- # if
- [('<lines 7>', None), # non-var
- ],
- ]
- self._return_parse_func = [
- ('func1', '<sig 1>'),
- ]
- self._return_parse_var = [
- ('var1', '<vartype 1>'),
- (None, None),
- ('var2', '<vartype 2>'),
- (None, None),
- (None, None),
- (None, None),
- (None, None),
- (None, None),
- (None, None),
- ]
- self._return_parse_compound = [
- ([[
- 'if (',
- '<simple>',
- ')',
- ],
- ],
- ['<block 1>']),
- ]
-
- srcvars = list(iter_variables('spam.c',
- _iter_source_lines=self._iter_source_lines,
- _iter_global=self._iter_global,
- _iter_local=self._iter_local,
- _parse_func=self._parse_func,
- _parse_var=self._parse_var,
- _parse_compound=self._parse_compound,
- ))
-
- self.assertEqual(srcvars, [
- (None, 'var1', '<vartype 1>'),
- (None, 'var2', '<vartype 2>'),
- ])
- self.assertEqual(self.calls, [
- ('_iter_source_lines', ('spam.c',)),
- ('_iter_global', (content.splitlines(),)),
- ('_parse_var', ('<lines 1>',)),
- ('_parse_var', ('<lines 2>',)),
- ('_parse_var', ('<lines 3>',)),
- ('_parse_func', ('<lines 4>', '<body 1>')),
- ('_iter_local', (['<body 1>'],)),
- ('_parse_var', ('<lines 5>',)),
- ('_parse_compound', ('<lines 6>', [('<header 1>', '<block 1>')])),
- ('_parse_var', ('if (',)),
- ('_parse_var', ('<simple>',)),
- ('_parse_var', (')',)),
- ('_parse_var', ('<lines 8>',)),
- ('_iter_local', (['<block 1>'],)),
- ('_parse_var', ('<lines 7>',)),
- ])
diff --git a/Lib/test/test_tools/test_c_analyzer/test_parser/test_preprocessor.py b/Lib/test/test_tools/test_c_analyzer/test_parser/test_preprocessor.py
deleted file mode 100644
index b7f950f8139..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_parser/test_preprocessor.py
+++ /dev/null
@@ -1,1561 +0,0 @@
-import textwrap
-import unittest
-import sys
-
-from ..util import wrapped_arg_combos, StrProxy
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.parser.preprocessor import (
- iter_lines,
- # directives
- parse_directive, PreprocessorDirective,
- Constant, Macro, IfDirective, Include, OtherDirective,
- )
-
-
-class TestCaseBase(unittest.TestCase):
-
- maxDiff = None
-
- def reset(self):
- self._calls = []
- self.errors = None
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
- errors = None
-
- def try_next_exc(self):
- if not self.errors:
- return
- if exc := self.errors.pop(0):
- raise exc
-
- def check_calls(self, *expected):
- self.assertEqual(self.calls, list(expected))
- self.assertEqual(self.errors or [], [])
-
-
-class IterLinesTests(TestCaseBase):
-
- parsed = None
-
- def check_calls(self, *expected):
- super().check_calls(*expected)
- self.assertEqual(self.parsed or [], [])
-
- def _parse_directive(self, line):
- self.calls.append(
- ('_parse_directive', line))
- self.try_next_exc()
- return self.parsed.pop(0)
-
- def test_no_lines(self):
- lines = []
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [])
- self.check_calls()
-
- def test_no_directives(self):
- lines = textwrap.dedent('''
-
- // xyz
- typedef enum {
- SPAM
- EGGS
- } kind;
-
- struct info {
- kind kind;
- int status;
- };
-
- typedef struct spam {
- struct info info;
- } myspam;
-
- static int spam = 0;
-
- /**
- * ...
- */
- static char *
- get_name(int arg,
- char *default,
- )
- {
- return default
- }
-
- int check(void) {
- return 0;
- }
-
- ''')[1:-1].splitlines()
- expected = [(lno, line, None, ())
- for lno, line in enumerate(lines, 1)]
- expected[1] = (2, ' ', None, ())
- expected[20] = (21, ' ', None, ())
- del expected[19]
- del expected[18]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, expected)
- self.check_calls()
-
- def test_single_directives(self):
- tests = [
- ('#include <stdio>', Include('<stdio>')),
- ('#define SPAM 1', Constant('SPAM', '1')),
- ('#define SPAM() 1', Macro('SPAM', (), '1')),
- ('#define SPAM(a, b) a = b;', Macro('SPAM', ('a', 'b'), 'a = b;')),
- ('#if defined(SPAM)', IfDirective('if', 'defined(SPAM)')),
- ('#ifdef SPAM', IfDirective('ifdef', 'SPAM')),
- ('#ifndef SPAM', IfDirective('ifndef', 'SPAM')),
- ('#elseif defined(SPAM)', IfDirective('elseif', 'defined(SPAM)')),
- ('#else', OtherDirective('else', None)),
- ('#endif', OtherDirective('endif', None)),
- ('#error ...', OtherDirective('error', '...')),
- ('#warning ...', OtherDirective('warning', '...')),
- ('#__FILE__ ...', OtherDirective('__FILE__', '...')),
- ('#__LINE__ ...', OtherDirective('__LINE__', '...')),
- ('#__DATE__ ...', OtherDirective('__DATE__', '...')),
- ('#__TIME__ ...', OtherDirective('__TIME__', '...')),
- ('#__TIMESTAMP__ ...', OtherDirective('__TIMESTAMP__', '...')),
- ]
- for line, directive in tests:
- with self.subTest(line):
- self.reset()
- self.parsed = [
- directive,
- ]
- text = textwrap.dedent('''
- static int spam = 0;
- {}
- static char buffer[256];
- ''').strip().format(line)
- lines = text.strip().splitlines()
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, 'static int spam = 0;', None, ()),
- (2, line, directive, ()),
- ((3, 'static char buffer[256];', None, ('defined(SPAM)',))
- if directive.kind in ('if', 'ifdef', 'elseif')
- else (3, 'static char buffer[256];', None, ('! defined(SPAM)',))
- if directive.kind == 'ifndef'
- else (3, 'static char buffer[256];', None, ())),
- ])
- self.check_calls(
- ('_parse_directive', line),
- )
-
- def test_directive_whitespace(self):
- line = ' # define eggs ( a , b ) { a = b ; } '
- directive = Macro('eggs', ('a', 'b'), '{ a = b; }')
- self.parsed = [
- directive,
- ]
- lines = [line]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, line, directive, ()),
- ])
- self.check_calls(
- ('_parse_directive', '#define eggs ( a , b ) { a = b ; }'),
- )
-
- @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows')
- def test_split_lines(self):
- directive = Macro('eggs', ('a', 'b'), '{ a = b; }')
- self.parsed = [
- directive,
- ]
- text = textwrap.dedent(r'''
- static int spam = 0;
- #define eggs(a, b) \
- { \
- a = b; \
- }
- static char buffer[256];
- ''').strip()
- lines = [line + '\n' for line in text.splitlines()]
- lines[-1] = lines[-1][:-1]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, 'static int spam = 0;\n', None, ()),
- (5, '#define eggs(a, b) { a = b; }\n', directive, ()),
- (6, 'static char buffer[256];', None, ()),
- ])
- self.check_calls(
- ('_parse_directive', '#define eggs(a, b) { a = b; }'),
- )
-
- def test_nested_conditions(self):
- directives = [
- IfDirective('ifdef', 'SPAM'),
- IfDirective('if', 'SPAM == 1'),
- IfDirective('elseif', 'SPAM == 2'),
- OtherDirective('else', None),
- OtherDirective('endif', None),
- OtherDirective('endif', None),
- ]
- self.parsed = list(directives)
- text = textwrap.dedent(r'''
- static int spam = 0;
-
- #ifdef SPAM
- static int start = 0;
- # if SPAM == 1
- static char buffer[10];
- # elif SPAM == 2
- static char buffer[100];
- # else
- static char buffer[256];
- # endif
- static int end = 0;
- #endif
-
- static int eggs = 0;
- ''').strip()
- lines = [line for line in text.splitlines() if line.strip()]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, 'static int spam = 0;', None, ()),
- (2, '#ifdef SPAM', directives[0], ()),
- (3, 'static int start = 0;', None, ('defined(SPAM)',)),
- (4, '# if SPAM == 1', directives[1], ('defined(SPAM)',)),
- (5, 'static char buffer[10];', None, ('defined(SPAM)', 'SPAM == 1')),
- (6, '# elif SPAM == 2', directives[2], ('defined(SPAM)', 'SPAM == 1')),
- (7, 'static char buffer[100];', None, ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')),
- (8, '# else', directives[3], ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')),
- (9, 'static char buffer[256];', None, ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')),
- (10, '# endif', directives[4], ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')),
- (11, 'static int end = 0;', None, ('defined(SPAM)',)),
- (12, '#endif', directives[5], ('defined(SPAM)',)),
- (13, 'static int eggs = 0;', None, ()),
- ])
- self.check_calls(
- ('_parse_directive', '#ifdef SPAM'),
- ('_parse_directive', '#if SPAM == 1'),
- ('_parse_directive', '#elif SPAM == 2'),
- ('_parse_directive', '#else'),
- ('_parse_directive', '#endif'),
- ('_parse_directive', '#endif'),
- )
-
- def test_split_blocks(self):
- directives = [
- IfDirective('ifdef', 'SPAM'),
- OtherDirective('else', None),
- OtherDirective('endif', None),
- ]
- self.parsed = list(directives)
- text = textwrap.dedent(r'''
- void str_copy(char *buffer, *orig);
-
- int init(char *name) {
- static int initialized = 0;
- if (initialized) {
- return 0;
- }
- #ifdef SPAM
- static char buffer[10];
- str_copy(buffer, char);
- }
-
- void copy(char *buffer, *orig) {
- strncpy(buffer, orig, 9);
- buffer[9] = 0;
- }
-
- #else
- static char buffer[256];
- str_copy(buffer, char);
- }
-
- void copy(char *buffer, *orig) {
- strcpy(buffer, orig);
- }
-
- #endif
- ''').strip()
- lines = [line for line in text.splitlines() if line.strip()]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, 'void str_copy(char *buffer, *orig);', None, ()),
- (2, 'int init(char *name) {', None, ()),
- (3, ' static int initialized = 0;', None, ()),
- (4, ' if (initialized) {', None, ()),
- (5, ' return 0;', None, ()),
- (6, ' }', None, ()),
-
- (7, '#ifdef SPAM', directives[0], ()),
-
- (8, ' static char buffer[10];', None, ('defined(SPAM)',)),
- (9, ' str_copy(buffer, char);', None, ('defined(SPAM)',)),
- (10, '}', None, ('defined(SPAM)',)),
- (11, 'void copy(char *buffer, *orig) {', None, ('defined(SPAM)',)),
- (12, ' strncpy(buffer, orig, 9);', None, ('defined(SPAM)',)),
- (13, ' buffer[9] = 0;', None, ('defined(SPAM)',)),
- (14, '}', None, ('defined(SPAM)',)),
-
- (15, '#else', directives[1], ('defined(SPAM)',)),
-
- (16, ' static char buffer[256];', None, ('! (defined(SPAM))',)),
- (17, ' str_copy(buffer, char);', None, ('! (defined(SPAM))',)),
- (18, '}', None, ('! (defined(SPAM))',)),
- (19, 'void copy(char *buffer, *orig) {', None, ('! (defined(SPAM))',)),
- (20, ' strcpy(buffer, orig);', None, ('! (defined(SPAM))',)),
- (21, '}', None, ('! (defined(SPAM))',)),
-
- (22, '#endif', directives[2], ('! (defined(SPAM))',)),
- ])
- self.check_calls(
- ('_parse_directive', '#ifdef SPAM'),
- ('_parse_directive', '#else'),
- ('_parse_directive', '#endif'),
- )
-
- @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows')
- def test_basic(self):
- directives = [
- Include('<stdio.h>'),
- IfDirective('ifdef', 'SPAM'),
- IfDirective('if', '! defined(HAM) || !HAM'),
- Constant('HAM', '0'),
- IfDirective('elseif', 'HAM < 0'),
- Constant('HAM', '-1'),
- OtherDirective('else', None),
- OtherDirective('endif', None),
- OtherDirective('endif', None),
- IfDirective('if', 'defined(HAM) && (HAM < 0 || ! HAM)'),
- OtherDirective('undef', 'HAM'),
- OtherDirective('endif', None),
- IfDirective('ifndef', 'HAM'),
- OtherDirective('endif', None),
- ]
- self.parsed = list(directives)
- text = textwrap.dedent(r'''
- #include <stdio.h>
- print("begin");
- #ifdef SPAM
- print("spam");
- #if ! defined(HAM) || !HAM
- # DEFINE HAM 0
- #elseif HAM < 0
- # DEFINE HAM -1
- #else
- print("ham HAM");
- #endif
- #endif
-
- #if defined(HAM) && \
- (HAM < 0 || ! HAM)
- print("ham?");
- #undef HAM
- # endif
-
- #ifndef HAM
- print("no ham");
- #endif
- print("end");
- ''')[1:-1]
- lines = [line + '\n' for line in text.splitlines()]
- lines[-1] = lines[-1][:-1]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, '#include <stdio.h>\n', Include('<stdio.h>'), ()),
- (2, 'print("begin");\n', None, ()),
- #
- (3, '#ifdef SPAM\n',
- IfDirective('ifdef', 'SPAM'),
- ()),
- (4, ' print("spam");\n',
- None,
- ('defined(SPAM)',)),
- (5, ' #if ! defined(HAM) || !HAM\n',
- IfDirective('if', '! defined(HAM) || !HAM'),
- ('defined(SPAM)',)),
- (6, '# DEFINE HAM 0\n',
- Constant('HAM', '0'),
- ('defined(SPAM)', '! defined(HAM) || !HAM')),
- (7, ' #elseif HAM < 0\n',
- IfDirective('elseif', 'HAM < 0'),
- ('defined(SPAM)', '! defined(HAM) || !HAM')),
- (8, '# DEFINE HAM -1\n',
- Constant('HAM', '-1'),
- ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')),
- (9, ' #else\n',
- OtherDirective('else', None),
- ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')),
- (10, ' print("ham HAM");\n',
- None,
- ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')),
- (11, ' #endif\n',
- OtherDirective('endif', None),
- ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')),
- (12, '#endif\n',
- OtherDirective('endif', None),
- ('defined(SPAM)',)),
- #
- (13, '\n', None, ()),
- #
- (15, '#if defined(HAM) && (HAM < 0 || ! HAM)\n',
- IfDirective('if', 'defined(HAM) && (HAM < 0 || ! HAM)'),
- ()),
- (16, ' print("ham?");\n',
- None,
- ('defined(HAM) && (HAM < 0 || ! HAM)',)),
- (17, ' #undef HAM\n',
- OtherDirective('undef', 'HAM'),
- ('defined(HAM) && (HAM < 0 || ! HAM)',)),
- (18, '# endif\n',
- OtherDirective('endif', None),
- ('defined(HAM) && (HAM < 0 || ! HAM)',)),
- #
- (19, '\n', None, ()),
- #
- (20, '#ifndef HAM\n',
- IfDirective('ifndef', 'HAM'),
- ()),
- (21, ' print("no ham");\n',
- None,
- ('! defined(HAM)',)),
- (22, '#endif\n',
- OtherDirective('endif', None),
- ('! defined(HAM)',)),
- #
- (23, 'print("end");', None, ()),
- ])
-
- @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows')
- def test_typical(self):
- # We use Include/compile.h from commit 66c4f3f38b86. It has
- # a good enough mix of code without being too large.
- directives = [
- IfDirective('ifndef', 'Py_COMPILE_H'),
- Constant('Py_COMPILE_H', None),
-
- IfDirective('ifndef', 'Py_LIMITED_API'),
-
- Include('"code.h"'),
-
- IfDirective('ifdef', '__cplusplus'),
- OtherDirective('endif', None),
-
- Constant('PyCF_MASK', '(CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'),
- Constant('PyCF_MASK_OBSOLETE', '(CO_NESTED)'),
- Constant('PyCF_SOURCE_IS_UTF8', ' 0x0100'),
- Constant('PyCF_DONT_IMPLY_DEDENT', '0x0200'),
- Constant('PyCF_ONLY_AST', '0x0400'),
- Constant('PyCF_IGNORE_COOKIE', '0x0800'),
- Constant('PyCF_TYPE_COMMENTS', '0x1000'),
- Constant('PyCF_ALLOW_TOP_LEVEL_AWAIT', '0x2000'),
-
- IfDirective('ifndef', 'Py_LIMITED_API'),
- OtherDirective('endif', None),
-
- Constant('FUTURE_NESTED_SCOPES', '"nested_scopes"'),
- Constant('FUTURE_GENERATORS', '"generators"'),
- Constant('FUTURE_DIVISION', '"division"'),
- Constant('FUTURE_ABSOLUTE_IMPORT', '"absolute_import"'),
- Constant('FUTURE_WITH_STATEMENT', '"with_statement"'),
- Constant('FUTURE_PRINT_FUNCTION', '"print_function"'),
- Constant('FUTURE_UNICODE_LITERALS', '"unicode_literals"'),
- Constant('FUTURE_BARRY_AS_BDFL', '"barry_as_FLUFL"'),
- Constant('FUTURE_GENERATOR_STOP', '"generator_stop"'),
- Constant('FUTURE_ANNOTATIONS', '"annotations"'),
-
- Macro('PyAST_Compile', ('mod', 's', 'f', 'ar'), 'PyAST_CompileEx(mod, s, f, -1, ar)'),
-
- Constant('PY_INVALID_STACK_EFFECT', 'INT_MAX'),
-
- IfDirective('ifdef', '__cplusplus'),
- OtherDirective('endif', None),
-
- OtherDirective('endif', None), # ifndef Py_LIMITED_API
-
- Constant('Py_single_input', '256'),
- Constant('Py_file_input', '257'),
- Constant('Py_eval_input', '258'),
- Constant('Py_func_type_input', '345'),
-
- OtherDirective('endif', None), # ifndef Py_COMPILE_H
- ]
- self.parsed = list(directives)
- text = textwrap.dedent(r'''
- #ifndef Py_COMPILE_H
- #define Py_COMPILE_H
-
- #ifndef Py_LIMITED_API
- #include "code.h"
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /* Public interface */
- struct _node; /* Declare the existence of this type */
- PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
- /* XXX (ncoghlan): Unprefixed type name in a public API! */
-
- #define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
- CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
- CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
- CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)
- #define PyCF_MASK_OBSOLETE (CO_NESTED)
- #define PyCF_SOURCE_IS_UTF8 0x0100
- #define PyCF_DONT_IMPLY_DEDENT 0x0200
- #define PyCF_ONLY_AST 0x0400
- #define PyCF_IGNORE_COOKIE 0x0800
- #define PyCF_TYPE_COMMENTS 0x1000
- #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000
-
- #ifndef Py_LIMITED_API
- typedef struct {
- int cf_flags; /* bitmask of CO_xxx flags relevant to future */
- int cf_feature_version; /* minor Python version (PyCF_ONLY_AST) */
- } PyCompilerFlags;
- #endif
-
- /* Future feature support */
-
- typedef struct {
- int ff_features; /* flags set by future statements */
- int ff_lineno; /* line number of last future statement */
- } PyFutureFeatures;
-
- #define FUTURE_NESTED_SCOPES "nested_scopes"
- #define FUTURE_GENERATORS "generators"
- #define FUTURE_DIVISION "division"
- #define FUTURE_ABSOLUTE_IMPORT "absolute_import"
- #define FUTURE_WITH_STATEMENT "with_statement"
- #define FUTURE_PRINT_FUNCTION "print_function"
- #define FUTURE_UNICODE_LITERALS "unicode_literals"
- #define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"
- #define FUTURE_GENERATOR_STOP "generator_stop"
- #define FUTURE_ANNOTATIONS "annotations"
-
- struct _mod; /* Declare the existence of this type */
- #define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)
- PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(
- struct _mod *mod,
- const char *filename, /* decoded from the filesystem encoding */
- PyCompilerFlags *flags,
- int optimize,
- PyArena *arena);
- PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(
- struct _mod *mod,
- PyObject *filename,
- PyCompilerFlags *flags,
- int optimize,
- PyArena *arena);
- PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(
- struct _mod * mod,
- const char *filename /* decoded from the filesystem encoding */
- );
- PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(
- struct _mod * mod,
- PyObject *filename
- );
-
- /* _Py_Mangle is defined in compile.c */
- PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
-
- #define PY_INVALID_STACK_EFFECT INT_MAX
- PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg);
- PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump);
-
- PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif /* !Py_LIMITED_API */
-
- /* These definitions must match corresponding definitions in graminit.h. */
- #define Py_single_input 256
- #define Py_file_input 257
- #define Py_eval_input 258
- #define Py_func_type_input 345
-
- #endif /* !Py_COMPILE_H */
- ''').strip()
- lines = [line + '\n' for line in text.splitlines()]
- lines[-1] = lines[-1][:-1]
-
- results = list(
- iter_lines(lines, _parse_directive=self._parse_directive))
-
- self.assertEqual(results, [
- (1, '#ifndef Py_COMPILE_H\n',
- IfDirective('ifndef', 'Py_COMPILE_H'),
- ()),
- (2, '#define Py_COMPILE_H\n',
- Constant('Py_COMPILE_H', None),
- ('! defined(Py_COMPILE_H)',)),
- (3, '\n',
- None,
- ('! defined(Py_COMPILE_H)',)),
- (4, '#ifndef Py_LIMITED_API\n',
- IfDirective('ifndef', 'Py_LIMITED_API'),
- ('! defined(Py_COMPILE_H)',)),
- (5, '#include "code.h"\n',
- Include('"code.h"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (6, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (7, '#ifdef __cplusplus\n',
- IfDirective('ifdef', '__cplusplus'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (8, 'extern "C" {\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')),
- (9, '#endif\n',
- OtherDirective('endif', None),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')),
- (10, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (11, ' \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (12, 'struct _node; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (13, 'PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (14, ' \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (15, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (19, '#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)\n',
- Constant('PyCF_MASK', '(CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (20, '#define PyCF_MASK_OBSOLETE (CO_NESTED)\n',
- Constant('PyCF_MASK_OBSOLETE', '(CO_NESTED)'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (21, '#define PyCF_SOURCE_IS_UTF8 0x0100\n',
- Constant('PyCF_SOURCE_IS_UTF8', ' 0x0100'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (22, '#define PyCF_DONT_IMPLY_DEDENT 0x0200\n',
- Constant('PyCF_DONT_IMPLY_DEDENT', '0x0200'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (23, '#define PyCF_ONLY_AST 0x0400\n',
- Constant('PyCF_ONLY_AST', '0x0400'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (24, '#define PyCF_IGNORE_COOKIE 0x0800\n',
- Constant('PyCF_IGNORE_COOKIE', '0x0800'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (25, '#define PyCF_TYPE_COMMENTS 0x1000\n',
- Constant('PyCF_TYPE_COMMENTS', '0x1000'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (26, '#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000\n',
- Constant('PyCF_ALLOW_TOP_LEVEL_AWAIT', '0x2000'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (27, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (28, '#ifndef Py_LIMITED_API\n',
- IfDirective('ifndef', 'Py_LIMITED_API'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (29, 'typedef struct {\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')),
- (30, ' int cf_flags; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')),
- (31, ' int cf_feature_version; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')),
- (32, '} PyCompilerFlags;\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')),
- (33, '#endif\n',
- OtherDirective('endif', None),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')),
- (34, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (35, ' \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (36, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (37, 'typedef struct {\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (38, ' int ff_features; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (39, ' int ff_lineno; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (40, '} PyFutureFeatures;\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (41, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (42, '#define FUTURE_NESTED_SCOPES "nested_scopes"\n',
- Constant('FUTURE_NESTED_SCOPES', '"nested_scopes"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (43, '#define FUTURE_GENERATORS "generators"\n',
- Constant('FUTURE_GENERATORS', '"generators"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (44, '#define FUTURE_DIVISION "division"\n',
- Constant('FUTURE_DIVISION', '"division"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (45, '#define FUTURE_ABSOLUTE_IMPORT "absolute_import"\n',
- Constant('FUTURE_ABSOLUTE_IMPORT', '"absolute_import"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (46, '#define FUTURE_WITH_STATEMENT "with_statement"\n',
- Constant('FUTURE_WITH_STATEMENT', '"with_statement"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (47, '#define FUTURE_PRINT_FUNCTION "print_function"\n',
- Constant('FUTURE_PRINT_FUNCTION', '"print_function"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (48, '#define FUTURE_UNICODE_LITERALS "unicode_literals"\n',
- Constant('FUTURE_UNICODE_LITERALS', '"unicode_literals"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (49, '#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"\n',
- Constant('FUTURE_BARRY_AS_BDFL', '"barry_as_FLUFL"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (50, '#define FUTURE_GENERATOR_STOP "generator_stop"\n',
- Constant('FUTURE_GENERATOR_STOP', '"generator_stop"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (51, '#define FUTURE_ANNOTATIONS "annotations"\n',
- Constant('FUTURE_ANNOTATIONS', '"annotations"'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (52, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (53, 'struct _mod; \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (54, '#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)\n',
- Macro('PyAST_Compile', ('mod', 's', 'f', 'ar'), 'PyAST_CompileEx(mod, s, f, -1, ar)'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (55, 'PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (56, ' struct _mod *mod,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (57, ' const char *filename, \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (58, ' PyCompilerFlags *flags,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (59, ' int optimize,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (60, ' PyArena *arena);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (61, 'PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (62, ' struct _mod *mod,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (63, ' PyObject *filename,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (64, ' PyCompilerFlags *flags,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (65, ' int optimize,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (66, ' PyArena *arena);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (67, 'PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (68, ' struct _mod * mod,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (69, ' const char *filename \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (70, ' );\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (71, 'PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (72, ' struct _mod * mod,\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (73, ' PyObject *filename\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (74, ' );\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (75, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (76, ' \n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (77, 'PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (78, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (79, '#define PY_INVALID_STACK_EFFECT INT_MAX\n',
- Constant('PY_INVALID_STACK_EFFECT', 'INT_MAX'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (80, 'PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (81, 'PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (82, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (83, 'PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (84, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (85, '#ifdef __cplusplus\n',
- IfDirective('ifdef', '__cplusplus'),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (86, '}\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')),
- (87, '#endif\n',
- OtherDirective('endif', None),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')),
- (88, '\n',
- None,
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (89, '#endif \n',
- OtherDirective('endif', None),
- ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')),
- (90, '\n',
- None,
- ('! defined(Py_COMPILE_H)',)),
- (91, ' \n',
- None,
- ('! defined(Py_COMPILE_H)',)),
- (92, '#define Py_single_input 256\n',
- Constant('Py_single_input', '256'),
- ('! defined(Py_COMPILE_H)',)),
- (93, '#define Py_file_input 257\n',
- Constant('Py_file_input', '257'),
- ('! defined(Py_COMPILE_H)',)),
- (94, '#define Py_eval_input 258\n',
- Constant('Py_eval_input', '258'),
- ('! defined(Py_COMPILE_H)',)),
- (95, '#define Py_func_type_input 345\n',
- Constant('Py_func_type_input', '345'),
- ('! defined(Py_COMPILE_H)',)),
- (96, '\n',
- None,
- ('! defined(Py_COMPILE_H)',)),
- (97, '#endif ',
- OtherDirective('endif', None),
- ('! defined(Py_COMPILE_H)',)),
- ])
- self.check_calls(
- ('_parse_directive', '#ifndef Py_COMPILE_H'),
- ('_parse_directive', '#define Py_COMPILE_H'),
- ('_parse_directive', '#ifndef Py_LIMITED_API'),
- ('_parse_directive', '#include "code.h"'),
- ('_parse_directive', '#ifdef __cplusplus'),
- ('_parse_directive', '#endif'),
- ('_parse_directive', '#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'),
- ('_parse_directive', '#define PyCF_MASK_OBSOLETE (CO_NESTED)'),
- ('_parse_directive', '#define PyCF_SOURCE_IS_UTF8 0x0100'),
- ('_parse_directive', '#define PyCF_DONT_IMPLY_DEDENT 0x0200'),
- ('_parse_directive', '#define PyCF_ONLY_AST 0x0400'),
- ('_parse_directive', '#define PyCF_IGNORE_COOKIE 0x0800'),
- ('_parse_directive', '#define PyCF_TYPE_COMMENTS 0x1000'),
- ('_parse_directive', '#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000'),
- ('_parse_directive', '#ifndef Py_LIMITED_API'),
- ('_parse_directive', '#endif'),
- ('_parse_directive', '#define FUTURE_NESTED_SCOPES "nested_scopes"'),
- ('_parse_directive', '#define FUTURE_GENERATORS "generators"'),
- ('_parse_directive', '#define FUTURE_DIVISION "division"'),
- ('_parse_directive', '#define FUTURE_ABSOLUTE_IMPORT "absolute_import"'),
- ('_parse_directive', '#define FUTURE_WITH_STATEMENT "with_statement"'),
- ('_parse_directive', '#define FUTURE_PRINT_FUNCTION "print_function"'),
- ('_parse_directive', '#define FUTURE_UNICODE_LITERALS "unicode_literals"'),
- ('_parse_directive', '#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"'),
- ('_parse_directive', '#define FUTURE_GENERATOR_STOP "generator_stop"'),
- ('_parse_directive', '#define FUTURE_ANNOTATIONS "annotations"'),
- ('_parse_directive', '#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)'),
- ('_parse_directive', '#define PY_INVALID_STACK_EFFECT INT_MAX'),
- ('_parse_directive', '#ifdef __cplusplus'),
- ('_parse_directive', '#endif'),
- ('_parse_directive', '#endif'),
- ('_parse_directive', '#define Py_single_input 256'),
- ('_parse_directive', '#define Py_file_input 257'),
- ('_parse_directive', '#define Py_eval_input 258'),
- ('_parse_directive', '#define Py_func_type_input 345'),
- ('_parse_directive', '#endif'),
- )
-
-
-class ParseDirectiveTests(unittest.TestCase):
-
- def test_directives(self):
- tests = [
- # includes
- ('#include "internal/pycore_pystate.h"', Include('"internal/pycore_pystate.h"')),
- ('#include <stdio>', Include('<stdio>')),
-
- # defines
- ('#define SPAM int', Constant('SPAM', 'int')),
- ('#define SPAM', Constant('SPAM', '')),
- ('#define SPAM(x, y) run(x, y)', Macro('SPAM', ('x', 'y'), 'run(x, y)')),
- ('#undef SPAM', None),
-
- # conditionals
- ('#if SPAM', IfDirective('if', 'SPAM')),
- # XXX complex conditionls
- ('#ifdef SPAM', IfDirective('ifdef', 'SPAM')),
- ('#ifndef SPAM', IfDirective('ifndef', 'SPAM')),
- ('#elseif SPAM', IfDirective('elseif', 'SPAM')),
- # XXX complex conditionls
- ('#else', OtherDirective('else', '')),
- ('#endif', OtherDirective('endif', '')),
-
- # other
- ('#error oops!', None),
- ('#warning oops!', None),
- ('#pragma ...', None),
- ('#__FILE__ ...', None),
- ('#__LINE__ ...', None),
- ('#__DATE__ ...', None),
- ('#__TIME__ ...', None),
- ('#__TIMESTAMP__ ...', None),
-
- # extra whitespace
- (' # include <stdio> ', Include('<stdio>')),
- ('#else ', OtherDirective('else', '')),
- ('#endif ', OtherDirective('endif', '')),
- ('#define SPAM int ', Constant('SPAM', 'int')),
- ('#define SPAM ', Constant('SPAM', '')),
- ]
- for line, expected in tests:
- if expected is None:
- kind, _, text = line[1:].partition(' ')
- expected = OtherDirective(kind, text)
- with self.subTest(line):
- directive = parse_directive(line)
-
- self.assertEqual(directive, expected)
-
- def test_bad_directives(self):
- tests = [
- # valid directives with bad text
- '#define 123',
- '#else spam',
- '#endif spam',
- ]
- for kind in PreprocessorDirective.KINDS:
- # missing leading "#"
- tests.append(kind)
- if kind in ('else', 'endif'):
- continue
- # valid directives with missing text
- tests.append('#' + kind)
- tests.append('#' + kind + ' ')
- for line in tests:
- with self.subTest(line):
- with self.assertRaises(ValueError):
- parse_directive(line)
-
- def test_not_directives(self):
- tests = [
- '',
- ' ',
- 'directive',
- 'directive?',
- '???',
- ]
- for line in tests:
- with self.subTest(line):
- with self.assertRaises(ValueError):
- parse_directive(line)
-
-
-class ConstantTests(unittest.TestCase):
-
- def test_type(self):
- directive = Constant('SPAM', '123')
-
- self.assertIs(type(directive), Constant)
- self.assertIsInstance(directive, PreprocessorDirective)
-
- def test_attrs(self):
- d = Constant('SPAM', '123')
- kind, name, value = d.kind, d.name, d.value
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertEqual(value, '123')
-
- def test_text(self):
- tests = [
- (('SPAM', '123'), 'SPAM 123'),
- (('SPAM',), 'SPAM'),
- ]
- for args, expected in tests:
- with self.subTest(args):
- d = Constant(*args)
- text = d.text
-
- self.assertEqual(text, expected)
-
- def test_iter(self):
- kind, name, value = Constant('SPAM', '123')
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertEqual(value, '123')
-
- def test_defaults(self):
- kind, name, value = Constant('SPAM')
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertIs(value, None)
-
- def test_coerce(self):
- tests = []
- # coerced name, value
- for args in wrapped_arg_combos('SPAM', '123'):
- tests.append((args, ('SPAM', '123')))
- # missing name, value
- for name in ('', ' ', None, StrProxy(' '), ()):
- for value in ('', ' ', None, StrProxy(' '), ()):
- tests.append(
- ((name, value), (None, None)))
- # whitespace
- tests.extend([
- ((' SPAM ', ' 123 '), ('SPAM', '123')),
- ])
-
- for args, expected in tests:
- with self.subTest(args):
- d = Constant(*args)
-
- self.assertEqual(d[1:], expected)
- for i, exp in enumerate(expected, start=1):
- if exp is not None:
- self.assertIs(type(d[i]), str)
-
- def test_valid(self):
- tests = [
- ('SPAM', '123'),
- # unusual name
- ('_SPAM_', '123'),
- ('X_1', '123'),
- # unusual value
- ('SPAM', None),
- ]
- for args in tests:
- with self.subTest(args):
- directive = Constant(*args)
-
- directive.validate()
-
- def test_invalid(self):
- tests = [
- # invalid name
- ((None, '123'), TypeError),
- (('_', '123'), ValueError),
- (('1', '123'), ValueError),
- (('_1_', '123'), ValueError),
- # There is no invalid value (including None).
- ]
- for args, exctype in tests:
- with self.subTest(args):
- directive = Constant(*args)
-
- with self.assertRaises(exctype):
- directive.validate()
-
-
-class MacroTests(unittest.TestCase):
-
- def test_type(self):
- directive = Macro('SPAM', ('x', 'y'), '123')
-
- self.assertIs(type(directive), Macro)
- self.assertIsInstance(directive, PreprocessorDirective)
-
- def test_attrs(self):
- d = Macro('SPAM', ('x', 'y'), '123')
- kind, name, args, body = d.kind, d.name, d.args, d.body
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertEqual(args, ('x', 'y'))
- self.assertEqual(body, '123')
-
- def test_text(self):
- tests = [
- (('SPAM', ('x', 'y'), '123'), 'SPAM(x, y) 123'),
- (('SPAM', ('x', 'y'),), 'SPAM(x, y)'),
- ]
- for args, expected in tests:
- with self.subTest(args):
- d = Macro(*args)
- text = d.text
-
- self.assertEqual(text, expected)
-
- def test_iter(self):
- kind, name, args, body = Macro('SPAM', ('x', 'y'), '123')
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertEqual(args, ('x', 'y'))
- self.assertEqual(body, '123')
-
- def test_defaults(self):
- kind, name, args, body = Macro('SPAM', ('x', 'y'))
-
- self.assertEqual(kind, 'define')
- self.assertEqual(name, 'SPAM')
- self.assertEqual(args, ('x', 'y'))
- self.assertIs(body, None)
-
- def test_coerce(self):
- tests = []
- # coerce name and body
- for args in wrapped_arg_combos('SPAM', ('x', 'y'), '123'):
- tests.append(
- (args, ('SPAM', ('x', 'y'), '123')))
- # coerce args
- tests.extend([
- (('SPAM', 'x', '123'),
- ('SPAM', ('x',), '123')),
- (('SPAM', 'x,y', '123'),
- ('SPAM', ('x', 'y'), '123')),
- ])
- # coerce arg names
- for argnames in wrapped_arg_combos('x', 'y'):
- tests.append(
- (('SPAM', argnames, '123'),
- ('SPAM', ('x', 'y'), '123')))
- # missing name, body
- for name in ('', ' ', None, StrProxy(' '), ()):
- for argnames in (None, ()):
- for body in ('', ' ', None, StrProxy(' '), ()):
- tests.append(
- ((name, argnames, body),
- (None, (), None)))
- # missing args
- tests.extend([
- (('SPAM', None, '123'),
- ('SPAM', (), '123')),
- (('SPAM', (), '123'),
- ('SPAM', (), '123')),
- ])
- # missing arg names
- for arg in ('', ' ', None, StrProxy(' '), ()):
- tests.append(
- (('SPAM', (arg,), '123'),
- ('SPAM', (None,), '123')))
- tests.extend([
- (('SPAM', ('x', '', 'z'), '123'),
- ('SPAM', ('x', None, 'z'), '123')),
- ])
- # whitespace
- tests.extend([
- ((' SPAM ', (' x ', ' y '), ' 123 '),
- ('SPAM', ('x', 'y'), '123')),
- (('SPAM', 'x, y', '123'),
- ('SPAM', ('x', 'y'), '123')),
- ])
-
- for args, expected in tests:
- with self.subTest(args):
- d = Macro(*args)
-
- self.assertEqual(d[1:], expected)
- for i, exp in enumerate(expected, start=1):
- if i == 2:
- self.assertIs(type(d[i]), tuple)
- elif exp is not None:
- self.assertIs(type(d[i]), str)
-
- def test_init_bad_args(self):
- tests = [
- ('SPAM', StrProxy('x'), '123'),
- ('SPAM', object(), '123'),
- ]
- for args in tests:
- with self.subTest(args):
- with self.assertRaises(TypeError):
- Macro(*args)
-
- def test_valid(self):
- tests = [
- # unusual name
- ('SPAM', ('x', 'y'), 'run(x, y)'),
- ('_SPAM_', ('x', 'y'), 'run(x, y)'),
- ('X_1', ('x', 'y'), 'run(x, y)'),
- # unusual args
- ('SPAM', (), 'run(x, y)'),
- ('SPAM', ('_x_', 'y_1'), 'run(x, y)'),
- ('SPAM', 'x', 'run(x, y)'),
- ('SPAM', 'x, y', 'run(x, y)'),
- # unusual body
- ('SPAM', ('x', 'y'), None),
- ]
- for args in tests:
- with self.subTest(args):
- directive = Macro(*args)
-
- directive.validate()
-
- def test_invalid(self):
- tests = [
- # invalid name
- ((None, ('x', 'y'), '123'), TypeError),
- (('_', ('x', 'y'), '123'), ValueError),
- (('1', ('x', 'y'), '123'), ValueError),
- (('_1', ('x', 'y'), '123'), ValueError),
- # invalid args
- (('SPAM', (None, 'y'), '123'), ValueError),
- (('SPAM', ('x', '_'), '123'), ValueError),
- (('SPAM', ('x', '1'), '123'), ValueError),
- (('SPAM', ('x', '_1_'), '123'), ValueError),
- # There is no invalid body (including None).
- ]
- for args, exctype in tests:
- with self.subTest(args):
- directive = Macro(*args)
-
- with self.assertRaises(exctype):
- directive.validate()
-
-
-class IfDirectiveTests(unittest.TestCase):
-
- def test_type(self):
- directive = IfDirective('if', '1')
-
- self.assertIs(type(directive), IfDirective)
- self.assertIsInstance(directive, PreprocessorDirective)
-
- def test_attrs(self):
- d = IfDirective('if', '1')
- kind, condition = d.kind, d.condition
-
- self.assertEqual(kind, 'if')
- self.assertEqual(condition, '1')
- #self.assertEqual(condition, (ArithmeticCondition('1'),))
-
- def test_text(self):
- tests = [
- (('if', 'defined(SPAM) && 1 || (EGGS > 3 && defined(HAM))'),
- 'defined(SPAM) && 1 || (EGGS > 3 && defined(HAM))'),
- ]
- for kind in IfDirective.KINDS:
- tests.append(
- ((kind, 'SPAM'), 'SPAM'))
- for args, expected in tests:
- with self.subTest(args):
- d = IfDirective(*args)
- text = d.text
-
- self.assertEqual(text, expected)
-
- def test_iter(self):
- kind, condition = IfDirective('if', '1')
-
- self.assertEqual(kind, 'if')
- self.assertEqual(condition, '1')
- #self.assertEqual(condition, (ArithmeticCondition('1'),))
-
- #def test_complex_conditions(self):
- # ...
-
- def test_coerce(self):
- tests = []
- for kind in IfDirective.KINDS:
- if kind == 'ifdef':
- cond = 'defined(SPAM)'
- elif kind == 'ifndef':
- cond = '! defined(SPAM)'
- else:
- cond = 'SPAM'
- for args in wrapped_arg_combos(kind, 'SPAM'):
- tests.append((args, (kind, cond)))
- tests.extend([
- ((' ' + kind + ' ', ' SPAM '), (kind, cond)),
- ])
- for raw in ('', ' ', None, StrProxy(' '), ()):
- tests.append(((kind, raw), (kind, None)))
- for kind in ('', ' ', None, StrProxy(' '), ()):
- tests.append(((kind, 'SPAM'), (None, 'SPAM')))
- for args, expected in tests:
- with self.subTest(args):
- d = IfDirective(*args)
-
- self.assertEqual(tuple(d), expected)
- for i, exp in enumerate(expected):
- if exp is not None:
- self.assertIs(type(d[i]), str)
-
- def test_valid(self):
- tests = []
- for kind in IfDirective.KINDS:
- tests.extend([
- (kind, 'SPAM'),
- (kind, '_SPAM_'),
- (kind, 'X_1'),
- (kind, '()'),
- (kind, '--'),
- (kind, '???'),
- ])
- for args in tests:
- with self.subTest(args):
- directive = IfDirective(*args)
-
- directive.validate()
-
- def test_invalid(self):
- tests = []
- # kind
- tests.extend([
- ((None, 'SPAM'), TypeError),
- (('_', 'SPAM'), ValueError),
- (('-', 'SPAM'), ValueError),
- (('spam', 'SPAM'), ValueError),
- ])
- for kind in PreprocessorDirective.KINDS:
- if kind in IfDirective.KINDS:
- continue
- tests.append(
- ((kind, 'SPAM'), ValueError))
- # condition
- for kind in IfDirective.KINDS:
- tests.extend([
- ((kind, None), TypeError),
- # Any other condition is valid.
- ])
- for args, exctype in tests:
- with self.subTest(args):
- directive = IfDirective(*args)
-
- with self.assertRaises(exctype):
- directive.validate()
-
-
-class IncludeTests(unittest.TestCase):
-
- def test_type(self):
- directive = Include('<stdio>')
-
- self.assertIs(type(directive), Include)
- self.assertIsInstance(directive, PreprocessorDirective)
-
- def test_attrs(self):
- d = Include('<stdio>')
- kind, file, text = d.kind, d.file, d.text
-
- self.assertEqual(kind, 'include')
- self.assertEqual(file, '<stdio>')
- self.assertEqual(text, '<stdio>')
-
- def test_iter(self):
- kind, file = Include('<stdio>')
-
- self.assertEqual(kind, 'include')
- self.assertEqual(file, '<stdio>')
-
- def test_coerce(self):
- tests = []
- for arg, in wrapped_arg_combos('<stdio>'):
- tests.append((arg, '<stdio>'))
- tests.extend([
- (' <stdio> ', '<stdio>'),
- ])
- for arg in ('', ' ', None, StrProxy(' '), ()):
- tests.append((arg, None ))
- for arg, expected in tests:
- with self.subTest(arg):
- _, file = Include(arg)
-
- self.assertEqual(file, expected)
- if expected is not None:
- self.assertIs(type(file), str)
-
- def test_valid(self):
- tests = [
- '<stdio>',
- '"spam.h"',
- '"internal/pycore_pystate.h"',
- ]
- for arg in tests:
- with self.subTest(arg):
- directive = Include(arg)
-
- directive.validate()
-
- def test_invalid(self):
- tests = [
- (None, TypeError),
- # We currently don't check the file.
- ]
- for arg, exctype in tests:
- with self.subTest(arg):
- directive = Include(arg)
-
- with self.assertRaises(exctype):
- directive.validate()
-
-
-class OtherDirectiveTests(unittest.TestCase):
-
- def test_type(self):
- directive = OtherDirective('undef', 'SPAM')
-
- self.assertIs(type(directive), OtherDirective)
- self.assertIsInstance(directive, PreprocessorDirective)
-
- def test_attrs(self):
- d = OtherDirective('undef', 'SPAM')
- kind, text = d.kind, d.text
-
- self.assertEqual(kind, 'undef')
- self.assertEqual(text, 'SPAM')
-
- def test_iter(self):
- kind, text = OtherDirective('undef', 'SPAM')
-
- self.assertEqual(kind, 'undef')
- self.assertEqual(text, 'SPAM')
-
- def test_coerce(self):
- tests = []
- for kind in OtherDirective.KINDS:
- if kind in ('else', 'endif'):
- continue
- for args in wrapped_arg_combos(kind, '...'):
- tests.append((args, (kind, '...')))
- tests.extend([
- ((' ' + kind + ' ', ' ... '), (kind, '...')),
- ])
- for raw in ('', ' ', None, StrProxy(' '), ()):
- tests.append(((kind, raw), (kind, None)))
- for kind in ('else', 'endif'):
- for args in wrapped_arg_combos(kind, None):
- tests.append((args, (kind, None)))
- tests.extend([
- ((' ' + kind + ' ', None), (kind, None)),
- ])
- for kind in ('', ' ', None, StrProxy(' '), ()):
- tests.append(((kind, '...'), (None, '...')))
- for args, expected in tests:
- with self.subTest(args):
- d = OtherDirective(*args)
-
- self.assertEqual(tuple(d), expected)
- for i, exp in enumerate(expected):
- if exp is not None:
- self.assertIs(type(d[i]), str)
-
- def test_valid(self):
- tests = []
- for kind in OtherDirective.KINDS:
- if kind in ('else', 'endif'):
- continue
- tests.extend([
- (kind, '...'),
- (kind, '???'),
- (kind, 'SPAM'),
- (kind, '1 + 1'),
- ])
- for kind in ('else', 'endif'):
- tests.append((kind, None))
- for args in tests:
- with self.subTest(args):
- directive = OtherDirective(*args)
-
- directive.validate()
-
- def test_invalid(self):
- tests = []
- # kind
- tests.extend([
- ((None, '...'), TypeError),
- (('_', '...'), ValueError),
- (('-', '...'), ValueError),
- (('spam', '...'), ValueError),
- ])
- for kind in PreprocessorDirective.KINDS:
- if kind in OtherDirective.KINDS:
- continue
- tests.append(
- ((kind, None), ValueError))
- # text
- for kind in OtherDirective.KINDS:
- if kind in ('else', 'endif'):
- tests.extend([
- # Any text is invalid.
- ((kind, 'SPAM'), ValueError),
- ((kind, '...'), ValueError),
- ])
- else:
- tests.extend([
- ((kind, None), TypeError),
- # Any other text is valid.
- ])
- for args, exctype in tests:
- with self.subTest(args):
- directive = OtherDirective(*args)
-
- with self.assertRaises(exctype):
- directive.validate()
diff --git a/Lib/test/test_tools/test_c_analyzer/test_symbols/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_symbols/__init__.py
deleted file mode 100644
index bc502ef32d2..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_symbols/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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_symbols/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_symbols/test_info.py
deleted file mode 100644
index 1282a89718c..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_symbols/test_info.py
+++ /dev/null
@@ -1,192 +0,0 @@
-import string
-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.symbols.info import Symbol
-
-
-class SymbolTests(unittest.TestCase):
-
- VALID_ARGS = (
- ID('x/y/z/spam.c', 'func', 'eggs'),
- Symbol.KIND.VARIABLE,
- False,
- )
- VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS))
- VALID_EXPECTED = VALID_ARGS
-
- def test_init_typical_binary_local(self):
- id = ID(None, None, 'spam')
- symbol = Symbol(
- id=id,
- kind=Symbol.KIND.VARIABLE,
- external=False,
- )
-
- self.assertEqual(symbol, (
- id,
- Symbol.KIND.VARIABLE,
- False,
- ))
-
- def test_init_typical_binary_global(self):
- id = ID('Python/ceval.c', None, 'spam')
- symbol = Symbol(
- id=id,
- kind=Symbol.KIND.VARIABLE,
- external=False,
- )
-
- self.assertEqual(symbol, (
- id,
- Symbol.KIND.VARIABLE,
- False,
- ))
-
- def test_init_coercion(self):
- tests = [
- ('str subclass',
- dict(
- id=PseudoStr('eggs'),
- kind=PseudoStr('variable'),
- external=0,
- ),
- (ID(None, None, 'eggs'),
- Symbol.KIND.VARIABLE,
- False,
- )),
- ('with filename',
- dict(
- id=('x/y/z/spam.c', 'eggs'),
- kind=PseudoStr('variable'),
- external=0,
- ),
- (ID('x/y/z/spam.c', None, 'eggs'),
- Symbol.KIND.VARIABLE,
- False,
- )),
- ('non-str 1',
- dict(
- id=('a', 'b', 'c'),
- kind=StrProxy('variable'),
- external=0,
- ),
- (ID('a', 'b', 'c'),
- Symbol.KIND.VARIABLE,
- False,
- )),
- ('non-str 2',
- dict(
- id=('a', 'b', 'c'),
- kind=Object(),
- external=0,
- ),
- (ID('a', 'b', 'c'),
- '<object>',
- False,
- )),
- ]
- for summary, kwargs, expected in tests:
- with self.subTest(summary):
- symbol = Symbol(**kwargs)
-
- for field in Symbol._fields:
- value = getattr(symbol, field)
- if field == 'external':
- self.assertIs(type(value), bool)
- elif field == 'id':
- self.assertIs(type(value), ID)
- else:
- self.assertIs(type(value), str)
- self.assertEqual(tuple(symbol), expected)
-
- def test_init_all_missing(self):
- id = ID(None, None, 'spam')
-
- symbol = Symbol(id)
-
- self.assertEqual(symbol, (
- id,
- Symbol.KIND.VARIABLE,
- None,
- ))
-
- def test_fields(self):
- id = ID('z', 'x', 'a')
-
- symbol = Symbol(id, 'b', False)
-
- self.assertEqual(symbol.id, id)
- self.assertEqual(symbol.kind, 'b')
- self.assertIs(symbol.external, False)
-
- def test___getattr__(self):
- id = ID('z', 'x', 'a')
- symbol = Symbol(id, 'b', False)
-
- filename = symbol.filename
- funcname = symbol.funcname
- name = symbol.name
-
- self.assertEqual(filename, 'z')
- self.assertEqual(funcname, 'x')
- self.assertEqual(name, 'a')
-
- def test_validate_typical(self):
- id = ID('z', 'x', 'a')
-
- symbol = Symbol(
- id=id,
- kind=Symbol.KIND.VARIABLE,
- external=False,
- )
-
- symbol.validate() # This does not fail.
-
- def test_validate_missing_field(self):
- for field in Symbol._fields:
- with self.subTest(field):
- symbol = Symbol(**self.VALID_KWARGS)
- symbol = symbol._replace(**{field: None})
-
- with self.assertRaises(TypeError):
- symbol.validate()
-
- def test_validate_bad_field(self):
- badch = tuple(c for c in string.punctuation + string.digits)
- notnames = (
- '1a',
- 'a.b',
- 'a-b',
- '&a',
- 'a++',
- ) + badch
- tests = [
- ('id', notnames),
- ('kind', ('bogus',)),
- ]
- seen = set()
- for field, invalid in tests:
- for value in invalid:
- if field != 'kind':
- seen.add(value)
- with self.subTest(f'{field}={value!r}'):
- symbol = Symbol(**self.VALID_KWARGS)
- symbol = symbol._replace(**{field: value})
-
- with self.assertRaises(ValueError):
- symbol.validate()
-
- for field, invalid in tests:
- if field == 'kind':
- continue
- valid = seen - set(invalid)
- for value in valid:
- with self.subTest(f'{field}={value!r}'):
- symbol = Symbol(**self.VALID_KWARGS)
- symbol = symbol._replace(**{field: value})
-
- symbol.validate() # This does not fail.
diff --git a/Lib/test/test_tools/test_c_analyzer/test_variables/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_variables/__init__.py
deleted file mode 100644
index bc502ef32d2..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_variables/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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_variables/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_variables/test_find.py
deleted file mode 100644
index 7a13cf3f5bf..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_variables/test_find.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.variables import info
- from c_analyzer.variables.find import (
- vars_from_binary,
- )
-
-
-class _Base(unittest.TestCase):
-
- maxDiff = None
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
-
-class VarsFromBinaryTests(_Base):
-
- _return_iter_vars = ()
- _return_get_symbol_resolver = None
-
- def setUp(self):
- super().setUp()
-
- self.kwargs = dict(
- _iter_vars=self._iter_vars,
- _get_symbol_resolver=self._get_symbol_resolver,
- )
-
- def _iter_vars(self, binfile, resolve, handle_id):
- self.calls.append(('_iter_vars', (binfile, resolve, handle_id)))
- return [(v, v.id) for v in self._return_iter_vars]
-
- def _get_symbol_resolver(self, known=None, dirnames=(), *,
- handle_var,
- filenames=None,
- check_filename=None,
- perfilecache=None,
- ):
- self.calls.append(('_get_symbol_resolver',
- (known, dirnames, handle_var, filenames,
- check_filename, perfilecache)))
- return self._return_get_symbol_resolver
-
- def test_typical(self):
- resolver = self._return_get_symbol_resolver = object()
- variables = self._return_iter_vars = [
- 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/spam.c', 'func2', 'var4', 'const char *'),
- info.Variable.from_parts('dir1/eggs.c', None, 'var1', 'static int'),
- info.Variable.from_parts('dir1/eggs.c', 'func1', 'var2', 'static char *'),
- ]
- known = object()
- filenames = object()
-
- found = list(vars_from_binary('python',
- known=known,
- filenames=filenames,
- **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/spam.c', 'func2', 'var4', 'const char *'),
- info.Variable.from_parts('dir1/eggs.c', None, 'var1', 'static int'),
- info.Variable.from_parts('dir1/eggs.c', 'func1', 'var2', 'static char *'),
- ])
- self.assertEqual(self.calls, [
- ('_get_symbol_resolver', (filenames, known, info.Variable.from_id, None, None, {})),
- ('_iter_vars', ('python', resolver, None)),
- ])
-
-# self._return_iter_symbols = [
-# s_info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False),
-# s_info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False),
-# s_info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False),
-# s_info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True),
-# s_info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False),
-# s_info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False),
-# s_info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True),
-# s_info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False),
-# s_info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False),
-# s_info.Symbol(('dir1/eggs.c', '???', 'var2'), 'variable', False),
-# s_info.Symbol(('???', None, 'var_x'), 'variable', False),
-# s_info.Symbol(('???', '???', 'var_y'), 'variable', False),
-# s_info.Symbol((None, None, '???'), 'other', False),
-# ]
-# known = object()
-#
-# vars_from_binary('python', knownvars=known, **this.kwargs)
-# found = list(globals_from_symbols(['dir1'], self.iter_symbols))
-#
-# self.assertEqual(found, [
-# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'),
-# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'),
-# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'),
-# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'),
-# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'),
-# ])
-# self.assertEqual(self.calls, [
-# ('iter_symbols', (['dir1'],)),
-# ])
-#
-# def test_no_symbols(self):
-# self._return_iter_symbols = []
-#
-# found = list(globals_from_symbols(['dir1'], self.iter_symbols))
-#
-# self.assertEqual(found, [])
-# self.assertEqual(self.calls, [
-# ('iter_symbols', (['dir1'],)),
-# ])
-
- # XXX need functional test
diff --git a/Lib/test/test_tools/test_c_analyzer/test_variables/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_variables/test_info.py
deleted file mode 100644
index d424d8eebb8..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_variables/test_info.py
+++ /dev/null
@@ -1,244 +0,0 @@
-import string
-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 UNKNOWN, ID
- from c_analyzer.variables.info import (
- normalize_vartype, Variable
- )
-
-
-class NormalizeVartypeTests(unittest.TestCase):
-
- def test_basic(self):
- tests = [
- (None, None),
- ('', ''),
- ('int', 'int'),
- (PseudoStr('int'), 'int'),
- (StrProxy('int'), 'int'),
- ]
- for vartype, expected in tests:
- with self.subTest(vartype):
- normalized = normalize_vartype(vartype)
-
- self.assertEqual(normalized, expected)
-
-
-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):
- 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'),
- storage,
- 'int',
- ))
-
- def test_init_typical_local(self):
- 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',
- ))
-
- def test_init_all_missing(self):
- for value in ('', None):
- 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):
- id = ID('x/y/z/spam.c', 'func', 'spam')
- tests = [
- ('str subclass',
- dict(
- id=(
- PseudoStr('x/y/z/spam.c'),
- 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,
- storage=('a', 'b', 'c'),
- vartype=('x', 'y', 'z'),
- ),
- (id,
- "('a', 'b', 'c')",
- "('x', 'y', 'z')",
- )),
- ]
- for summary, kwargs, expected in tests:
- with self.subTest(summary):
- static = Variable(**kwargs)
-
- for field in Variable._fields:
- value = getattr(static, field)
- if field == 'id':
- self.assertIs(type(value), ID)
- else:
- self.assertIs(type(value), str)
- self.assertEqual(tuple(static), expected)
-
- def test_iterable(self):
- static = Variable(**self.VALID_KWARGS)
-
- id, storage, vartype = static
-
- 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', 'y')
-
- self.assertEqual(static.id, ('a', 'b', 'z'))
- self.assertEqual(static.storage, 'x')
- self.assertEqual(static.vartype, 'y')
-
- def test___getattr__(self):
- 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):
- 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.
-
- def test_validate_missing_field(self):
- for field in Variable._fields:
- with self.subTest(field):
- static = Variable(**self.VALID_KWARGS)
- static = static._replace(**{field: None})
-
- 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)
- notnames = (
- '1a',
- 'a.b',
- 'a-b',
- '&a',
- 'a++',
- ) + badch
- tests = [
- ('id', ()), # Any non-empty str is okay.
- ('storage', ('external', 'global') + notnames),
- ('vartype', ()), # Any non-empty str is okay.
- ]
- seen = set()
- for field, invalid in tests:
- for value in invalid:
- seen.add(value)
- with self.subTest(f'{field}={value!r}'):
- static = Variable(**self.VALID_KWARGS)
- static = static._replace(**{field: value})
-
- with self.assertRaises(ValueError):
- 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}'):
- static = Variable(**self.VALID_KWARGS)
- static = static._replace(**{field: value})
-
- static.validate() # This does not fail.
diff --git a/Lib/test/test_tools/test_c_analyzer/test_variables/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_variables/test_known.py
deleted file mode 100644
index 49ff45c6d1b..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/test_variables/test_known.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import re
-import textwrap
-import unittest
-
-from .. import tool_imports_for_tests
-with tool_imports_for_tests():
- from c_analyzer.common.info import ID
- from c_analyzer.variables.info import Variable
- from c_analyzer.variables.known import (
- read_file,
- from_file,
- )
-
-class _BaseTests(unittest.TestCase):
-
- maxDiff = None
-
- @property
- def calls(self):
- try:
- return self._calls
- except AttributeError:
- self._calls = []
- return self._calls
-
-
-class ReadFileTests(_BaseTests):
-
- _return_read_tsv = ()
-
- def _read_tsv(self, *args):
- self.calls.append(('_read_tsv', args))
- return self._return_read_tsv
-
- def test_typical(self):
- lines = textwrap.dedent('''
- filename funcname name kind declaration
- file1.c - var1 variable static int
- file1.c func1 local1 variable static int
- file1.c - var2 variable int
- file1.c func2 local2 variable char *
- file2.c - var1 variable char *
- ''').strip().splitlines()
- lines = [re.sub(r'\s+', '\t', line, 4) for line in lines]
- self._return_read_tsv = [tuple(v.strip() for v in line.split('\t'))
- for line in lines[1:]]
-
- known = list(read_file('known.tsv', _read_tsv=self._read_tsv))
-
- self.assertEqual(known, [
- ('variable', ID('file1.c', '', 'var1'), 'static int'),
- ('variable', ID('file1.c', 'func1', 'local1'), 'static int'),
- ('variable', ID('file1.c', '', 'var2'), 'int'),
- ('variable', ID('file1.c', 'func2', 'local2'), 'char *'),
- ('variable', ID('file2.c', '', 'var1'), 'char *'),
- ])
- self.assertEqual(self.calls, [
- ('_read_tsv',
- ('known.tsv', 'filename\tfuncname\tname\tkind\tdeclaration')),
- ])
-
- def test_empty(self):
- self._return_read_tsv = []
-
- known = list(read_file('known.tsv', _read_tsv=self._read_tsv))
-
- self.assertEqual(known, [])
- self.assertEqual(self.calls, [
- ('_read_tsv', ('known.tsv', 'filename\tfuncname\tname\tkind\tdeclaration')),
- ])
-
-
-class FromFileTests(_BaseTests):
-
- _return_read_file = ()
- _return_handle_var = ()
-
- def _read_file(self, infile):
- self.calls.append(('_read_file', (infile,)))
- return iter(self._return_read_file)
-
- def _handle_var(self, varid, decl):
- self.calls.append(('_handle_var', (varid, decl)))
- var = self._return_handle_var.pop(0)
- return var
-
- def test_typical(self):
- expected = [
- Variable.from_parts('file1.c', '', 'var1', 'static int'),
- Variable.from_parts('file1.c', 'func1', 'local1', 'static int'),
- Variable.from_parts('file1.c', '', 'var2', 'int'),
- Variable.from_parts('file1.c', 'func2', 'local2', 'char *'),
- Variable.from_parts('file2.c', '', 'var1', 'char *'),
- ]
- self._return_read_file = [('variable', v.id, v.vartype)
- for v in expected]
-# ('variable', ID('file1.c', '', 'var1'), 'static int'),
-# ('variable', ID('file1.c', 'func1', 'local1'), 'static int'),
-# ('variable', ID('file1.c', '', 'var2'), 'int'),
-# ('variable', ID('file1.c', 'func2', 'local2'), 'char *'),
-# ('variable', ID('file2.c', '', 'var1'), 'char *'),
-# ]
- self._return_handle_var = list(expected) # a copy
-
- known = from_file('known.tsv',
- handle_var=self._handle_var,
- _read_file=self._read_file,
- )
-
- self.assertEqual(known, {
- 'variables': {v.id: v for v in expected},
- })
-# Variable.from_parts('file1.c', '', 'var1', 'static int'),
-# Variable.from_parts('file1.c', 'func1', 'local1', 'static int'),
-# Variable.from_parts('file1.c', '', 'var2', 'int'),
-# Variable.from_parts('file1.c', 'func2', 'local2', 'char *'),
-# Variable.from_parts('file2.c', '', 'var1', 'char *'),
-# ]},
-# })
- self.assertEqual(self.calls, [
- ('_read_file', ('known.tsv',)),
- *[('_handle_var', (v.id, v.vartype))
- for v in expected],
- ])
-
- def test_empty(self):
- self._return_read_file = []
-
- known = from_file('known.tsv',
- handle_var=self._handle_var,
- _read_file=self._read_file,
- )
-
- self.assertEqual(known, {
- 'variables': {},
- })
- self.assertEqual(self.calls, [
- ('_read_file', ('known.tsv',)),
- ])
diff --git a/Lib/test/test_tools/test_c_analyzer/util.py b/Lib/test/test_tools/test_c_analyzer/util.py
deleted file mode 100644
index ba73b0a4b5f..00000000000
--- a/Lib/test/test_tools/test_c_analyzer/util.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import itertools
-
-
-class PseudoStr(str):
- pass
-
-
-class StrProxy:
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return self.value
- def __bool__(self):
- return bool(self.value)
-
-
-class Object:
- def __repr__(self):
- return '<object>'
-
-
-def wrapped_arg_combos(*args,
- wrappers=(PseudoStr, StrProxy),
- skip=(lambda w, i, v: not isinstance(v, str)),
- ):
- """Yield every possible combination of wrapped items for the given args.
-
- Effectively, the wrappers are applied to the args according to the
- powerset of the args indicies. So the result includes the args
- completely unwrapped.
-
- If "skip" is supplied (default is to skip all non-str values) and
- it returns True for a given arg index/value then that arg will
- remain unwrapped,
-
- Only unique results are returned. If an arg was skipped for one
- of the combinations then it could end up matching one of the other
- combinations. In that case only one of them will be yielded.
- """
- if not args:
- return
- indices = list(range(len(args)))
- # The powerset (from recipe in the itertools docs).
- combos = itertools.chain.from_iterable(itertools.combinations(indices, r)
- for r in range(len(indices)+1))
- seen = set()
- for combo in combos:
- for wrap in wrappers:
- indexes = []
- applied = list(args)
- for i in combo:
- arg = args[i]
- if skip and skip(wrap, i, arg):
- continue
- indexes.append(i)
- applied[i] = wrap(arg)
- key = (wrap, tuple(indexes))
- if key not in seen:
- yield tuple(applied)
- seen.add(key)