Skip to content
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

Fix build directory for classes from Kotlin files #1019

Merged
merged 2 commits into from
Sep 30, 2022
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 @@ -197,7 +197,7 @@ abstract class GenerateTestsAbstractCommand(name: String, help: String) :
UtSettings.treatOverflowAsError = treatOverflowAsError == TreatOverflowAsError.AS_ERROR

return TestCaseGenerator(
workingDirectory,
listOf(workingDirectory),
classPathNormalized,
System.getProperty("java.class.path"),
JdkInfoDefaultProvider().info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ object UtBotJavaApi {

testSets.addAll(withUtContext(utContext) {
val buildPath = FileUtil.isolateClassFiles(classUnderTest).toPath()
TestCaseGenerator(buildPath, classpath, dependencyClassPath, jdkInfo = JdkInfoDefaultProvider().info)
TestCaseGenerator(listOf(buildPath), classpath, dependencyClassPath, jdkInfo = JdkInfoDefaultProvider().info)
.generate(
methodsForAutomaticGeneration.map {
it.methodToBeTestedFromUserInput.executableId
Expand Down Expand Up @@ -173,7 +173,7 @@ object UtBotJavaApi {

return withUtContext(UtContext(classUnderTest.classLoader)) {
val buildPath = FileUtil.isolateClassFiles(classUnderTest).toPath()
TestCaseGenerator(buildPath, classpath, dependencyClassPath, jdkInfo = JdkInfoDefaultProvider().info)
TestCaseGenerator(listOf(buildPath), classpath, dependencyClassPath, jdkInfo = JdkInfoDefaultProvider().info)
.generate(
methodsForAutomaticGeneration.map {
it.methodToBeTestedFromUserInput.executableId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ import kotlin.reflect.KCallable
* Generates test cases: one by one or a whole set for the method under test.
*
* Note: the instantiating of [TestCaseGenerator] may take some time,
* because it requires initializing Soot for the current [buildDir] and [classpath].
* because it requires initializing Soot for the current [buildDirs] and [classpath].
*
* @param jdkInfo specifies the JRE and the runtime library version used for analysing system classes and user's code.
* @param forceSootReload forces to reinitialize Soot even if the previous buildDir equals to [buildDir] and previous
* @param forceSootReload forces to reinitialize Soot even if the previous buildDirs equals to [buildDirs] and previous
* classpath equals to [classpath]. This is the case for plugin scenario, as the source code may be modified.
*/
open class TestCaseGenerator(
private val buildDir: Path,
private val buildDirs: List<Path>,
private val classpath: String?,
private val dependencyPaths: String,
private val jdkInfo: JdkInfo,
Expand All @@ -71,21 +71,21 @@ open class TestCaseGenerator(
private val timeoutLogger: KLogger = KotlinLogging.logger(logger.name + ".timeout")

private val classpathForEngine: String
get() = buildDir.toString() + (classpath?.let { File.pathSeparator + it } ?: "")
get() = (buildDirs + listOfNotNull(classpath)).joinToString(File.pathSeparator)

init {
if (!isCanceled()) {
checkFrameworkDependencies(dependencyPaths)

logger.trace("Initializing ${this.javaClass.name} with buildDir = $buildDir, classpath = $classpath")
logger.trace("Initializing ${this.javaClass.name} with buildDirs = ${buildDirs.joinToString(File.pathSeparator)}, classpath = $classpath")


if (disableCoroutinesDebug) {
System.setProperty(kotlinx.coroutines.DEBUG_PROPERTY_NAME, kotlinx.coroutines.DEBUG_PROPERTY_VALUE_OFF)
}

timeoutLogger.trace().bracket("Soot initialization") {
SootUtils.runSoot(buildDir, classpath, forceSootReload, jdkInfo)
SootUtils.runSoot(buildDirs, classpath, forceSootReload, jdkInfo)
}

//warmup
Expand Down
174 changes: 70 additions & 104 deletions utbot-framework/src/main/kotlin/org/utbot/framework/util/SootUtils.kt
Original file line number Diff line number Diff line change
@@ -1,41 +1,7 @@
package org.utbot.framework.util

import org.utbot.api.mock.UtMock
import org.utbot.common.FileUtil
import org.utbot.engine.UtNativeStringWrapper
import org.utbot.engine.jimpleBody
import org.utbot.engine.overrides.Boolean
import org.utbot.engine.overrides.Byte
import org.utbot.engine.overrides.Character
import org.utbot.engine.overrides.Class
import org.utbot.engine.overrides.Integer
import org.utbot.engine.overrides.Long
import org.utbot.engine.overrides.PrintStream
import org.utbot.engine.overrides.Short
import org.utbot.engine.overrides.System
import org.utbot.engine.overrides.UtArrayMock
import org.utbot.engine.overrides.UtLogicMock
import org.utbot.engine.overrides.UtOverrideMock
import org.utbot.engine.overrides.collections.AbstractCollection
import org.utbot.engine.overrides.collections.AssociativeArray
import org.utbot.engine.overrides.collections.Collection
import org.utbot.engine.overrides.collections.List
import org.utbot.engine.overrides.collections.RangeModifiableUnlimitedArray
import org.utbot.engine.overrides.collections.UtArrayList
import org.utbot.engine.overrides.collections.UtGenericAssociative
import org.utbot.engine.overrides.collections.UtGenericStorage
import org.utbot.engine.overrides.collections.UtHashMap
import org.utbot.engine.overrides.collections.UtHashSet
import org.utbot.engine.overrides.collections.UtLinkedList
import org.utbot.engine.overrides.collections.UtLinkedListWithNullableCheck
import org.utbot.engine.overrides.collections.UtOptional
import org.utbot.engine.overrides.collections.UtOptionalDouble
import org.utbot.engine.overrides.collections.UtOptionalInt
import org.utbot.engine.overrides.collections.UtOptionalLong
import org.utbot.engine.overrides.stream.*
import org.utbot.engine.overrides.strings.UtString
import org.utbot.engine.overrides.strings.UtStringBuffer
import org.utbot.engine.overrides.strings.UtStringBuilder
import org.utbot.engine.pureJavaSignature
import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.services.JdkInfo
Expand All @@ -56,40 +22,40 @@ object SootUtils {
*
* @param jdkInfo specifies the JRE and the runtime library version used for analysing system classes and user's
* code.
* @param forceReload forces to reinitialize Soot even if the [previousBuildDir] equals to the class buildDir.
* @param forceReload forces to reinitialize Soot even if the [previousBuildDirs] equals to the class buildDir.
*/
fun runSoot(clazz: java.lang.Class<*>, forceReload: kotlin.Boolean, jdkInfo: JdkInfo) {
fun runSoot(clazz: Class<*>, forceReload: Boolean, jdkInfo: JdkInfo) {
val buildDir = FileUtil.locateClassPath(clazz) ?: FileUtil.isolateClassFiles(clazz)
val buildDirPath = buildDir.toPath()

runSoot(buildDirPath, null, forceReload, jdkInfo)
runSoot(listOf(buildDirPath), null, forceReload, jdkInfo)
}


/**
* @param jdkInfo specifies the JRE and the runtime library version used for analysing system classes and user's
* code.
* @param forceReload forces to reinitialize Soot even if the [previousBuildDir] equals to [buildDirPath] and
* @param forceReload forces to reinitialize Soot even if the [previousBuildDirs] equals to [buildDirPaths] and
* [previousClassPath] equals to [classPath].
*/
fun runSoot(buildDirPath: Path, classPath: String?, forceReload: kotlin.Boolean, jdkInfo: JdkInfo) {
fun runSoot(buildDirPaths: List<Path>, classPath: String?, forceReload: Boolean, jdkInfo: JdkInfo) {
synchronized(this) {
if (buildDirPath != previousBuildDir || classPath != previousClassPath || forceReload) {
initSoot(buildDirPath, classPath, jdkInfo)
previousBuildDir = buildDirPath
if (buildDirPaths != previousBuildDirs || classPath != previousClassPath || forceReload) {
initSoot(buildDirPaths, classPath, jdkInfo)
previousBuildDirs = buildDirPaths
previousClassPath = classPath
}
}
}

private var previousBuildDir: Path? = null
private var previousBuildDirs: List<Path>? = null
private var previousClassPath: String? = null
}

/**
* Convert code to Jimple
*/
private fun initSoot(buildDir: Path, classpath: String?, jdkInfo: JdkInfo) {
private fun initSoot(buildDirs: List<Path>, classpath: String?, jdkInfo: JdkInfo) {
G.reset()
val options = Options.v()

Expand All @@ -105,7 +71,7 @@ private fun initSoot(buildDir: Path, classpath: String?, jdkInfo: JdkInfo) {
+ if (!classpath.isNullOrEmpty()) File.pathSeparator + "$classpath" else ""
)
set_src_prec(Options.src_prec_only_class)
set_process_dir(listOf("$buildDir"))
set_process_dir(buildDirs.map { it.toString() })
set_keep_line_number(true)
set_ignore_classpath_errors(true) // gradle/build/resources/main does not exists, but it's not a problem
set_output_format(Options.output_format_jimple)
Expand Down Expand Up @@ -141,69 +107,69 @@ fun jimpleBody(method: ExecutableId): JimpleBody =
method.sootMethod.jimpleBody()


private fun addBasicClasses(vararg classes: java.lang.Class<*>) {
private fun addBasicClasses(vararg classes: Class<*>) {
classes.forEach {
Scene.v().addBasicClass(it.name, SootClass.BODIES)
}
}

private val classesToLoad = arrayOf(
AbstractCollection::class,
UtMock::class,
UtOverrideMock::class,
UtLogicMock::class,
UtArrayMock::class,
Boolean::class,
Byte::class,
Character::class,
Class::class,
Integer::class,
Long::class,
Short::class,
System::class,
UtOptional::class,
UtOptionalInt::class,
UtOptionalLong::class,
UtOptionalDouble::class,
UtArrayList::class,
UtArrayList.UtArrayListIterator::class,
UtLinkedList::class,
UtLinkedListWithNullableCheck::class,
UtLinkedList.UtLinkedListIterator::class,
UtLinkedList.ReverseIteratorWrapper::class,
UtHashSet::class,
UtHashSet.UtHashSetIterator::class,
UtHashMap::class,
UtHashMap.Entry::class,
UtHashMap.LinkedEntryIterator::class,
UtHashMap.LinkedEntrySet::class,
UtHashMap.LinkedHashIterator::class,
UtHashMap.LinkedKeyIterator::class,
UtHashMap.LinkedKeySet::class,
UtHashMap.LinkedValueIterator::class,
UtHashMap.LinkedValues::class,
RangeModifiableUnlimitedArray::class,
AssociativeArray::class,
UtGenericStorage::class,
UtGenericAssociative::class,
PrintStream::class,
UtNativeStringWrapper::class,
UtString::class,
UtStringBuilder::class,
UtStringBuffer::class,
Stream::class,
Arrays::class,
Collection::class,
List::class,
UtStream::class,
UtIntStream::class,
UtLongStream::class,
UtDoubleStream::class,
UtStream.UtStreamIterator::class,
UtIntStream.UtIntStreamIterator::class,
UtLongStream.UtLongStreamIterator::class,
UtDoubleStream.UtDoubleStreamIterator::class,
IntStream::class,
LongStream::class,
DoubleStream::class,
org.utbot.engine.overrides.collections.AbstractCollection::class,
org.utbot.api.mock.UtMock::class,
org.utbot.engine.overrides.UtOverrideMock::class,
org.utbot.engine.overrides.UtLogicMock::class,
org.utbot.engine.overrides.UtArrayMock::class,
org.utbot.engine.overrides.Boolean::class,
org.utbot.engine.overrides.Byte::class,
org.utbot.engine.overrides.Character::class,
org.utbot.engine.overrides.Class::class,
org.utbot.engine.overrides.Integer::class,
org.utbot.engine.overrides.Long::class,
org.utbot.engine.overrides.Short::class,
org.utbot.engine.overrides.System::class,
org.utbot.engine.overrides.collections.UtOptional::class,
org.utbot.engine.overrides.collections.UtOptionalInt::class,
org.utbot.engine.overrides.collections.UtOptionalLong::class,
org.utbot.engine.overrides.collections.UtOptionalDouble::class,
org.utbot.engine.overrides.collections.UtArrayList::class,
org.utbot.engine.overrides.collections.UtArrayList.UtArrayListIterator::class,
org.utbot.engine.overrides.collections.UtLinkedList::class,
org.utbot.engine.overrides.collections.UtLinkedListWithNullableCheck::class,
org.utbot.engine.overrides.collections.UtLinkedList.UtLinkedListIterator::class,
org.utbot.engine.overrides.collections.UtLinkedList.ReverseIteratorWrapper::class,
org.utbot.engine.overrides.collections.UtHashSet::class,
org.utbot.engine.overrides.collections.UtHashSet.UtHashSetIterator::class,
org.utbot.engine.overrides.collections.UtHashMap::class,
org.utbot.engine.overrides.collections.UtHashMap.Entry::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedEntryIterator::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedEntrySet::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedHashIterator::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedKeyIterator::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedKeySet::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedValueIterator::class,
org.utbot.engine.overrides.collections.UtHashMap.LinkedValues::class,
org.utbot.engine.overrides.collections.RangeModifiableUnlimitedArray::class,
org.utbot.engine.overrides.collections.AssociativeArray::class,
org.utbot.engine.overrides.collections.UtGenericStorage::class,
org.utbot.engine.overrides.collections.UtGenericAssociative::class,
org.utbot.engine.overrides.PrintStream::class,
org.utbot.engine.UtNativeStringWrapper::class,
org.utbot.engine.overrides.strings.UtString::class,
org.utbot.engine.overrides.strings.UtStringBuilder::class,
org.utbot.engine.overrides.strings.UtStringBuffer::class,
org.utbot.engine.overrides.stream.Stream::class,
org.utbot.engine.overrides.stream.Arrays::class,
org.utbot.engine.overrides.collections.Collection::class,
org.utbot.engine.overrides.collections.List::class,
org.utbot.engine.overrides.stream.UtStream::class,
org.utbot.engine.overrides.stream.UtIntStream::class,
org.utbot.engine.overrides.stream.UtLongStream::class,
org.utbot.engine.overrides.stream.UtDoubleStream::class,
org.utbot.engine.overrides.stream.UtStream.UtStreamIterator::class,
org.utbot.engine.overrides.stream.UtIntStream.UtIntStreamIterator::class,
org.utbot.engine.overrides.stream.UtLongStream.UtLongStreamIterator::class,
org.utbot.engine.overrides.stream.UtDoubleStream.UtDoubleStreamIterator::class,
org.utbot.engine.overrides.stream.IntStream::class,
org.utbot.engine.overrides.stream.LongStream::class,
org.utbot.engine.overrides.stream.DoubleStream::class,
).map { it.java }.toTypedArray()
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class TestSpecificTestCaseGenerator(
engineActions: MutableList<(UtBotSymbolicEngine) -> Unit> = mutableListOf(),
isCanceled: () -> Boolean = { false },
): TestCaseGenerator(
buildDir,
listOf(buildDir),
classpath,
dependencyPaths,
JdkInfoDefaultProvider().info,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ open class GenerateTestsAndSarifReportTask @Inject constructor(
withUtContext(UtContext(sourceSet.classLoader)) {
val testCaseGenerator =
TestCaseGenerator(
sourceSet.workingDirectory,
listOf(sourceSet.workingDirectory),
sourceSet.runtimeClasspath,
dependencyPaths,
JdkInfoDefaultProvider().info
Expand Down
Loading