diff --git a/utbot-cli-python/src/main/kotlin/org/utbot/cli/language/python/PythonGenerateTestsCommand.kt b/utbot-cli-python/src/main/kotlin/org/utbot/cli/language/python/PythonGenerateTestsCommand.kt index 7cc8e65311..981d2f9b4b 100644 --- a/utbot-cli-python/src/main/kotlin/org/utbot/cli/language/python/PythonGenerateTestsCommand.kt +++ b/utbot-cli-python/src/main/kotlin/org/utbot/cli/language/python/PythonGenerateTestsCommand.kt @@ -129,12 +129,14 @@ class PythonGenerateTestsCommand : CliktCommand( val topLevelClasses = PythonCode.getTopLevelClasses(parsedModule) val selectedMethods = methods + val filterMethods = listOf("__init__", "__new__") if (pythonClass == null && methods == null) { return if (topLevelFunctions.isNotEmpty()) Success( topLevelFunctions .mapNotNull { parseFunctionDefinition(it) } .map { PythonMethodHeader(it.name.toString(), absSourceFile(), null) } + .filter { !filterMethods.contains(it.name) } ) else { val topLevelClassMethods = topLevelClasses @@ -146,6 +148,7 @@ class PythonGenerateTestsCommand : CliktCommand( val parsedClassName = PythonClassId(cls.name.toString()) PythonMethodHeader(function.name.toString(), absSourceFile(), parsedClassName) } + .filter { !filterMethods.contains(it.name) } } if (topLevelClassMethods.isNotEmpty()) { Success(topLevelClassMethods) @@ -178,6 +181,7 @@ class PythonGenerateTestsCommand : CliktCommand( .map { PythonMethodHeader(it.name.toString(), absSourceFile(), parsedClassId) } + .filter { !filterMethods.contains(it.name) } if (fineMethods.isNotEmpty()) Success(fineMethods) else diff --git a/utbot-python-executor/src/main/python/utbot_executor/pyproject.toml b/utbot-python-executor/src/main/python/utbot_executor/pyproject.toml index 8f855fb4d2..74249105ff 100644 --- a/utbot-python-executor/src/main/python/utbot_executor/pyproject.toml +++ b/utbot-python-executor/src/main/python/utbot_executor/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "utbot-executor" -version = "1.4.41" +version = "1.4.44" description = "" authors = ["Vyacheslav Tamarin "] readme = "README.md" diff --git a/utbot-python-executor/src/main/python/utbot_executor/tests/test_deep_serialization.py b/utbot-python-executor/src/main/python/utbot_executor/tests/test_deep_serialization.py index 290785206c..58f991562d 100644 --- a/utbot-python-executor/src/main/python/utbot_executor/tests/test_deep_serialization.py +++ b/utbot-python-executor/src/main/python/utbot_executor/tests/test_deep_serialization.py @@ -192,6 +192,28 @@ def test_comparable(): assert memory_dump.objects[serialized_obj_ids[0]].comparable +def test_complex(): + obj = complex(real=float('-inf'), imag=float('nan')) + serialized_obj_ids, _, serialized_memory_dump = serialize_objects_dump([obj], True) + memory_dump = json_converter.deserialize_memory_objects(serialized_memory_dump) + assert not memory_dump.objects[serialized_obj_ids[0]].comparable + + +def test_complex_state(): + class A: + def __init__(self, c): + self.c = c + + obj = A(complex(real=float('-inf'), imag=float('nan'))) + serialized_obj_ids, _, serialized_memory_dump = serialize_objects_dump([obj], True) + memory_dump = json_converter.deserialize_memory_objects(serialized_memory_dump) + deserialized_obj = memory_dump.objects[serialized_obj_ids[0]] + assert not deserialized_obj.comparable + state = memory_dump.objects[deserialized_obj.state].items + field_value = memory_dump.objects[list(state.values())[0]] + assert not field_value.comparable + + class IncomparableClass: pass diff --git a/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/deep_serialization/memory_objects.py b/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/deep_serialization/memory_objects.py index ac9c32199b..5acc0703a5 100644 --- a/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/deep_serialization/memory_objects.py +++ b/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/deep_serialization/memory_objects.py @@ -307,14 +307,20 @@ def initialize(self) -> None: state = serializer[self.state] if isinstance(state, dict): for key, value in state.items(): - setattr(deserialized_obj, key, value) + try: + setattr(deserialized_obj, key, value) + except AttributeError: + pass elif hasattr(deserialized_obj, "__setstate__"): deserialized_obj.__setstate__(state) elif isinstance(state, tuple) and len(state) == 2: _, slotstate = state if slotstate: for key, value in slotstate.items(): - setattr(deserialized_obj, key, value) + try: + setattr(deserialized_obj, key, value) + except AttributeError: + pass items = serializer[self.listitems] if isinstance(items, Iterable): diff --git a/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/executor.py b/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/executor.py index 293b676134..a1e10ec57e 100644 --- a/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/executor.py +++ b/utbot-python-executor/src/main/python/utbot_executor/utbot_executor/executor.py @@ -23,9 +23,11 @@ __all__ = ['PythonExecutor'] -def _update_states(init_memory_dump: MemoryDump, state_before: MemoryDump) -> MemoryDump: - for id_, obj in state_before.objects.items(): - if id_ not in init_memory_dump.objects: +def _update_states(init_memory_dump: MemoryDump, before_memory_dump: MemoryDump) -> MemoryDump: + for id_, obj in before_memory_dump.objects.items(): + if id_ in init_memory_dump.objects: + init_memory_dump.objects[id_].comparable = obj.comparable + else: init_memory_dump.objects[id_] = obj return init_memory_dump @@ -98,15 +100,16 @@ def run_function(self, request: ExecutionRequest) -> ExecutionResponse: args = [loader.load_object(PythonId(arg_id)) for arg_id in request.arguments_ids] logging.debug("Arguments: %s", args) kwargs = {name: loader.load_object(PythonId(kwarg_id)) for name, kwarg_id in request.kwarguments_ids.items()} + logging.debug("Kwarguments: %s", kwargs) except Exception as _: logging.debug("Error \n%s", traceback.format_exc()) return ExecutionFailResponse("fail", traceback.format_exc()) logging.debug("Arguments have been created") try: - state_before_memory = _load_objects(args + list(kwargs.values())) - init_state_before = _update_states(loader.reload_id(), state_before_memory) - serialized_state_init = serialize_memory_dump(init_state_before) + state_init_memory = _load_objects(args + list(kwargs.values())) + state_init = _update_states(loader.reload_id(), state_init_memory) + serialized_state_init = serialize_memory_dump(state_init) def _coverage_sender(info: typing.Tuple[str, int]): if pathlib.Path(info[0]) == pathlib.Path(request.filepath): diff --git a/utbot-python-executor/src/main/resources/utbot_executor_version b/utbot-python-executor/src/main/resources/utbot_executor_version index f4b5f63c9a..b0a831507c 100644 --- a/utbot-python-executor/src/main/resources/utbot_executor_version +++ b/utbot-python-executor/src/main/resources/utbot_executor_version @@ -1 +1 @@ -1.4.41 \ No newline at end of file +1.4.44 \ No newline at end of file diff --git a/utbot-python/samples/run_tests.py b/utbot-python/samples/run_tests.py index 96b1c4f694..fd4064d1f7 100644 --- a/utbot-python/samples/run_tests.py +++ b/utbot-python/samples/run_tests.py @@ -117,7 +117,8 @@ def check_coverage( def main_test_generation(args): config = parse_config(args.config_file) - shutil.rmtree(args.coverage_output_dir) + if pathlib.Path(args.coverage_output_dir).exists(): + shutil.rmtree(args.coverage_output_dir) for part in config['parts']: for file in part['files']: for group in file['groups']: diff --git a/utbot-python/samples/test_configuration.json b/utbot-python/samples/test_configuration.json index bb7ebf9685..37f4d5645c 100644 --- a/utbot-python/samples/test_configuration.json +++ b/utbot-python/samples/test_configuration.json @@ -207,7 +207,7 @@ "classes": null, "methods": null, "timeout": 30, - "coverage": 92 + "coverage": 88 } ] } diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonApi.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonApi.kt index d76d1a04cb..e2c6ca43ba 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonApi.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonApi.kt @@ -2,7 +2,6 @@ package org.utbot.python.framework.api.python import org.utbot.framework.plugin.api.* import org.utbot.python.PythonArgument -import org.utbot.python.framework.api.python.util.comparePythonTree import org.utbot.python.framework.api.python.util.moduleOfType /** @@ -80,7 +79,7 @@ class PythonTreeModel( if (other !is PythonTreeModel) { return false } - return comparePythonTree(tree, other.tree) + return tree == other.tree } override fun hashCode(): Int { diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt index ccaef79f85..794c502127 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt @@ -54,6 +54,8 @@ object PythonTree { ) { constructor(type: PythonClassId, comparable: Boolean = true) : this(PythonIdGenerator.createId(), type, comparable) + fun PythonTreeNode.wrap(): PythonTreeWrapper = PythonTreeWrapper(this) + open val children: List = emptyList() fun isRecursive(): Boolean { @@ -75,7 +77,7 @@ object PythonTree { if (other !is PythonTreeNode) { return false } - return id == other.id + return this.wrap() == other.wrap() } override fun hashCode(): Int { @@ -367,7 +369,7 @@ class PythonTreeWrapper(val tree: PythonTree.PythonTreeNode) { if (other !is PythonTreeWrapper) return false if (PythonTree.isRecursiveObject(tree) || PythonTree.isRecursiveObject(other.tree)) - return tree == other.tree + return tree.id == other.tree.id return tree.softEquals(other.tree) } diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt index 9658a2ecdf..d31cf52346 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt @@ -189,7 +189,7 @@ class PythonCgMethodConstructor(context: CgContext) : CgMethodConstructor(contex assertEquality( expected = it.second, actual = it.first, - expectedVariableName = paramNames[executableId]?.get(index) + "_modified" + expectedVariableName = paramNames[executableId]?.get(index) + "_expected" ) } if (assertThisObject.isNotEmpty()) { @@ -199,7 +199,7 @@ class PythonCgMethodConstructor(context: CgContext) : CgMethodConstructor(contex assertEquality( expected = it.second, actual = it.first, - expectedVariableName = it.first.name + "_modified" + expectedVariableName = it.first.name + "_expected" ) } } @@ -408,23 +408,29 @@ class PythonCgMethodConstructor(context: CgContext) : CgMethodConstructor(contex is PythonTree.ReduceNode -> { if (expectedNode.state.isNotEmpty()) { expectedNode.state.forEach { (field, value) -> - val fieldActual = newVar(value.type, "actual_$field") { - CgFieldAccess( - actual, FieldId( - value.type, - field + if (value.comparable) { + val fieldActual = newVar(value.type, "actual_$field") { + CgFieldAccess( + actual, FieldId( + value.type, + field + ) ) - ) - } - val fieldExpected = newVar(value.type, "expected_$field") { - CgFieldAccess( - expected, FieldId( - value.type, - field - ) - ) + } + val fieldExpected = if (useExpectedAsValue) { + newVar(value.type, "expected_$field") { + CgFieldAccess( + expected, FieldId( + value.type, + field + ) + ) + } + } else { + variableConstructor.getOrCreateVariable(PythonTreeModel(expectedNode)) + } + pythonDeepTreeEquals(value, fieldExpected, fieldActual, depth - 1, useExpectedAsValue = useExpectedAsValue) } - pythonDeepTreeEquals(value, fieldExpected, fieldActual, depth - 1) } } else { emptyLineIfNeeded() diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt index dd2329f73c..6c9369c619 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt @@ -35,7 +35,7 @@ class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor( } } - private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null, depth: Int = 6): Pair> { + private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null): Pair> { val id = objectNode.id val assistant = (context.cgLanguageAssistant as PythonCgLanguageAssistant) return when (objectNode) {