Skip to content

Commit b77ab34

Browse files
committed
switching to jcdb: another portion #349
1 parent 3837280 commit b77ab34

32 files changed

+226
-301
lines changed

utbot-cli/src/main/kotlin/org/utbot/cli/BunchTestGeneratorCommand.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ import com.github.ajalt.clikt.parameters.arguments.argument
44
import com.github.ajalt.clikt.parameters.options.default
55
import com.github.ajalt.clikt.parameters.options.option
66
import com.github.ajalt.clikt.parameters.types.choice
7+
import kotlinx.coroutines.runBlocking
8+
import mu.KotlinLogging
79
import org.utbot.cli.util.createClassLoader
810
import org.utbot.engine.Mocker
9-
import org.utbot.framework.plugin.api.ClassId
1011
import org.utbot.framework.plugin.api.CodegenLanguage
1112
import org.utbot.framework.plugin.api.util.UtContext
13+
import org.utbot.framework.plugin.api.util.utContext
1214
import org.utbot.framework.plugin.api.util.withUtContext
1315
import java.io.File
1416
import java.net.URLClassLoader
1517
import java.nio.file.Paths
1618
import java.time.temporal.ChronoUnit
1719
import kotlin.reflect.KClass
1820
import kotlin.reflect.jvm.jvmName
19-
import mu.KotlinLogging
2021

2122

2223
private val logger = KotlinLogging.logger {}
@@ -66,7 +67,7 @@ class BunchTestGeneratorCommand : GenerateTestsAbstractCommand(
6667
}
6768
}
6869

69-
override fun run() {
70+
override fun run() = runBlocking {
7071
val classesFromPath = loadClassesFromPath(classLoader, classRootDirectory)
7172
classesFromPath.filterNot { it.java.isInterface }.filter { clazz ->
7273
clazz.qualifiedName != null
@@ -84,7 +85,7 @@ class BunchTestGeneratorCommand : GenerateTestsAbstractCommand(
8485
}
8586
}
8687

87-
private fun generateTestsForClass(targetClassFqn: String) {
88+
private suspend fun generateTestsForClass(targetClassFqn: String) {
8889
val started = now()
8990
val workingDirectory = getWorkingDirectory(targetClassFqn)
9091
?: throw IllegalStateException("Error: Cannot find the target class in the classpath")
@@ -109,7 +110,7 @@ class BunchTestGeneratorCommand : GenerateTestsAbstractCommand(
109110
targetMethods,
110111
searchDirectory = workingDirectory,
111112
chosenClassesToMockAlways = (Mocker.defaultSuperClassesToMockAlwaysNames + classesToMockAlways)
112-
.mapTo(mutableSetOf()) { ClassId(it) }
113+
.mapNotNullTo(mutableSetOf()) { utContext.classpath.findClassOrNull(it) }
113114
)
114115

115116
val testClassBody = generateTest(classUnderTest, testClassName, testSets)

utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsAbstractCommand.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.utbot.framework.UtSettings
1515
import org.utbot.framework.codegen.*
1616
import org.utbot.framework.codegen.model.CodeGenerator
1717
import org.utbot.framework.plugin.api.*
18+
import org.utbot.framework.plugin.api.util.id
1819
import org.utbot.jcdb.api.ClassId
1920
import org.utbot.summary.summarize
2021
import java.io.File
@@ -192,7 +193,7 @@ abstract class GenerateTestsAbstractCommand(name: String, help: String) :
192193
forceStaticMocking == ForceStaticMocking.FORCE && staticsMocking is NoStaticMocking
193194
return CodeGenerator(
194195
testFramework = testFrameworkByName(testFramework),
195-
classUnderTest = classUnderTest.java,
196+
classUnderTest = classUnderTest.java.id,
196197
codegenLanguage = codegenLanguage,
197198
staticsMocking = staticsMocking,
198199
forceStaticMocking = forceStaticMocking,

utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
11
package org.utbot.cli
22

33
import com.github.ajalt.clikt.parameters.arguments.argument
4-
import com.github.ajalt.clikt.parameters.options.check
5-
import com.github.ajalt.clikt.parameters.options.default
6-
import com.github.ajalt.clikt.parameters.options.flag
7-
import com.github.ajalt.clikt.parameters.options.option
8-
import com.github.ajalt.clikt.parameters.options.required
4+
import com.github.ajalt.clikt.parameters.options.*
95
import com.github.ajalt.clikt.parameters.types.choice
6+
import kotlinx.coroutines.runBlocking
7+
import mu.KotlinLogging
108
import org.utbot.common.PathUtil.toPath
9+
import org.utbot.common.filterWhen
1110
import org.utbot.engine.Mocker
12-
import org.utbot.framework.plugin.api.ClassId
11+
import org.utbot.framework.UtSettings
1312
import org.utbot.framework.plugin.api.CodegenLanguage
1413
import org.utbot.framework.plugin.api.UtMethodTestSet
1514
import org.utbot.framework.plugin.api.util.UtContext
15+
import org.utbot.framework.plugin.api.util.utContext
1616
import org.utbot.framework.plugin.api.util.withUtContext
17+
import org.utbot.framework.util.isKnownSyntheticMethod
1718
import org.utbot.sarif.SarifReport
1819
import org.utbot.sarif.SourceFindingStrategyDefault
1920
import java.nio.file.Files
2021
import java.nio.file.Paths
2122
import java.time.temporal.ChronoUnit
2223
import kotlin.reflect.KClass
23-
import mu.KotlinLogging
24-
import org.utbot.common.filterWhen
25-
import org.utbot.framework.UtSettings
26-
import org.utbot.framework.util.isKnownSyntheticMethod
2724

2825

2926
private val logger = KotlinLogging.logger {}
@@ -84,7 +81,7 @@ class GenerateTestsCommand :
8481
)
8582
.flag(default = false)
8683

87-
override fun run() {
84+
override fun run(): Unit = runBlocking {
8885
val started = now()
8986
val workingDirectory = getWorkingDirectory(targetClassFqn)
9087
?: throw Exception("Cannot find the target class in the classpath")
@@ -112,7 +109,7 @@ class GenerateTestsCommand :
112109
Paths.get(sourceCodeFile),
113110
searchDirectory = workingDirectory,
114111
chosenClassesToMockAlways = (Mocker.defaultSuperClassesToMockAlwaysNames + classesToMockAlways)
115-
.mapTo(mutableSetOf()) { ClassId(it) }
112+
.mapNotNullTo (mutableSetOf()) { utContext.classpath.findClassOrNull(it) }
116113
)
117114
val testClassBody = generateTest(classUnderTest, testClassName, testSets)
118115

utbot-framework-api/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ dependencies {
1414
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlin_logging_version
1515
implementation group: 'org.ow2.asm', name: 'asm', version: asm_version
1616

17-
api group: 'com.github.UnitTestBot.jcdb', name: 'jcdb-core', version: '6269be7929'
17+
api group: 'com.github.UnitTestBot.jcdb', name: 'jcdb-core', version: '69b1effdc8'
1818
}
1919

2020
shadowJar {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,7 @@ class BuiltinMethodId(
10481048
// by default we assume that the builtin method is non-static and public
10491049
) : MethodId {
10501050

1051-
override suspend fun access() = if(isStatic) Opcodes.ACC_PUBLIC else Opcodes.ACC_PUBLIC and Opcodes.ACC_STATIC
1051+
override suspend fun access() = if(isStatic) Opcodes.ACC_PUBLIC and Opcodes.ACC_STATIC else Opcodes.ACC_PUBLIC
10521052

10531053
override suspend fun annotations() = emptyList<ClassId>()
10541054

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

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ suspend inline fun <reified T> asClass(): ClassId {
282282

283283
val KClass<*>.id: ClassId
284284
get() = runBlocking {
285-
utContext.classpath.findClass(jvmName)
285+
utContext.classpath.findClass(jvmName.jcdbName())
286286
}
287287

288288
suspend fun KClass<*>.asClassId(): ClassId {
@@ -412,54 +412,55 @@ fun ExecutableId.isConstructor(): Boolean {
412412
/**
413413
* Construct MethodId
414414
*/
415-
fun methodId(classId: ClassId, name: String, returnType: ClassId, vararg arguments: ClassId): MethodId = runBlocking {
416-
classId.methods().first {
417-
it.name == name && it.returnType == returnType && it.parameters().toTypedArray().contentEquals(arguments)
418-
}
415+
fun ClassId.findMethod(name: String, returnType: ClassId, arguments: List<ClassId> = emptyList()): MethodId = runBlocking {
416+
val args = arguments.toTypedArray()
417+
methods().firstOrNull {
418+
it.name == name && it.returnType == returnType && it.parameters().toTypedArray().contentEquals(args)
419+
} ?: throw IllegalStateException("Can't find method: ${this@findMethod.name}#$name(${arguments.joinToString { it.name }}): $returnType.name")
420+
}
421+
422+
fun ClassId.findConstructor(vararg arguments: ClassId): MethodId = runBlocking {
423+
methods().firstOrNull {
424+
it.name == "<init>" && it.parameters().toTypedArray().contentEquals(arguments)
425+
} ?: throw IllegalStateException("Can't find constructor $name(${arguments.joinToString { it.name }})")
419426
}
420427

428+
421429
fun MethodId.asExecutable(): ExecutableId {
422-
if (isConstructor()) {
430+
if (isConstructor) {
423431
return ConstructorExecutableId(this)
424432
}
425433
return MethodExecutableId(this)
426434
}
427435

428436
fun MethodId.asExecutableMethod(): MethodExecutableId {
429-
if (isConstructor()) {
437+
if (isConstructor) {
430438
throw IllegalStateException("Method $this is a constructor")
431439
}
432440
return MethodExecutableId(this)
433441
}
434442

435-
/**
436-
* Construct ConstructorId
437-
*/
438-
fun constructorId(classId: ClassId, arguments: List<ClassId> = emptyList()): ConstructorExecutableId = runBlocking {
439-
val argsArray = arguments.toTypedArray()
440-
ConstructorExecutableId(classId.methods().first {
441-
it.name == "<init>" && it.parameters().toTypedArray().contentEquals(argsArray)
442-
})
443+
fun MethodId.asExecutableConstructor(): ConstructorExecutableId {
444+
if (!isConstructor) {
445+
throw IllegalStateException("Method $this is a constructor")
446+
}
447+
return ConstructorExecutableId(this)
443448
}
444449

445-
fun constructorId(classId: ClassId, vararg arguments: ClassId) = constructorId(classId, arguments.toList())
446-
447-
fun builtinMethodId(
448-
classId: BuiltinClassId,
450+
fun BuiltinClassId.newBuiltinMethod(
449451
name: String,
450452
returnType: ClassId,
451-
vararg arguments: ClassId
453+
arguments: List<ClassId>
452454
): BuiltinMethodId {
453-
return BuiltinMethodId(classId, name, returnType, arguments.toList(), false)
455+
return BuiltinMethodId(this, name, returnType, arguments, false)
454456
}
455457

456-
fun builtinStaticMethodId(
457-
classId: BuiltinClassId,
458+
fun BuiltinClassId.newBuiltinStaticMethodId(
458459
name: String,
459460
returnType: ClassId,
460-
vararg arguments: ClassId
461+
arguments: List<ClassId> = emptyList()
461462
): BuiltinMethodId {
462-
return BuiltinMethodId(classId, name, returnType, arguments.toList(), true).also {
463-
classId.withMethod(it)
463+
return BuiltinMethodId(this, name, returnType, arguments, true).also {
464+
withMethod(it)
464465
}
465466
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package org.utbot.framework.plugin.api.util
22

33
import kotlinx.coroutines.ThreadContextElement
4+
import kotlinx.coroutines.runBlocking
45
import org.utbot.common.StopWatch
56
import org.utbot.common.currentThreadInfo
67
import org.utbot.framework.plugin.api.util.UtContext.Companion.setUtContext
8+
import org.utbot.framework.plugin.jcdb.DelegatingClasspathSet
79
import org.utbot.jcdb.api.ClasspathSet
10+
import org.utbot.jcdb.jcdb
11+
import java.net.URLClassLoader
12+
import java.nio.file.Paths
813
import kotlin.coroutines.CoroutineContext
914

1015
val utContext: UtContext
@@ -18,6 +23,8 @@ class UtContext(val classLoader: ClassLoader, val classpath: ClasspathSet) : Thr
1823
var stopWatch: StopWatch? = null
1924
private set
2025

26+
constructor(classLoader: ClassLoader) : this(classLoader, classLoader.asClasspath())
27+
2128
constructor(classLoader: ClassLoader, stopWatch: StopWatch) : this(classLoader) {
2229
this.stopWatch = stopWatch
2330
}
@@ -58,6 +65,17 @@ class UtContext(val classLoader: ClassLoader, val classpath: ClasspathSet) : Thr
5865
threadLocalContextHolder.remove()
5966
}
6067
}
68+
69+
private fun ClassLoader.asClasspath(): ClasspathSet = runBlocking {
70+
this@asClasspath as URLClassLoader
71+
val files = urLs.map { Paths.get(it.toURI()).toFile() }
72+
val jcdb = jcdb {
73+
useProcessJavaRuntime()
74+
predefinedDirOrJars = files
75+
}
76+
DelegatingClasspathSet(jcdb.classpathSet(files))
77+
}
78+
6179
}
6280

6381
override val key: CoroutineContext.Key<UtContext> get() = Key
@@ -69,6 +87,8 @@ class UtContext(val classLoader: ClassLoader, val classpath: ClasspathSet) : Thr
6987
threadLocalContextHolder.set(this)
7088
return prevUtContext
7189
}
90+
91+
7292
}
7393

7494
inline fun <T> withUtContext(context: UtContext, block: () -> T): T = setUtContext(context).use { block() }

utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden
101101
.apply {
102102
instantiationChain += UtExecutableCallModel(
103103
instance = null,
104-
executable = constructorId(classId),
104+
executable = classId.findConstructor().asExecutable(),
105105
params = emptyList(),
106106
returnValue = this
107107
)
@@ -202,11 +202,10 @@ class ListWrapper(private val utListClass: UtListClass) : BaseGenericStorageBase
202202
else -> classId // TODO: actually we have to find not abstract class with constructor, but it's another story
203203
}
204204

205-
override val modificationMethodId: MethodId = methodId(
206-
classId = java.util.List::class.id,
205+
override val modificationMethodId: MethodId get() = java.util.List::class.id.findMethod(
207206
name = "add",
208207
returnType = booleanClassId,
209-
arguments = arrayOf(objectClassId),
208+
arguments = listOf(objectClassId),
210209
)
211210

212211
override val baseModelName = "list"
@@ -234,12 +233,11 @@ class SetWrapper : BaseGenericStorageBasedContainerWrapper(UtHashSet::class.qual
234233
else -> classId // TODO: actually we have to find not abstract class with constructor, but it's another story
235234
}
236235

237-
override val modificationMethodId: MethodId =
238-
methodId(
239-
classId = java.util.Set::class.id,
236+
override val modificationMethodId: MethodId get() =
237+
java.util.Set::class.id.findMethod(
240238
name = "add",
241239
returnType = booleanClassId,
242-
arguments = arrayOf(objectClassId),
240+
arguments = listOf(objectClassId),
243241
)
244242

245243
override val baseModelName: String = "set"
@@ -309,12 +307,11 @@ class MapWrapper : BaseContainerWrapper(UtHashMap::class.qualifiedName!!) {
309307
else -> classId // TODO: actually we have to find not abstract class with constructor, but it's another story
310308
}
311309

312-
override val modificationMethodId: MethodId =
313-
methodId(
314-
classId = java.util.Map::class.id,
310+
override val modificationMethodId: MethodId get() =
311+
java.util.Map::class.id.findMethod(
315312
name = "put",
316313
returnType = objectClassId,
317-
arguments = arrayOf(objectClassId, objectClassId),
314+
arguments = listOf(objectClassId, objectClassId),
318315
)
319316

320317
override val baseModelName: String = "map"

utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import org.utbot.engine.overrides.strings.UtStringBuffer
1616
import org.utbot.engine.overrides.strings.UtStringBuilder
1717
import org.utbot.engine.pc.UtAddrExpression
1818
import org.utbot.framework.plugin.api.*
19-
import org.utbot.framework.plugin.api.util.constructorId
2019
import org.utbot.framework.plugin.api.util.id
2120
import org.utbot.framework.plugin.api.util.stringClassId
2221
import org.utbot.framework.util.nextModelName
@@ -223,10 +222,10 @@ data class ThrowableWrapper(val throwable: Throwable) : WrapperInterface {
223222
return UtAssembleModel(addr, classId, modelName, instantiationChain)
224223
.apply {
225224
instantiationChain += when (val message = throwable.message) {
226-
null -> UtExecutableCallModel(null, constructorId(classId), emptyList(), this)
225+
null -> UtExecutableCallModel(null, classId.findConstructor(), emptyList(), this)
227226
else -> UtExecutableCallModel(
228227
null,
229-
constructorId(classId, listOf(stringClassId)),
228+
classId.findConstructor(listOf(stringClassId)),
230229
listOf(UtPrimitiveModel(message)),
231230
this,
232231
)

utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,17 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
9595
}
9696
return if (!isPresent) {
9797
UtExecutableCallModel(
98-
null, methodId(
99-
classId,
98+
null, classId.findMethod(
10099
"empty",
101100
classId
102101
).asExecutable(), emptyList(), model
103102
)
104103
} else {
105104
UtExecutableCallModel(
106-
null, methodId(
107-
classId,
105+
null, classId.findMethod(
108106
"of",
109107
classId,
110-
utOptionalClass.elementClassId
108+
listOf(utOptionalClass.elementClassId)
111109
).asExecutable(), listOf(valueModel), model
112110
)
113111
}

utbot-framework/src/main/kotlin/org/utbot/engine/Resolver.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import org.utbot.engine.z3.intValue
1313
import org.utbot.engine.z3.value
1414
import org.utbot.framework.assemble.AssembleModelGenerator
1515
import org.utbot.framework.plugin.api.*
16-
import org.utbot.framework.plugin.api.id
1716
import org.utbot.framework.plugin.api.util.*
1817
import org.utbot.framework.util.nextModelName
1918
import org.utbot.jcdb.api.ClassId
@@ -479,7 +478,7 @@ class Resolver(
479478
val primitiveClassId = primitiveByWrapper[classId]!!
480479
val fields = collectFieldModels(UtAddrExpression(mkInt(addr)), actualType)
481480
val baseModelName = primitiveClassId.name
482-
val constructorId = constructorId(classId, primitiveClassId)
481+
val constructorId = classId.findConstructor(primitiveClassId).asExecutable()
483482
val valueModel = fields[classId.findFieldOrNull("value")] ?: primitiveClassId.defaultValueModel()
484483
val instantiationChain = mutableListOf<UtExecutableCallModel>()
485484
UtAssembleModel(addr, classId, nextModelName(baseModelName), instantiationChain)

0 commit comments

Comments
 (0)