diff options
author | Eugene Triguba <eugenetriguba@gmail.com> | 2024-05-21 22:36:01 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-22 04:36:01 +0200 |
commit | 73ab83b27f105a4509046ce26e35f20d66625195 (patch) | |
tree | bcb20b17d09ee4cb329abdebf70d632682e51b9f /Lib/test/test_pyrepl/test_keymap.py | |
parent | c886bece3b3a49f8a0f188aecfc1d6ff89d281e6 (diff) | |
download | cpython-73ab83b27f105a4509046ce26e35f20d66625195.tar.gz cpython-73ab83b27f105a4509046ce26e35f20d66625195.zip |
gh-119357: Increase test coverage for keymap in _pyrepl (#119358)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
Diffstat (limited to 'Lib/test/test_pyrepl/test_keymap.py')
-rw-r--r-- | Lib/test/test_pyrepl/test_keymap.py | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/Lib/test/test_pyrepl/test_keymap.py b/Lib/test/test_pyrepl/test_keymap.py index 419f1643030..2c97066b2c7 100644 --- a/Lib/test/test_pyrepl/test_keymap.py +++ b/Lib/test/test_pyrepl/test_keymap.py @@ -1,41 +1,78 @@ +import string import unittest -from _pyrepl.keymap import parse_keys, compile_keymap +from _pyrepl.keymap import _keynames, _escapes, parse_keys, compile_keymap, KeySpecError class TestParseKeys(unittest.TestCase): def test_single_character(self): - self.assertEqual(parse_keys("a"), ["a"]) - self.assertEqual(parse_keys("b"), ["b"]) - self.assertEqual(parse_keys("1"), ["1"]) + """Ensure that single ascii characters or single digits are parsed as single characters.""" + test_cases = [(key, [key]) for key in string.ascii_letters + string.digits] + for test_key, expected_keys in test_cases: + with self.subTest(f"{test_key} should be parsed as {expected_keys}"): + self.assertEqual(parse_keys(test_key), expected_keys) + + def test_keynames(self): + """Ensure that keynames are parsed to their corresponding mapping. + + A keyname is expected to be of the following form: \\<keyname> such as \\<left> + which would get parsed as "left". + """ + test_cases = [(f"\\<{keyname}>", [parsed_keyname]) for keyname, parsed_keyname in _keynames.items()] + for test_key, expected_keys in test_cases: + with self.subTest(f"{test_key} should be parsed as {expected_keys}"): + self.assertEqual(parse_keys(test_key), expected_keys) def test_escape_sequences(self): - self.assertEqual(parse_keys("\\n"), ["\n"]) - self.assertEqual(parse_keys("\\t"), ["\t"]) - self.assertEqual(parse_keys("\\\\"), ["\\"]) - self.assertEqual(parse_keys("\\'"), ["'"]) - self.assertEqual(parse_keys('\\"'), ['"']) + """Ensure that escaping sequences are parsed to their corresponding mapping.""" + test_cases = [(f"\\{escape}", [parsed_escape]) for escape, parsed_escape in _escapes.items()] + for test_key, expected_keys in test_cases: + with self.subTest(f"{test_key} should be parsed as {expected_keys}"): + self.assertEqual(parse_keys(test_key), expected_keys) def test_control_sequences(self): - self.assertEqual(parse_keys("\\C-a"), ["\x01"]) - self.assertEqual(parse_keys("\\C-b"), ["\x02"]) - self.assertEqual(parse_keys("\\C-c"), ["\x03"]) + """Ensure that supported control sequences are parsed successfully.""" + keys = ["@", "[", "]", "\\", "^", "_", "\\<space>", "\\<delete>"] + keys.extend(string.ascii_letters) + test_cases = [(f"\\C-{key}", chr(ord(key) & 0x1F)) for key in []] + for test_key, expected_keys in test_cases: + with self.subTest(f"{test_key} should be parsed as {expected_keys}"): + self.assertEqual(parse_keys(test_key), expected_keys) def test_meta_sequences(self): self.assertEqual(parse_keys("\\M-a"), ["\033", "a"]) self.assertEqual(parse_keys("\\M-b"), ["\033", "b"]) self.assertEqual(parse_keys("\\M-c"), ["\033", "c"]) - def test_keynames(self): - self.assertEqual(parse_keys("\\<up>"), ["up"]) - self.assertEqual(parse_keys("\\<down>"), ["down"]) - self.assertEqual(parse_keys("\\<left>"), ["left"]) - self.assertEqual(parse_keys("\\<right>"), ["right"]) - def test_combinations(self): self.assertEqual(parse_keys("\\C-a\\n\\<up>"), ["\x01", "\n", "up"]) self.assertEqual(parse_keys("\\M-a\\t\\<down>"), ["\033", "a", "\t", "down"]) + def test_keyspec_errors(self): + cases = [ + ("\\Ca", "\\C must be followed by `-'"), + ("\\ca", "\\C must be followed by `-'"), + ("\\C-\\C-", "doubled \\C-"), + ("\\Ma", "\\M must be followed by `-'"), + ("\\ma", "\\M must be followed by `-'"), + ("\\M-\\M-", "doubled \\M-"), + ("\\<left", "unterminated \\<"), + ("\\<unsupported>", "unrecognised keyname"), + ("\\大", "unknown backslash escape"), + ("\\C-\\<backspace>", "\\C- followed by invalid key") + ] + for test_keys, expected_err in cases: + with self.subTest(f"{test_keys} should give error {expected_err}"): + with self.assertRaises(KeySpecError) as e: + parse_keys(test_keys) + self.assertIn(expected_err, str(e.exception)) + + def test_index_errors(self): + test_cases = ["\\", "\\C", "\\C-\\C"] + for test_keys in test_cases: + with self.assertRaises(IndexError): + parse_keys(test_keys) + class TestCompileKeymap(unittest.TestCase): def test_empty_keymap(self): @@ -72,3 +109,12 @@ class TestCompileKeymap(unittest.TestCase): keymap = {b"a": {b"b": {b"c": "action"}}} result = compile_keymap(keymap) self.assertEqual(result, {b"a": {b"b": {b"c": "action"}}}) + + def test_clashing_definitions(self): + km = {b'a': 'c', b'a' + b'b': 'd'} + with self.assertRaises(KeySpecError): + compile_keymap(km) + + def test_non_bytes_key(self): + with self.assertRaises(TypeError): + compile_keymap({123: 'a'}) |