def create_stmt_from_constant( constant: ast.Constant, testcase: tc.TestCase) -> Optional[prim_stmt.PrimitiveStatement]: """Creates a statement from an ast.constant node. Args: constant: the ast.Constant statement testcase: the testcase containing the statement Returns: The corresponding statement. """ if constant.value is None: return prim_stmt.NoneStatement(testcase, constant.value) val = constant.value if isinstance(val, bool): return prim_stmt.BooleanPrimitiveStatement(testcase, val) if isinstance(val, int): return prim_stmt.IntPrimitiveStatement(testcase, val) if isinstance(val, float): return prim_stmt.FloatPrimitiveStatement(testcase, val) if isinstance(val, str): return prim_stmt.StringPrimitiveStatement(testcase, val) if isinstance(val, bytes): return prim_stmt.BytesPrimitiveStatement(testcase, val) logger.info( "Could not find case for constant while handling assign statement.") return None
def test_none_statement_equals_clone(): test_case = MagicMock(tc.TestCase) statement = prim.NoneStatement(test_case, type(None)) test_case.statements = [statement] test_case2 = MagicMock(tc.TestCase) clone = statement.clone(test_case2) test_case2.statements = [clone] assert statement.__eq__(clone)
def test_select_random_variable_for_call_none(constructor_mock, function_mock): test_case = dtc.DefaultTestCase() test_case.add_statement(prim.NoneStatement(test_case, MagicMock)) test_case.add_statement(prim.FloatPrimitiveStatement(test_case, 5.0)) function_mock.inferred_signature.update_return_type(None) test_case.add_statement( par_stmt.FunctionStatement(test_case, function_mock)) assert (tf.TestFactory._select_random_variable_for_call( test_case, test_case.size()) is None)
def test_change_call_function(function_mock): test_case = dtc.DefaultTestCase() test_case.add_statement(prim.FloatPrimitiveStatement(test_case, 3.5)) to_replace = prim.NoneStatement(test_case, float) test_case.add_statement(to_replace) test_cluster = MagicMock(TestCluster) test_factory = tf.TestFactory(test_cluster) test_factory.change_call(test_case, to_replace, function_mock) assert test_case.statements[1].accessible_object() == function_mock assert test_case.statements[1].return_value is to_replace.return_value
def _create_none( test_case: tc.TestCase, parameter_type: Optional[Type], position: int, recursion_depth: int, ) -> vr.VariableReference: statement = prim.NoneStatement(test_case, parameter_type) test_case.add_statement(statement, position) ret = test_case.get_statement(position).return_value ret.distance = recursion_depth return ret
def test_change_call_method(constructor_mock, method_mock): test_case = dtc.DefaultTestCase() test_case.add_statement(par_stmt.ConstructorStatement(test_case, constructor_mock)) test_case.add_statement(prim.IntPrimitiveStatement(test_case, 3)) to_replace = prim.NoneStatement(test_case, float) test_case.add_statement(to_replace) test_cluster = MagicMock(TestCluster) test_factory = tf.TestFactory(test_cluster) test_factory.change_call(test_case, to_replace, method_mock) assert test_case.statements[2].accessible_object() == method_mock assert test_case.statements[2].return_value is to_replace.return_value
def test_change_call_unknown(): test_case = dtc.DefaultTestCase() test_case.add_statement(prim.FloatPrimitiveStatement(test_case, 3.5)) to_replace = prim.NoneStatement(test_case, float) test_case.add_statement(to_replace) test_cluster = MagicMock(TestCluster) test_factory = tf.TestFactory(test_cluster) acc = MagicMock(gao.GenericAccessibleObject) acc.is_method.return_value = False acc.is_constructor.return_value = False acc.is_function.return_value = False with pytest.raises(AssertionError): test_factory.change_call(test_case, to_replace, acc)
def _mutate_parameter(self, arg: Union[int, str]) -> bool: """Replace the given parameter with another one that also fits the parameter type. Args: arg: the parameter Returns: True, if the parameter was mutated. """ to_mutate = self._get_argument(arg) param_type = self._get_parameter_type(arg) possible_replacements = self.test_case.get_objects( param_type, self.get_position()) if to_mutate in possible_replacements: possible_replacements.remove(to_mutate) # Consider duplicating an existing statement/variable. copy: Optional[stmt.Statement] = None if self._param_count_of_type( param_type) > len(possible_replacements) + 1: original_param_source = self.test_case.get_statement( to_mutate.get_statement_position()) copy = original_param_source.clone(self.test_case) copy.mutate() possible_replacements.append(copy.ret_val) # TODO(fk) Use param_type instead of to_mutate.variable_type, # to make the selection broader, but this requires access to # the test cluster, to select a concrete type. # Using None as parameter value is also a possibility. none_statement = prim.NoneStatement(self.test_case, to_mutate.variable_type) possible_replacements.append(none_statement.ret_val) replacement = randomness.choice(possible_replacements) if copy and replacement is copy.ret_val: # The chosen replacement is a copy, so we have to add it to the test case. self.test_case.add_statement(copy, self.get_position()) elif replacement is none_statement.ret_val: # The chosen replacement is a none statement, so we have to add it to the # test case. self.test_case.add_statement(none_statement, self.get_position()) self._replace_argument(arg, replacement) return True
def test_change_random_call_unknown_type(test_case_mock): test_cluster = MagicMock(TestCluster) test_factory = tf.TestFactory(test_cluster) assert not test_factory.change_random_call( test_case_mock, prim.NoneStatement(test_case_mock, None))
def test_get_random_non_none_object_none_statement(): test_case = dtc.DefaultTestCase() none_statement = prim.NoneStatement(test_case, float) test_case.add_statement(none_statement) with pytest.raises(ConstructionFailedException): tf.TestFactory._get_random_non_none_object(test_case, float, 0)
def test_none_statement_delta(test_case_mock): statement = prim.NoneStatement(test_case_mock, type(None)) statement.delta() assert statement.value is None
def test_none_statement_randomize_value(test_case_mock): statement = prim.NoneStatement(test_case_mock, type(None)) statement.randomize_value() assert statement.value is None
def _mutate_parameter(self, param_name: str, inf_sig: InferredSignature) -> bool: """Replace the given parameter with another one that also fits the parameter type. Args: param_name: the name of the parameter that should be mutated. Returns: True, if the parameter was mutated. """ current = self._args.get(param_name, None) param_type = inf_sig.parameters[param_name] possible_replacements = self.test_case.get_objects( param_type, self.get_position()) # Param has to be optional, otherwise it would be set. if current is None: # Create value for currently unset parameter. if (randomness.next_float() > config.configuration.skip_optional_parameter_probability): if len(possible_replacements) > 0: self._args[param_name] = randomness.choice( possible_replacements) return True return False if (is_optional_parameter(inf_sig, param_name) and randomness.next_float() < config.configuration.skip_optional_parameter_probability): # unset parameters that are not necessary with a certain probability, # e.g., if they have default value or are *args, **kwargs. self._args.pop(param_name) if current in possible_replacements: possible_replacements.remove(current) # Consider duplicating an existing statement/variable. copy: Optional[stmt.Statement] = None if self._param_count_of_type( param_type) > len(possible_replacements) + 1: original_param_source = self.test_case.get_statement( current.get_statement_position()) copy = original_param_source.clone(self.test_case) copy.mutate() possible_replacements.append(copy.ret_val) # TODO(fk) Use param_type instead of to_mutate.variable_type, # to make the selection broader, but this requires access to # the test cluster, to select a concrete type. # Using None as parameter value is also a possibility. none_statement = prim.NoneStatement(self.test_case, current.variable_type) possible_replacements.append(none_statement.ret_val) replacement = randomness.choice(possible_replacements) if copy and replacement is copy.ret_val: # The chosen replacement is a copy, so we have to add it to the test case. self.test_case.add_statement(copy, self.get_position()) elif replacement is none_statement.ret_val: # The chosen replacement is a none statement, so we have to add it to the # test case. self.test_case.add_statement(none_statement, self.get_position()) self._args[param_name] = replacement return True