def test_entered_for_loop_full_loop_not_entered(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.full_for_loop.__code__ = instr._instrument_code_recursive( simple_module.full_for_loop.__code__, True) tracer_mock.register_predicate.assert_called_once() simple_module.full_for_loop(0) tracer_mock.executed_bool_predicate.assert_called_with(False, 0)
def test_add_cmp_predicate(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.cmp_predicate.__code__ = instr._instrument_code_recursive( simple_module.cmp_predicate.__code__, True) simple_module.cmp_predicate(1, 2) tracer_mock.register_predicate.assert_called_once() tracer_mock.executed_compare_predicate.assert_called_once()
def test_avoid_duplicate_instrumentation(simple_module): tracer = MagicMock(ExecutionTracer) instr = BranchDistanceInstrumentation(tracer) already_instrumented = instr.instrument_module( simple_module.cmp_predicate.__code__) with pytest.raises(AssertionError): instr.instrument_module(already_instrumented)
def test_entered_function(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.simple_function.__code__ = instr._instrument_code_recursive( simple_module.simple_function.__code__, True) simple_module.simple_function(1) tracer_mock.register_code_object.assert_called_once() tracer_mock.executed_code_object.assert_called_once()
def test_conditional_assignment(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.conditional_assignment.__code__ = instr._instrument_code_recursive( simple_module.conditional_assignment.__code__, True) simple_module.conditional_assignment(10) tracer_mock.register_predicate.assert_called_once() assert tracer_mock.register_code_object.call_count == 1 tracer_mock.executed_compare_predicate.assert_called_once() tracer_mock.executed_code_object.assert_has_calls([call(0)])
def test_add_cmp_predicate_loop_comprehension(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.comprehension.__code__ = instr._instrument_code_recursive( simple_module.comprehension.__code__, True) call_count = 5 simple_module.comprehension(call_count, 3) assert tracer_mock.register_predicate.call_count == 2 assert tracer_mock.executed_compare_predicate.call_count == call_count tracer_mock.executed_bool_predicate.assert_has_calls([call(True, 1)])
def get_code(self, fullname) -> CodeType: """Add instrumentation instructions to the code of the module before it is executed.""" to_instrument = cast( CodeType, super(InstrumentationLoader, self).get_code(fullname)) assert to_instrument, "Failed to get code object of module." # TODO(fk) apply different instrumentations here instrumentation = BranchDistanceInstrumentation(self._tracer) return instrumentation.instrument_module(to_instrument)
def test_add_cmp_predicate_lambda(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.lambda_func.__code__ = instr._instrument_code_recursive( simple_module.lambda_func.__code__, True) lam = simple_module.lambda_func(10) lam(5) tracer_mock.register_predicate.assert_called_once() assert tracer_mock.register_code_object.call_count == 2 tracer_mock.executed_compare_predicate.assert_called_once() tracer_mock.executed_code_object.assert_has_calls( [call(0), call(1)], any_order=True)
def test_conditionally_nested_class(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.conditionally_nested_class.__code__ = instr._instrument_code_recursive( simple_module.conditionally_nested_class.__code__, True) assert tracer_mock.register_code_object.call_count == 3 simple_module.conditionally_nested_class(6) tracer_mock.executed_code_object.assert_has_calls( [call(0), call(1), call(2)], any_order=True) tracer_mock.register_predicate.assert_called_once() tracer_mock.executed_compare_predicate.assert_called_once()
def test_integrate_branch_distance_instrumentation( simple_module, function_name, branchless_function_count, branches_count, ): tracer = ExecutionTracer() function_callable = getattr(simple_module, function_name) instr = BranchDistanceInstrumentation(tracer) function_callable.__code__ = instr._instrument_code_recursive( function_callable.__code__, 0) assert (len(tracer.get_known_data().branch_less_code_objects) == branchless_function_count) assert len(list( tracer.get_known_data().existing_predicates)) == branches_count
def test_transform_for_loop_multi(simple_module, tracer_mock): instr = BranchDistanceInstrumentation(tracer_mock) simple_module.multi_loop.__code__ = instr._instrument_code_recursive( simple_module.multi_loop.__code__, True) assert simple_module.multi_loop(5) == 25 assert tracer_mock.register_predicate.call_count == 3 calls = [ call(True, 0), call(True, 1), call(True, 1), call(True, 1), call(True, 1), call(True, 1), call(False, 2), ] assert tracer_mock.executed_bool_predicate.call_count == len(calls) tracer_mock.executed_bool_predicate.assert_has_calls(calls)
def get_code(self, fullname) -> CodeType: """Add instrumentation instructions to the code of the module before it is executed. Args: fullname: The name of the module Returns: The modules code blocks """ to_instrument = cast(CodeType, super().get_code(fullname)) assert to_instrument, "Failed to get code object of module." # TODO(fk) apply different instrumentations here if config.configuration.dynamic_constant_seeding: dynamic_seeding_instr = DynamicSeedingInstrumentation() to_instrument = dynamic_seeding_instr.instrument_module(to_instrument) instrumentation = BranchDistanceInstrumentation(self._tracer) return instrumentation.instrument_module(to_instrument)