diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-08-06 15:06:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-06 15:06:14 (GMT) |
commit | d1c5e278a1a2458bc5efcdc300c17f9e39a59b6c (patch) | |
tree | a796feb2459ee37bb159ab2d812ab56a006c7121 /Lib/test/test_getargs2.py | |
parent | 7e4ff9796cb2c5b64307a2bd928e35930e3f1b2a (diff) | |
download | cpython-d1c5e278a1a2458bc5efcdc300c17f9e39a59b6c.zip cpython-d1c5e278a1a2458bc5efcdc300c17f9e39a59b6c.tar.gz cpython-d1c5e278a1a2458bc5efcdc300c17f9e39a59b6c.tar.bz2 |
[2.7] bpo-34272: Move argument parsing tests from test_capi to test_getargs2. (GH-8567). (GH-8691)
(cherry picked from commit 8f7bb100d0fa7fb2714f3953b5b627878277c7c6)
Diffstat (limited to 'Lib/test/test_getargs2.py')
-rw-r--r-- | Lib/test/test_getargs2.py | 146 |
1 files changed, 139 insertions, 7 deletions
diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index e0efcaa..7f819fb 100644 --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -1,9 +1,10 @@ import unittest import math +import string import sys from test import test_support # Skip this test if the _testcapi module isn't available. -test_support.import_module('_testcapi') +_testcapi = test_support.import_module('_testcapi') from _testcapi import getargs_keywords import warnings @@ -799,12 +800,6 @@ class Unicode_TestCase(unittest.TestCase): self.assertRaises(TypeError, getargs_u_hash, None) -def test_main(): - tests = [Signed_TestCase, Unsigned_TestCase, LongLong_TestCase, - Tuple_TestCase, Keywords_TestCase, - Bytes_TestCase, String_TestCase, Unicode_TestCase] - test_support.run_unittest(*tests) - class Object_TestCase(unittest.TestCase): def test_S(self): from _testcapi import getargs_S @@ -840,5 +835,142 @@ class Object_TestCase(unittest.TestCase): self.assertRaises(TypeError, getargs_U, buffer(obj)) +class SkipitemTest(unittest.TestCase): + + def test_skipitem(self): + """ + If this test failed, you probably added a new "format unit" + in Python/getargs.c, but neglected to update our poor friend + skipitem() in the same file. (If so, shame on you!) + + With a few exceptions**, this function brute-force tests all + printable ASCII*** characters (32 to 126 inclusive) as format units, + checking to see that PyArg_ParseTupleAndKeywords() return consistent + errors both when the unit is attempted to be used and when it is + skipped. If the format unit doesn't exist, we'll get one of two + specific error messages (one for used, one for skipped); if it does + exist we *won't* get that error--we'll get either no error or some + other error. If we get the specific "does not exist" error for one + test and not for the other, there's a mismatch, and the test fails. + + ** Some format units have special funny semantics and it would + be difficult to accommodate them here. Since these are all + well-established and properly skipped in skipitem() we can + get away with not testing them--this test is really intended + to catch *new* format units. + + *** Python C source files must be ASCII. Therefore it's impossible + to have non-ASCII format units. + + """ + empty_tuple = () + tuple_1 = (0,) + dict_b = {'b':1} + keywords = ["a", "b"] + + for i in range(32, 127): + c = chr(i) + + # skip parentheses, the error reporting is inconsistent about them + # skip 'e', it's always a two-character code + # skip '|', it doesn't represent arguments anyway + if c in '()e|': + continue + + # test the format unit when not skipped + format = c + "i" + try: + _testcapi.parse_tuple_and_keywords(tuple_1, dict_b, + format, keywords) + when_not_skipped = False + except TypeError as e: + s = "argument 1 (impossible<bad format char>)" + when_not_skipped = (str(e) == s) + except RuntimeError: + when_not_skipped = False + + # test the format unit when skipped + optional_format = "|" + format + try: + _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b, + optional_format, keywords) + when_skipped = False + except RuntimeError as e: + s = "impossible<bad format char>: '{}'".format(format) + when_skipped = (str(e) == s) + + message = ("test_skipitem_parity: " + "detected mismatch between convertsimple and skipitem " + "for format unit '{}' ({}), not skipped {}, skipped {}".format( + c, i, when_skipped, when_not_skipped)) + self.assertIs(when_skipped, when_not_skipped, message) + + def test_skipitem_with_suffix(self): + parse = _testcapi.parse_tuple_and_keywords + empty_tuple = () + tuple_1 = (0,) + dict_b = {'b':1} + keywords = ["a", "b"] + + supported = ('s#', 's*', 'z#', 'z*', 'u#', 't#', 'w#', 'w*') + for c in string.ascii_letters: + for c2 in '#*': + f = c + c2 + optional_format = "|" + f + "i" + if f in supported: + parse(empty_tuple, dict_b, optional_format, keywords) + else: + with self.assertRaisesRegexp((RuntimeError, TypeError), + 'impossible<bad format char>'): + parse(empty_tuple, dict_b, optional_format, keywords) + + for c in map(chr, range(32, 128)): + f = 'e' + c + optional_format = "|" + f + "i" + if c in 'st': + parse(empty_tuple, dict_b, optional_format, keywords) + else: + with self.assertRaisesRegexp(RuntimeError, + 'impossible<bad format char>'): + parse(empty_tuple, dict_b, optional_format, keywords) + + +class ParseTupleAndKeywords_Test(unittest.TestCase): + + def test_parse_tuple_and_keywords(self): + # Test handling errors in the parse_tuple_and_keywords helper itself + self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords, + (), {}, 42, []) + self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, + (), {}, '', 42) + self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, + (), {}, '', [''] * 42) + self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords, + (), {}, '', [42]) + + def test_bad_use(self): + # Test handling invalid format and keywords in + # PyArg_ParseTupleAndKeywords() + self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '||O', ['a']) + self.assertRaises(RuntimeError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '|O', ['a', 'b']) + self.assertRaises(RuntimeError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '|OO', ['a']) + + +class Test_testcapi(unittest.TestCase): + locals().update((name, getattr(_testcapi, name)) + for name in dir(_testcapi) + if name.startswith('test_') and name.endswith('_code')) + + +def test_main(): + tests = [Signed_TestCase, Unsigned_TestCase, LongLong_TestCase, + Tuple_TestCase, Keywords_TestCase, + Bytes_TestCase, String_TestCase, Unicode_TestCase, + SkipitemTest, ParseTupleAndKeywords_Test, Test_testcapi] + test_support.run_unittest(*tests) + if __name__ == "__main__": test_main() |