Skip to content

UTBot Python fix bugs #2581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "utbot-executor"
version = "1.4.41"
version = "1.4.44"
description = ""
authors = ["Vyacheslav Tamarin <vyacheslav.tamarin@yandex.ru>"]
readme = "README.md"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.41
1.4.44
3 changes: 2 additions & 1 deletion utbot-python/samples/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']:
Expand Down
2 changes: 1 addition & 1 deletion utbot-python/samples/test_configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
"classes": null,
"methods": null,
"timeout": 30,
"coverage": 92
"coverage": 88
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<PythonTreeNode> = emptyList()

fun isRecursive(): Boolean {
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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"
)
}
}
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor(
}
}

private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null, depth: Int = 6): Pair<CgValue, List<CgStatement>> {
private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null): Pair<CgValue, List<CgStatement>> {
val id = objectNode.id
val assistant = (context.cgLanguageAssistant as PythonCgLanguageAssistant)
return when (objectNode) {
Expand Down