def test_build_errors_with_non_ast(self): sample_ast = [None] with self.assertRaises(ValueError): BasicBlock.build_first_from_ast(sample_ast) sample_ast = [[]] with self.assertRaises(ValueError): BasicBlock.build_first_from_ast(sample_ast)
def test_basic_blocks_are_hashable_by_identifier(self): test_set = set() basic_block = BasicBlock() basic_block.identifier = -1 test_set.add(basic_block) basic_block.identifier = 1 self.assertNotIn(basic_block, test_set) basic_block.identifier = -1 self.assertIn(basic_block, test_set)
def _build_all_basic_blocks( self, ast_nodes: List[AST], ) -> List[BasicBlock]: """Parse all basic blocks out of the list of nodes Args: ast_nodes (List[AST]): AST nodes containing statements that make up basic blocks Returns: List[BasicBlock]: All of the basic blocks that are formed by the given nodes """ basic_blocks: List[BasicBlock] = [] new_block, remaining_nodes = BasicBlock.build_first_from_ast(ast_nodes) if len(new_block.body) > 0: basic_blocks.append(new_block) self.equivalence_classes.add(new_block.identifier) if len(remaining_nodes) == 0: return basic_blocks # Entering new basic block nested_blocks = self._build_nested_blocks(remaining_nodes[0]) unnested_blocks = self._build_all_basic_blocks(remaining_nodes[1:]) self._link_nested_blocks( new_block, nested_blocks, unnested_blocks, remaining_nodes[0] ) return basic_blocks + nested_blocks + unnested_blocks
def test_return_statements_are_ignored(self): sample_code = "return\n" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 0)
def test_class_definitions_are_ignored(self): sample_code = "class TestClass:\n" sample_code += " pass" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 0)
def test_async_function_declarations_are_ignored(self): sample_code = "async def testFunc():\n" sample_code += " pass" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 0)
def test_loops_are_ignored(self): sample_code = "for i in range(10):\n" sample_code += " print(i)" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 0) sample_code = "while True:" sample_code += " print(i)" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 0)
def test_build_multiple_expressions(self): sample_code = "print('Hello Number 1')\n" sample_code += "print('Hello World 2')\n" sample_code += "print('Hello World 3')" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertIsInstance(basic_block, BasicBlock) self.assertEqual(len(basic_block.body), 3)
def test_build_single_expression(self): sample_code = "print('Hello, world!')" module = parse(sample_code) function_call = module.body[0].value (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertIsInstance(basic_block, BasicBlock) self.assertEqual(len(basic_block.body), 1) self.assertEqual(basic_block.body[0], function_call) self.assertIsInstance(basic_block.body[0], Call)
def test_entrance_or_exit_returned_with_remaining(self): sample_code = "print('Test')\n" sample_code += "while True:\n" sample_code += " print(i)\n" sample_code += "print('Test')\n" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertIsInstance(remaining_nodes[0], While)
def test_basic_block_truncated_at_invalid_node(self): sample_code = "print('Test')\n" sample_code += "while True:\n" sample_code += " print(i)\n" sample_code += "print('Test')\n" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 1)
def test_conditionals_are_ignored(self): sample_code = "x = 10\n" sample_code += "if x == 11:\n" sample_code += " x += 1\n" sample_code += "else:\n" sample_code += " x += 2\n" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.body), 1)
def test_function_calls_returns_only_calls(self): sample_code = "print('Hello Number 1')\n" sample_code += "print('Hello World 2')\n" sample_code += "def testFunc():\n" sample_code += " pass" module = parse(sample_code) (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( module.body ) self.assertEqual(len(basic_block.function_calls), 2) self.assertIsInstance(basic_block.function_calls[0], Call) self.assertIsInstance(basic_block.function_calls[1], Call)
def test_basic_block_ids_auto_increment(self): basic_block = BasicBlock() basic_block_id = basic_block.identifier basic_block = BasicBlock() self.assertEqual(basic_block_id + 1, basic_block.identifier)
def test_build_returns_BasicBlock(self): sample_ast = [Expr(Constant())] (basic_block, remaining_nodes,) = BasicBlock.build_first_from_ast( sample_ast ) self.assertIsInstance(basic_block, BasicBlock)