Skip to content

Commit 5a3e2ec

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/utbot-python-codegen' into utbot-python-codegen
2 parents 0eb7a4e + b11d81c commit 5a3e2ec

7 files changed

Lines changed: 141 additions & 103 deletions

File tree

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,8 @@ class PythonListModel(
376376
val length: Int = 0,
377377
val stores: List<PythonModel>
378378
) : PythonModel(classId) {
379-
override fun toString() = withToStringThreadLocalReentrancyGuard {
380-
(0 until length).map { stores[it] }.joinToString(", ", "[", "]")
381-
}
379+
override fun toString() =
380+
(0 until length).joinToString(", ", "[", "]") { stores[it].toString() }
382381

383382
override val allContainingClassIds: Set<PythonClassId>
384383
get() = super.allContainingClassIds + stores.flatMap { it.allContainingClassIds }
@@ -392,9 +391,8 @@ class PythonTupleModel(
392391
val length: Int = 0,
393392
val stores: List<PythonModel>
394393
) : PythonModel(classId) {
395-
override fun toString() = withToStringThreadLocalReentrancyGuard {
396-
(0 until length).map { stores[it] }.joinToString(", ", "(", ")")
397-
}
394+
override fun toString() =
395+
(0 until length).joinToString(", ", "(", ")") { stores[it].toString() }
398396

399397
override val allContainingClassIds: Set<PythonClassId>
400398
get() = super.allContainingClassIds + stores.flatMap { it.allContainingClassIds }

utbot-python/samples/samples/matrix.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
from typing import List
44

55

6+
class MatrixException(Exception):
7+
def __init__(self, description):
8+
self.description = description
9+
10+
611
class Matrix:
712
def __init__(self, elements: List[List[float]]):
813
self.elements = elements
@@ -31,6 +36,9 @@ def __mul__(self, other):
3136
]
3237
for i in range(self.dim[0])
3338
])
39+
else:
40+
raise MatrixException("Wrong Type")
41+
3442

3543
def __matmul__(self, other):
3644
if isinstance(other, Matrix):
@@ -42,9 +50,11 @@ def __matmul__(self, other):
4250
for k in range(self.dim[1])
4351
)
4452
return Matrix(result)
53+
else:
54+
raise MatrixException("Wrong Type")
4555

4656

4757
if __name__ == '__main__':
48-
a = Matrix([[1, 2]])
49-
b = Matrix([[3], [4]])
58+
a = Matrix([[1., 2.]])
59+
b = Matrix([[3.], [4.]])
5060
print(a @ b)

utbot-python/src/main/kotlin/org/utbot/python/PythonEngine.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class PythonEngine(
2323
private val pythonPath: String,
2424
private val fuzzedConcreteValues: List<FuzzedConcreteValue>,
2525
private val selectedTypeMap: Map<String, NormalizedPythonAnnotation>,
26-
private val timeoutForRun: Long
26+
private val timeoutForRun: Long,
27+
private val initialCoveredLines: Set<Int>
2728
) {
2829

2930
private data class JobResult(
@@ -74,7 +75,7 @@ class PythonEngine(
7475
)
7576
}.iterator()
7677

77-
val coveredLines = mutableSetOf<Int>()
78+
val coveredLines = initialCoveredLines.toMutableSet()
7879
while (evaluationInputIterator.hasNext()) {
7980
val chunk = mutableListOf<EvaluationInput>()
8081
while (evaluationInputIterator.hasNext() && chunk.size < CHUNK_SIZE)
@@ -110,7 +111,7 @@ class PythonEngine(
110111
if (isException && (resultJSON.type.name in prohibitedExceptions)) { // wrong type (sometimes mypy fails)
111112
logger.debug("Evaluation with prohibited exception. Substituted types: ${
112113
types.joinToString { it.name }
113-
}")
114+
}. Exception type: ${resultJSON.type.name}")
114115
return@sequence
115116
}
116117

utbot-python/src/main/kotlin/org/utbot/python/PythonTestCaseGenerator.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ package org.utbot.python
22

33
import mu.KotlinLogging
44
import org.utbot.framework.minimization.minimizeExecutions
5-
import org.utbot.framework.plugin.api.NormalizedPythonAnnotation
6-
import org.utbot.framework.plugin.api.UtError
7-
import org.utbot.framework.plugin.api.UtExecution
8-
import org.utbot.framework.plugin.api.pythonAnyClassId
5+
import org.utbot.framework.plugin.api.*
96
import org.utbot.python.code.ArgInfoCollector
107
import org.utbot.python.typing.AnnotationFinder.findAnnotations
118
import org.utbot.python.typing.MypyAnnotations
@@ -68,6 +65,7 @@ object PythonTestCaseGenerator {
6865
val executions = mutableListOf<UtExecution>()
6966
val errors = mutableListOf<UtError>()
7067
var missingLines: Set<Int>? = null
68+
val coveredLines = mutableSetOf<Int>()
7169
var generated = 0
7270

7371
run breaking@ {
@@ -86,7 +84,8 @@ object PythonTestCaseGenerator {
8684
pythonPath,
8785
argInfoCollector.getConstants(),
8886
annotations,
89-
timeoutForRun
87+
timeoutForRun,
88+
coveredLines
9089
)
9190

9291
engine.fuzzing().forEach {
@@ -97,12 +96,7 @@ object PythonTestCaseGenerator {
9796
is UtExecution -> {
9897
logger.debug("Added execution")
9998
executions += it
100-
val curMissing =
101-
(it.coverage as? PythonCoverage)
102-
?.missedInstructions
103-
?.map { x -> x.lineNumber } ?.toSet()
104-
?: emptySet()
105-
missingLines = if (missingLines == null) curMissing else missingLines!! intersect curMissing
99+
missingLines = updateCoverage(it, coveredLines, missingLines)
106100
}
107101
is UtError -> {
108102
logger.debug("Failed evaluation")
@@ -115,14 +109,30 @@ object PythonTestCaseGenerator {
115109
}
116110
}
117111

112+
val (successfulExecutions, failedExecutions) = executions.partition { it.result is UtExecutionSuccess }
113+
118114
return PythonTestSet(
119115
method,
120-
if (withMinimization) minimizeExecutions(executions) else executions,
116+
if (withMinimization)
117+
minimizeExecutions(successfulExecutions) + minimizeExecutions(failedExecutions)
118+
else
119+
executions,
121120
errors,
122121
storageForMypyMessages
123122
)
124123
}
125124

125+
// returns new missingLines
126+
private fun updateCoverage(execution: UtExecution, coveredLines: MutableSet<Int>, missingLines: Set<Int>?): Set<Int> {
127+
execution.coverage?.coveredInstructions?.map { instr -> coveredLines.add(instr.lineNumber) }
128+
val curMissing =
129+
(execution.coverage as? PythonCoverage)
130+
?.missedInstructions
131+
?.map { x -> x.lineNumber } ?.toSet()
132+
?: emptySet()
133+
return if (missingLines == null) curMissing else missingLines intersect curMissing
134+
}
135+
126136
private fun getAnnotations(
127137
method: PythonMethod,
128138
initialArgumentTypes: List<NormalizedPythonAnnotation>,

utbot-python/src/main/kotlin/org/utbot/python/code/CodeGen.kt

Lines changed: 97 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -42,37 +42,6 @@ object PythonCodeGenerator {
4242
return modulePrettyPrintVisitor.visitModule(module, IndentationPrettyPrint(0))
4343
}
4444

45-
private fun createOutputBlock(
46-
outputName: String,
47-
status: String,
48-
stmtsName: String,
49-
missedName: String
50-
): List<Statement> {
51-
return listOf(
52-
Assign(
53-
listOf(Name("out")),
54-
Atom(
55-
Name(
56-
"_PythonTreeSerializer().dumps"
57-
),
58-
listOf(createArguments(listOf(Name(outputName))))
59-
)
60-
),
61-
Atom(
62-
Name("print"),
63-
listOf(
64-
createArguments(
65-
listOf(Str("'$status'"), Name("json.dumps(out)"), Name(stmtsName), Name(missedName)),
66-
listOf(
67-
Keyword(Name("end"), Str("''")),
68-
Keyword(Name("sep"), Str("'\\n'"))
69-
)
70-
)
71-
)
72-
)
73-
)
74-
}
75-
7645
private fun createArguments(
7746
args: List<Expression> = emptyList(),
7847
keywords: List<Keyword> = emptyList(),
@@ -174,6 +143,9 @@ object PythonCodeGenerator {
174143
val missedFilteredName = Name("__missed_filtered")
175144
val coverageName = Name("__cov")
176145
val fullpathName = Name("__fullpath")
146+
val statusName = Name("__status")
147+
val exceptionName = Name("__exception")
148+
val serialisedName = Name("__serialized")
177149

178150
val fullpath = Assign(
179151
listOf(fullpathName),
@@ -205,11 +177,26 @@ object PythonCodeGenerator {
205177
listOf(Attribute(Identifier("start")), createArguments())
206178
)
207179

208-
val result = Assign(
180+
val resultSuccess = Assign(
209181
listOf(resultName),
210182
functionCall
211183
)
212184

185+
val statusSuccess = Assign(
186+
listOf(statusName),
187+
Str("\"" + successStatus + "\"")
188+
)
189+
190+
val resultError = Assign(
191+
listOf(resultName),
192+
exceptionName
193+
)
194+
195+
val statusError = Assign(
196+
listOf(statusName),
197+
Str("\"" + failStatus + "\"")
198+
)
199+
213200
val stopCoverage = Atom(
214201
coverageName,
215202
listOf(Attribute(Identifier("stop")), createArguments())
@@ -270,53 +257,92 @@ object PythonCodeGenerator {
270257
)
271258
)
272259

273-
val okOutputBlock = createOutputBlock(
274-
resultName.id.name,
275-
successStatus,
276-
stmtsFilteredWithDefName.id.name,
277-
missedFilteredName.id.name
260+
val serialize = Assign(
261+
listOf(serialisedName),
262+
Atom(
263+
Name("_PythonTreeSerializer().dumps"),
264+
listOf(createArguments(listOf(resultName)))
265+
)
278266
)
279267

280-
val exceptionName = "e"
281-
val failOutputBlock = createOutputBlock(
282-
exceptionName,
283-
failStatus,
284-
"[]",
285-
"[]"
268+
val jsonDumps = Atom(
269+
Name("json"),
270+
listOf(
271+
Attribute(Identifier("dumps")),
272+
createArguments(listOf(serialisedName))
273+
)
286274
)
287275

288-
val suppressedBlock = With(
289-
listOf(WithItem(Atom(
290-
Name(getStdoutSuppressName),
291-
listOf(createArguments())
292-
))),
293-
Body(
294-
parameters + listOf(
295-
fullpath,
296-
coverage,
297-
startCoverage,
298-
result,
299-
stopCoverage,
300-
sourcesAndStart,
301-
end,
302-
covAnalysis,
303-
clean,
304-
stmtsFiltered,
305-
stmtsFilteredWithDef,
306-
missedFiltered
276+
// TODO: Add this block
277+
// val suppressedBlock = With(
278+
// listOf(WithItem(Atom(
279+
// Name(getStdoutSuppressName),
280+
// listOf(createArguments())
281+
// ))),
282+
// Body(
283+
// parameters + listOf(
284+
// fullpath,
285+
// coverage,
286+
// startCoverage,
287+
// result,
288+
// stopCoverage,
289+
// sourcesAndStart,
290+
// end,
291+
// covAnalysis,
292+
// clean,
293+
// stmtsFiltered,
294+
// stmtsFilteredWithDef,
295+
// missedFiltered
296+
// )
297+
// )
298+
// )
299+
//
300+
// val tryBody = Body(
301+
// listOf(suppressedBlock) + okOutputBlock
302+
val printStmt = Atom(
303+
Name("print"),
304+
listOf(
305+
createArguments(
306+
listOf(statusName, jsonDumps, stmtsFilteredWithDefName, missedFilteredName),
307+
listOf(
308+
Keyword(Name("end"), Str("''")),
309+
Keyword(Name("sep"), Str("'\\n'"))
310+
)
307311
)
308312
)
309313
)
310314

311-
val tryBody = Body(
312-
listOf(suppressedBlock) + okOutputBlock
313-
)
314-
val tryHandler = ExceptHandler("Exception", exceptionName)
315-
val tryBlock = Try(tryBody, listOf(tryHandler), listOf(Body(failOutputBlock)))
316-
317-
testFunction.addStatement(
318-
tryBlock
319-
)
315+
val tryBody = Body(listOf(
316+
resultSuccess,
317+
statusSuccess
318+
))
319+
val failBody = Body(listOf(
320+
resultError,
321+
statusError
322+
))
323+
val tryHandler = ExceptHandler("Exception", exceptionName.id.name)
324+
val tryBlock = Try(tryBody, listOf(tryHandler), listOf(failBody))
325+
326+
(parameters + listOf(
327+
fullpath,
328+
coverage,
329+
startCoverage
330+
)).forEach { testFunction.addStatement(it) }
331+
332+
testFunction.addStatement(tryBlock)
333+
334+
listOf(
335+
stopCoverage,
336+
sourcesAndStart,
337+
end,
338+
covAnalysis,
339+
clean,
340+
stmtsFiltered,
341+
stmtsFilteredWithDef,
342+
missedFiltered,
343+
serialize,
344+
printStmt
345+
).forEach { testFunction.addStatement(it) }
320346

321347
val runFunction = Atom(
322348
Name(testFunctionName),

utbot-python/src/main/kotlin/org/utbot/python/providers/GenericModelProvider.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ object GenericModelProvider: PythonModelProvider() {
2626
)
2727
fuzz(syntheticGenericType, defaultPythonModelProvider)
2828
.randomChunked()
29-
.map(modelConstructor)
29+
.mapNotNull(modelConstructor)
3030
.forEach {
31-
if (it != null)
32-
yield(FuzzedParameter(index, it.fuzzed()))
31+
yield(FuzzedParameter(index, it.fuzzed()))
3332
}
3433
}
3534

0 commit comments

Comments
 (0)