예제 #1
0
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
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
 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
예제 #6
0
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
예제 #7
0
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)
예제 #8
0
    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
예제 #9
0
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))
예제 #10
0
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)
예제 #11
0
def test_none_statement_delta(test_case_mock):
    statement = prim.NoneStatement(test_case_mock, type(None))
    statement.delta()
    assert statement.value is None
예제 #12
0
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
예제 #13
0
    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