def visit_Compare(self, node: Compare) -> Any: node = self.generic_visit(node) # visit child nodes if self.instrumentation_level < INSTRUMENTATION_LEVEL_BRANCH_DISTANCE_CMP: return node operator = self.operator_to_string(node.ops[0]) if len(node.comparators) > 1: # TODO: handle len(comparators) > 1 return node if operator in VALID_OPS: self.branch_counter += 1 left_rec = self.generic_visit(node.left) right_rec = self.generic_visit(node.comparators[0]) ObjectiveRecorder().register_target( branch_objective_name(self.module, node.lineno, self.branch_counter, True)) ObjectiveRecorder().register_target( branch_objective_name(self.module, node.lineno, self.branch_counter, False)) return ast.Call(func=ast.Name("compare_statement", ast.Load()), args=[ left_rec, ast.Str(operator), right_rec, ast.Str(self.module), ast.Num(node.lineno), ast.Num(self.branch_counter) ], keywords=[]) return node
def visit_Module(self, node): node = self.generic_visit(node) # visit child nodes ObjectiveRecorder().register_target(file_objective_name(self.module)) import_node = ast.ImportFrom( module='evomaster_client.instrumentation.injected_functions', names=[ast.alias(name='*', asname=None)], level=0) node.body.insert(0, import_node) return node
def visit_Statement(self, node): node = self.generic_visit(node) # visit child nodes print("Visited node of type: ", node.__class__.__name__, " - line no:", node.lineno) if self.instrumentation_level < INSTRUMENTATION_LEVEL_COVERAGE: return node if hasattr(node, 'body'): print( "isBlockStatement. no point in instrumenting it. Recall, we still instrument its content anyway." ) return node self.statement_counter += 1 ObjectiveRecorder().register_target( line_objective_name(self.module, node.lineno)) ObjectiveRecorder().register_target( statement_objective_name(self.module, node.lineno, self.statement_counter)) # For nodes that were part of a collection of statements (that applies to all statement nodes), # the visitor may also return a list of nodes rather than just a single node. # TODO: Consider statements that do not need a completed_statement (return, continue, raise, etc.) # TODO: Replace return(something) with a completing_statement(something, ...) return [ ast.Expr( value=ast.Call(func=ast.Name("entering_statement", ast.Load()), args=[ ast.Str(self.module), ast.Num(node.lineno), ast.Num(self.statement_counter) ], keywords=[])) ] + [node] + [ ast.Expr(value=ast.Call(func=ast.Name("completed_statement", ast.Load()), args=[ ast.Str(self.module), ast.Num(node.lineno), ast.Num(self.statement_counter) ], keywords=[])), ]
def get_target_infos(self, ids: Set[int]): target_infos = [] objectives = ExecutionTracer().objective_coverage for mapped_id in ids: descriptive_id = ObjectiveRecorder().get_descriptive_id(mapped_id) # TODO: review what's the purpose of withMappedId and withNoDescriptiveId ? t = objectives.get(descriptive_id) if t: t.mapped_id = mapped_id t.descriptive_id = None else: t = TargetInfo.not_reached(mapped_id) target_infos.append(t) # If new targets were found, we add them even if not requested by EM for descriptive_id in ObjectiveRecorder().first_time_encountered: t = objectives[descriptive_id] t.mapped_id = ObjectiveRecorder().get_mapped_id(descriptive_id) target_infos.append(t) return target_infos
def update_objective(self, descriptive_id: str, value: float) -> None: if value < 0 or value > 1: raise ValueError(f'Invalid value: {value}') target_info = TargetInfo(None, descriptive_id, value, self.action_index) previous = self.objective_coverage.get(descriptive_id) if previous: if value > previous.value: self.objective_coverage[descriptive_id] = target_info else: self.objective_coverage[descriptive_id] = target_info ObjectiveRecorder().update(descriptive_id, value)
def visit_BoolOp(self, node: BoolOp) -> Any: node = self.generic_visit(node) # visit child nodes if self.instrumentation_level < INSTRUMENTATION_LEVEL_BRANCH_DISTANCE_BOOLOPS: return node if isinstance(node.op, And) or isinstance(node.op, Or): if len(node.values) > 2: # TODO: handle len(values) > 2 return node self.branch_counter += 1 ObjectiveRecorder().register_target( branch_objective_name(self.module, node.lineno, self.branch_counter, True)) ObjectiveRecorder().register_target( branch_objective_name(self.module, node.lineno, self.branch_counter, False)) injected_function = "and_statement" if isinstance( node.op, And) else "or_statement" right_pure = self.is_pure(node.values[1]) empty_args = ast.arguments(args=[], vararg=None, kwarg=None, defaults=[], posonlyargs=[], kwonlyargs=[], kw_defaults=[]) return ast.Call(func=ast.Name(injected_function, ast.Load()), args=[ ast.Lambda(empty_args, node.values[0]), ast.Lambda(empty_args, node.values[1]), ast.Constant(right_pure), ast.Constant(self.module), ast.Constant(node.lineno), ast.Constant(self.branch_counter) ], keywords=[]) return node
def new_test(self): ExecutionTracer().reset() ObjectiveRecorder().clearFirstTimeEncountered()
def new_search(self): ExecutionTracer().reset() ObjectiveRecorder().reset()
def is_instrumentation_activated(self) -> bool: return bool(ObjectiveRecorder().all_targets)
def get_units_info_dto(self): return { 'unitNames': list(ObjectiveRecorder().units_info.unit_names), 'numberOfLines': ObjectiveRecorder().units_info.lines_count, 'numberOfBranches': ObjectiveRecorder().units_info.branch_count }