From e4441df016c7076e6a026191662d984855ee00af Mon Sep 17 00:00:00 2001 From: pompolic <pompolic@special-circumstanc.es> Date: Tue, 9 Nov 2021 19:45:11 +0100 Subject: [PATCH] Fix breakpoint tests Steps towards figuring how to run tests spread out across multiple files --- gdb-port/tests/run_unittest_main.py | 3 + gdb-port/tests/unit/breakpoints_hammer.py | 10 +- gdb-port/tests/unit/breakpoints_pdf.py | 6 +- gdb-port/tests/unit/parser-envs-pdf.py | 2 +- gdb-port/tests/unit/parser_envs_pdf.py | 128 ++++++++++++++++++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 gdb-port/tests/run_unittest_main.py create mode 100644 gdb-port/tests/unit/parser_envs_pdf.py diff --git a/gdb-port/tests/run_unittest_main.py b/gdb-port/tests/run_unittest_main.py new file mode 100644 index 0000000..decab90 --- /dev/null +++ b/gdb-port/tests/run_unittest_main.py @@ -0,0 +1,3 @@ +import unittest + +unittest.main(exit=False) diff --git a/gdb-port/tests/unit/breakpoints_hammer.py b/gdb-port/tests/unit/breakpoints_hammer.py index fef2eb9..6d51f9d 100644 --- a/gdb-port/tests/unit/breakpoints_hammer.py +++ b/gdb-port/tests/unit/breakpoints_hammer.py @@ -3,9 +3,10 @@ import unittest class PerformLowlevelParseRetBreakpointCreated(unittest.TestCase): def test_breakpoint_is_at_ret(self): + breakpoint_loc = int(perform_lowlevel_parse_ret.location.lstrip("*"), 16) arch = gdb.selected_frame().architecture() - disassembled_ins = arch.disassemble(perform_lowlevel_parse_ret.location) - ins = disassembled_ins['asm'].split(" ")[0] + disassembled_ins = arch.disassemble(breakpoint_loc) + ins = disassembled_ins[0]['asm'].split(" ")[0] self.assertIn(ins, ["ret", "retq"]) @@ -14,9 +15,10 @@ class PerformLowlevelParseRetBreakpointCreated(unittest.TestCase): class HPackratParseRetBreakpointCreated(unittest.TestCase): def test_breakpoint_is_at_ret(self): + breakpoint_loc = int(h_packrat_parse_ret.location.lstrip("*"), 16) arch = gdb.selected_frame().architecture() - disassembled_ins = arch.disassemble(h_packrat_parse_ret.location) - ins = disassembled_ins['asm'].split(" ")[0] + disassembled_ins = arch.disassemble(breakpoint_loc) + ins = disassembled_ins[0]['asm'].split(" ")[0] self.assertIn(ins, ["ret", "retq"]) diff --git a/gdb-port/tests/unit/breakpoints_pdf.py b/gdb-port/tests/unit/breakpoints_pdf.py index 3c0ecb8..b179e62 100644 --- a/gdb-port/tests/unit/breakpoints_pdf.py +++ b/gdb-port/tests/unit/breakpoints_pdf.py @@ -3,12 +3,12 @@ import unittest # TODO: This actually tests whether the main script set up the breakpoint properly, move to integration class InitParserBreakpointCreated(unittest.TestCase): def test_breakpoint_is_at_ret(self): + breakpoint_loc = int(init_parser.location.lstrip("*"), 16) arch = gdb.selected_frame().architecture() - disassembled_ins = arch.disassemble(init_parser.location) - ins = disassembled_ins['asm'].split(" ")[0] + disassembled_ins = arch.disassemble(breakpoint_loc) + ins = disassembled_ins[0]['asm'].split(" ")[0] self.assertIn(ins, ["ret", "retq"]) def test_not_pending(self): self.assertFalse(init_parser.pending) - diff --git a/gdb-port/tests/unit/parser-envs-pdf.py b/gdb-port/tests/unit/parser-envs-pdf.py index 5cb9f60..13207bd 100644 --- a/gdb-port/tests/unit/parser-envs-pdf.py +++ b/gdb-port/tests/unit/parser-envs-pdf.py @@ -126,4 +126,4 @@ class TokenEnvCreation(unittest.TestCase): self.assertIsNotNone(self.parser_env.str_len) self.assertIsInstance(self.parser_env.str_len, int) -unittest.main() +unittest.main(exit=False) diff --git a/gdb-port/tests/unit/parser_envs_pdf.py b/gdb-port/tests/unit/parser_envs_pdf.py new file mode 100644 index 0000000..1c6b973 --- /dev/null +++ b/gdb-port/tests/unit/parser_envs_pdf.py @@ -0,0 +1,128 @@ +# These tests use parsers defined in the PDF parser, for expediency +# There's probably a way to test them in a general manner, but they'd need to be mocked out in process memory +import unittest + +hparser_p_t = gdb.lookup_type("HParser").pointer() + + +class ChoiceEnvCreation(unittest.TestCase): + # setup is also done by parser-name-instrumentation.py and parser-type-instrumentation.py + def setUp(self): + self.parser_obj = top_level_parse.parsers_by_name("eol")[0] + self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + + def test_parser_decombine(self): + self.assertIsInstance(self.parser_env, ChoiceEnv) + + def test_member_parsers(self): + self.assertIsNotNone(self.parser_env.member_parsers) + for p in self.parser_env.member_parsers: + self.assertIsInstance(p, Parser) + + def test_member_parsers_name(self): + for p in self.parser_env.member_parsers: + self.assertIsNotNone(p.name) + + def test_member_parsers_size(self): + self.assertEqual(len(self.parser_env.member_parsers),3) + + +# Maybe separate tests for h_left, h_middle, etc.? +class IgnoreSeqEnvCreation(unittest.TestCase): + # setup is also done by parser-name-instrumentation.py and parser-type-instrumentation.py + def setUp(self): + self.parser_obj = top_level_parse.parsers_by_name("name")[0] + self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + + def test_parser_decombine(self): + self.assertIsInstance(self.parser_env, IgnoreSeqEnv) + + def test_member_parsers(self): + self.assertIsNotNone(self.parser_env.member_parsers) + for p in self.parser_env.member_parsers: + self.assertIsInstance(p, Parser) + + def test_member_parsers_name(self): + for p in self.parser_env.member_parsers: + self.assertIsNotNone(p.name) + + def test_which(self): + self.assertIsNotNone(self.parser_env.which) + self.assertIsInstance(self.parser_env.which, int) + + def test_member_parsers_size(self): + self.assertEqual(len(self.parser_env.member_parsers),2) + + +class ManyEnvCreation(unittest.TestCase): + # setup is also done by parser-name-instrumentation.py and parser-type-instrumentation.py + def setUp(self): + self.parser_obj = top_level_parse.parsers_by_name("digits")[0] + self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + + def test_parser_decombine(self): + self.assertIsInstance(self.parser_env, ManyEnv) + + def test_member_parser(self): + self.assertIsNotNone(self.parser_env.p) + self.assertIsInstance(self.parser_env.p, Parser) + + def test_member_parser_name(self): + self.assertIsNotNone(self.parser_env.p.name) + + +# TODO: some parser combinators aren't represented in the H_RULE()s declared +#class NotEnvCreation(unittest.TestCase): + #def setUp(self): + # self.parser_obj = top_level_parse.parsers_by_name("")[0] + # self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + + #def test_parser_decombine(self): + # self.assertIsInstance(self.parser_env, NotEnv) + + #def test_member_parser(self): + # Member parser gets extracted from memory + # self.assertIsNotNone(self.parser_env.member_parser) + # Parser gets named on creation + # self.assertIsNotNone(self.parser_env.member_parser.name) + + +class SequenceEnvCreation(unittest.TestCase): + # setup is also done by parser-name-instrumentation.py and parser-type-instrumentation.py + def setUp(self): + self.parser_obj = top_level_parse.parsers_by_name("comment")[0] + self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + + def test_parser_decombine(self): + self.assertIsInstance(self.parser_env, SequenceEnv) + + def test_member_parsers(self): + self.assertIsNotNone(self.parser_env.member_parsers) + for p in self.parser_env.member_parsers: + self.assertIsInstance(p, Parser) + + def test_member_parsers_name(self): + for p in self.parser_env.member_parsers: + self.assertIsNotNone(p.name) + + def test_member_parsers_size(self): + self.assertEqual(len(self.parser_env.member_parsers),3) + +class TokenEnvCreation(unittest.TestCase): + def setUp(self): + self.parser_obj = top_level_parse.parsers_by_name("null")[0] + self.parser_env = top_level_parse.parser_decombinator.decompose_parser(self.parser_obj,top_level_parse) + self.token_type = gdb.lookup_type("uint8_t").pointer() + + def test_parser_decombine(self): + self.assertIsInstance(self.parser_env, TokenEnv) + + def test_token(self): + self.assertIsNotNone(self.parser_env.token) + self.assertIsInstance(self.parser_env.token, gdb.Value) + self.assertEqual(self.parser_env.token.type, self.token_type) # For gdb.Type objects, == checks for equivalence, and the "is" operator won't work + + def test_str_len(self): + self.assertIsNotNone(self.parser_env.str_len) + self.assertIsInstance(self.parser_env.str_len, int) + -- GitLab