From e2e53f2710b5c56e5b322112a0cc098e5b85ce7f Mon Sep 17 00:00:00 2001 From: Vassiliy-Kudryashov Date: Thu, 17 Nov 2022 10:06:32 +0300 Subject: [PATCH 01/16] Convert 'UTSettings.kt' into '.utbot/settings.properties' Experiments with Gradle tasks --- utbot-intellij/build.gradle.kts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index 4539792843..c3b8bede72 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -61,6 +61,29 @@ intellij { version.set(ideVersion) type.set(ideTypeOrAndroidStudio) } +abstract class SettingsToConfigTask : DefaultTask() { + @get:Internal + val path = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") + @get:Internal + val sourceFileName = "UTSettings.kt" + + @TaskAction + fun proceed() { + try { + File(path,sourceFileName).useLines { + it.iterator().forEach { line -> + if (line.startsWith(" var")) { + println(line.substring(7)) + } + } + } + } catch (e : java.io.IOException) { + logger.error("Unexpected error when processing $sourceFileName", e) + } + } +} + +tasks.register("generateConfigTemplate") tasks { compileKotlin { From 0fc356d1f73e1ee2d4238e86e0bc5a8e0c6493fa Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 17 Nov 2022 21:03:27 +0300 Subject: [PATCH 02/16] Parsing UtSettings.kt line by line to get name, type, possible values, documentation --- utbot-intellij/build.gradle.kts | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index c3b8bede72..1deaf96510 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -83,6 +83,52 @@ abstract class SettingsToConfigTask : DefaultTask() { } } +abstract class SettingsToConfigTask : DefaultTask() { + @get:Internal + val path = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") + @get:Internal + val sourceFileName = "UTSettings.kt" + + @TaskAction + fun proceed() { + try { + val docLines = mutableListOf() + File(path, sourceFileName).useLines { + it.iterator().forEach { line -> + var s = line.trim() + if (s == "/**") { + docLines.clear() + } + if (s.startsWith("* ")) { + docLines.add(s.substring(2)) + } + + if (s.startsWith("var")) { +// println(s.substring(3)) + var i = s.indexOf(" by ", 3) + if (i > 0) { + val propertyName = s.substring(0, i) + s = s.substring(i + 7) + i = s.indexOf("Property") + if (i > 0) { + val type = s.subSequence(0, i) + println("$propertyName: $type") + for (docLine in docLines) { + println(" |$docLine") + } + } + } else { + System.err.println(s) + } + } + } + } + } catch (e : java.io.IOException) { + logger.error("Unexpected error when processing $sourceFileName", e) + } + } +} + tasks.register("generateConfigTemplate") tasks { From e397cda62946143dd1a7fe03df3fbba0e03badad Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 17 Nov 2022 21:03:53 +0300 Subject: [PATCH 03/16] Misprint --- utbot-intellij/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index 1deaf96510..a2127cc5ba 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -87,7 +87,7 @@ abstract class SettingsToConfigTask : DefaultTask() { @get:Internal val path = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") @get:Internal - val sourceFileName = "UTSettings.kt" + val sourceFileName = "UtSettings.kt" @TaskAction fun proceed() { From bfda1decc7cd16589b1e61fa591804a92f2f1f82 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 18 Nov 2022 21:17:34 +0300 Subject: [PATCH 04/16] Grade task "generateConfigTemplate" UTSettings.kt -> settings.properties, first iteration with several yet-not-parsed (skipped) properties --- utbot-intellij/build.gradle.kts | 97 +++--- .../src/main/resources/settings.properties | 309 ++++++++++++++++++ 2 files changed, 365 insertions(+), 41 deletions(-) create mode 100644 utbot-intellij/src/main/resources/settings.properties diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index a2127cc5ba..8fc00ff496 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -1,3 +1,6 @@ +import java.io.ByteArrayOutputStream +import java.io.PrintWriter + val intellijPluginVersion: String? by rootProject val kotlinLoggingVersion: String? by rootProject val apacheCommonsTextVersion: String? by rootProject @@ -61,67 +64,79 @@ intellij { version.set(ideVersion) type.set(ideTypeOrAndroidStudio) } -abstract class SettingsToConfigTask : DefaultTask() { - @get:Internal - val path = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") - @get:Internal - val sourceFileName = "UTSettings.kt" - - @TaskAction - fun proceed() { - try { - File(path,sourceFileName).useLines { - it.iterator().forEach { line -> - if (line.startsWith(" var")) { - println(line.substring(7)) - } - } - } - } catch (e : java.io.IOException) { - logger.error("Unexpected error when processing $sourceFileName", e) - } - } -} abstract class SettingsToConfigTask : DefaultTask() { @get:Internal - val path = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") + val settingsSourceDir = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") @get:Internal val sourceFileName = "UtSettings.kt" + @get:Internal + val settingsResourceDir = File(project.buildDir.parentFile.parentFile, "utbot-intellij/src/main/resources/") + @get:Internal + val settingsFileName = "settings.properties" @TaskAction fun proceed() { try { + val constMap = mutableMapOf() + val acc = StringBuilder() val docLines = mutableListOf() - File(path, sourceFileName).useLines { + val byteArrayOutputStream = ByteArrayOutputStream() + val writer = PrintWriter(byteArrayOutputStream) + File(settingsSourceDir, sourceFileName).useLines { it.iterator().forEach { line -> var s = line.trim() - if (s == "/**") { + if (s.startsWith("const val ")) { + val pos = s.indexOf(" = ") + constMap[s.substring(10, pos)] = s.substring(pos + 3) + } else if (s == "/**") { docLines.clear() - } - if (s.startsWith("* ")) { + } else if (s.startsWith("* ")) { docLines.add(s.substring(2)) - } - - if (s.startsWith("var")) { -// println(s.substring(3)) - var i = s.indexOf(" by ", 3) - if (i > 0) { - val propertyName = s.substring(0, i) - s = s.substring(i + 7) - i = s.indexOf("Property") + } else if (s.startsWith("var")) { + acc.clear() + acc.append(s) + } else if (s.isEmpty() && !acc.isEmpty()) { + s = acc.toString() + acc.clear() + if (s.startsWith("var")) { + var i = s.indexOf(" by ", 3) if (i > 0) { - val type = s.subSequence(0, i) - println("$propertyName: $type") - for (docLine in docLines) { - println(" |$docLine") + var propertyName = s.substring(3, i).trim() + if (propertyName.contains(':')) { + propertyName = propertyName.substring(0, propertyName.lastIndexOf(':')) + } + s = s.substring(i + 7) + i = s.indexOf("Property") + if (i > 0) { + val type = s.subSequence(0, i) + i = s.indexOf('(', i) + if (i > 0) { + s = s.substring(i + 1) + var defaultValue = s.substring(0, s.indexOf(')')) + defaultValue = constMap[defaultValue] ?:defaultValue + if (byteArrayOutputStream.size() > 0) { + writer.println() + writer.println("#") + } + for (docLine in docLines) { + writer.println("# $docLine") + } + writer.println("$propertyName=$defaultValue") + writer.flush() + } } + } else { + System.err.println(s) } - } else { - System.err.println(s) } + } else if (acc.isNotEmpty()) { + acc.append(" $s") } } + writer.flush() + writer.close() + File(settingsResourceDir, settingsFileName).writeBytes(byteArrayOutputStream.toByteArray()) } } catch (e : java.io.IOException) { logger.error("Unexpected error when processing $sourceFileName", e) diff --git a/utbot-intellij/src/main/resources/settings.properties b/utbot-intellij/src/main/resources/settings.properties new file mode 100644 index 0000000000..4607fd8c32 --- /dev/null +++ b/utbot-intellij/src/main/resources/settings.properties @@ -0,0 +1,309 @@ +# Setting to disable coroutines debug explicitly. +# True by default, set it to false if debug info is required. +disableCoroutinesDebug=true + +# +# Make `true` for interactive mode (like Intellij plugin). If `false` UTBot can apply certain optimizations. +classfilesCanChange=true + +# +# Timeout for Z3 solver.check calls. +# Set it to 0 to disable timeout. +checkSolverTimeoutMillis=1000 + +# +# Timeout for symbolic execution +utBotGenerationTimeoutInMillis=60000L + +# +# Type of path selector. +pathSelectorType=PathSelectorType.INHERITORS_SELECTOR + +# +# Type of MLSelector recalculation. +mlSelectorRecalculationType=MLSelectorRecalculationType.WITHOUT_RECALCULATION + +# +# Type of [MLPredictor]. +mlPredictorType=MLPredictorType.MLP + +# +# Steps limit for path selector. +pathSelectorStepsLimit=3500 + +# +# Determines whether path selector should save remaining states for concrete execution after stopping by strategy. +# False for all framework tests by default. +saveRemainingStatesForConcreteExecution=true + +# +# Use debug visualization. +# False by default, set it to true if debug visualization is needed. +useDebugVisualization=false + +# +# Method is paused after this timeout to give an opportunity other methods +# to work +timeslotForOneToplevelMethodTraversalMs=2000 + +# +# Use simplification of UtExpressions. +# True by default, set it to false to disable expression simplification. +# @see +# UtBot Expression Optimizations +useExpressionSimplification=true + +# +# Use simplification of UtExpressions. +# True by default, set it to false to disable expression simplification. +# @see +# UtBot Expression Optimizations +# Activate or deactivate tests on comments && names/displayNames +# */ +testDisplayName=true + +# +# Generate summaries using plugin's custom JavaDoc tags. +useCustomJavaDocTags=true + +# +# Enable the Summarization module to generate summaries for methods under test. +# True by default. +# Note: if it is false, all the execution for a particular method will be stored at the same nameless region. +enableSummariesGeneration=true + +# +# Options below regulate which [NullPointerException] check should be performed. +# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. +checkNpeInNestedNotPrivateMethods=false + +# +# This option determines whether we should generate [NullPointerException] checks for final or non-public fields +# in non-application classes. Set by true, this option highly decreases test's readability in some cases +# because of using reflection API for setting final/non-public fields in non-application classes. +# NOTE: default false value loses some executions with NPE in system classes, but often most of these executions +# are not expected by user. +maximizeCoverageUsingReflection=false + +# +# Activate or deactivate substituting static fields values set in static initializer +# with symbolic variable to try to set them another value than in initializer. +substituteStaticsWithSymbolicVariable=true + +# +# Use concrete execution. +# True by default. +useConcreteExecution=true + +# +# Enable check of full coverage for methods with code generations tests. +# TODO doesn't work for now JIRA:1407 +checkCoverageInCodeGenerationTests=true + +# +# Enable code generation tests with every possible configuration +# for every method in samples. +# Important: disabled by default. This check requires enormous amount of time. +checkAllCombinationsForEveryTestInSamples=false + +# +# Enable transformation UtCompositeModels into UtAssembleModels using AssembleModelGenerator. +# True by default. +# Note: false doesn't mean that there will be no assemble models, it means that the generator will be turned off. +# Assemble models will present for lists, sets, etc. +useAssembleModelGenerator=true + +# +# Test related files from the temp directory that are older than [daysLimitForTempFiles] +# will be removed at the beginning of the test run. +daysLimitForTempFiles=3 + +# +# Enables soft constraints in the engine. +# True by default. +preferredCexOption=true + +# +# Type of test minimization strategy. +testMinimizationStrategyType=TestSelectionStrategyType.COVERAGE_STRATEGY + +# +# Set to true to start fuzzing if symbolic execution haven't return anything +useFuzzing=true + +# +# Set the total attempts to improve coverage by fuzzer. +fuzzingMaxAttempts=Int.MAX_VALUE + +# +# Fuzzer tries to generate and run tests during this time. +fuzzingTimeoutInMillis=3_000L + +# +# Generate tests that treat possible overflows in arithmetic operations as errors +# that throw Arithmetic Exception. +# False by default. +treatOverflowAsError=false + +# +# Generate tests that treat assertions as error suits. +# True by default. +treatAssertAsErrorSuit=true + +# +# Instrument all classes before start +warmupConcreteExecution=false + +# +# Ignore string literals during the code analysis to make possible to analyze antlr. +# It is a hack and must be removed after the competition. +ignoreStringLiterals=false + +# +# Timeout for specific concrete execution (in milliseconds). +concreteExecutionTimeoutInChildProcess= DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS + +# +# Log level for engine process, which started in idea on generate tests action. +engineProcessLogLevel=LogLevel.Info + +# +# Log level for concrete executor process. +childProcessLogLevel=LogLevel.Info + +# +# Determines whether should errors from a child process be written to a log file or suppressed. +# Note: being enabled, this option can highly increase disk usage when using ContestEstimator. +# False by default (for saving disk space). +logConcreteExecutionErrors=false + +# +# Property useful only for idea +# If true - runs engine process with the ability to attach a debugger +# @see runChildProcessWithDebug +# @see org.utbot.intellij.plugin.process.EngineProcess +runIdeaProcessWithDebug=false + +# +# If true, runs the child process with the ability to attach a debugger. +# To debug the child process, set the breakpoint in the childProcessRunner.start() line +# and in the child process's main function and run the main process. +# Then run the remote JVM debug configuration in IDEA. +# If you see the message in console about successful connection, then +# the debugger is attached successfully. +# Now you can put the breakpoints in the child process and debug +# both processes simultaneously. +# @see [org.utbot.instrumentation.process.ChildProcessRunner.cmds] +runChildProcessWithDebug=false + +# +# Number of branch instructions using for clustering executions in the test minimization phase. +numberOfBranchInstructionsForClustering=4 + +# +# Determines should we choose only one crash execution with "minimal" model or keep all. +minimizeCrashExecutions=true + +# +# Enable it to calculate unsat cores for hard constraints as well. +# It may be usefull during debug. +# Note: it might highly impact performance, so do not enable it in release mode. +# False by default. +enableUnsatCoreCalculationForHardConstraints=false + +# +# Enable it to process states with unknown solver status +# from the queue to concrete execution. +# True by default. +processUnknownStatesDuringConcreteExecution=true + +# +# 2^{this} will be the length of observed subpath. +# See [SubpathGuidedSelector] +subpathGuidedSelectorIndex=1 + +# +# Flag that indicates whether feature processing for execution states enabled or not +enableFeatureProcess=false + +# +# Path to deserialized ML models +modelPath="../models/0" + +# +# Full class name of the class containing the configuration for the ML models to solve path selection task. +analyticsConfigurationClassPath="org.utbot.AnalyticsConfiguration" + +# +# Full class name of the class containing the configuration for the ML models exported from the PyTorch to solve path selection task. +analyticsTorchConfigurationClassPath="org.utbot.AnalyticsTorchConfiguration" + +# +# Number of model iterations that will be used during ContestEstimator +iterations=1 + +# +# Path for state features dir +featurePath="eval/secondFeatures/antlr/INHERITORS_SELECTOR" + +# +# Counter for tests during testGeneration for one project in ContestEstimator +testCounter=0 + +# +# Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models) +singleSelector=true + +# +# Flag that indicates whether tests for synthetic (see [Executable.isSynthetic]) and implicitly declared methods (like values, valueOf in enums) should be generated, or not +skipTestGenerationForSyntheticAndImplicitlyDeclaredMethods=true + +# +# Flag that indicates whether should we branch on and set static fields from trusted libraries or not. +# @see [org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES] +ignoreStaticsFromTrustedLibraries=true + +# +# Use the sandbox in the concrete executor. +# If true (default), the sandbox will prevent potentially dangerous calls, e.g., file access, reading +# or modifying the environment, calls to `Unsafe` methods etc. +# If false, all these operations will be enabled and may lead to data loss during code analysis +# and test generation. +useSandbox=true + +# +# Limit for number of generated tests per method (in each region) +maxTestsPerMethodInRegion=50 + +# +# If this options set in true, all soot classes will be removed from a Soot Scene, +# therefore, you will be unable to test soot classes. +removeSootClassesFromHierarchy=true + +# +# If this options set in true, all UtBot classes will be removed from a Soot Scene, +# therefore, you will be unable to test UtBot classes. +removeUtBotClassesFromHierarchy=true + +# +# Use this option to enable calculation and logging of MD5 for dropped states by statistics. +# Example of such logging: +# Dropping state (lastStatus=UNDEFINED) by the distance statistics. MD5: 5d0bccc242e87d53578ca0ef64aa5864 +# Default value is false. +enableLoggingForDroppedStates=false + +# +# If this option set in true, depending on the number of possible types for +# a particular object will be used either type system based on conjunction +# or on bit vectors. +# @see useBitVecBasedTypeSystem +useBitVecBasedTypeSystem=true + +# +# The number of types on which the choice of the type system depends. +maxTypeNumberForEnumeration=64 + +# +# The threshold for numbers of types for which they will be encoded into solver. +# It is used to do not encode big type storages due to significand performance degradation. +maxNumberOfTypesToEncode=512 From 5e567df8b851824dd82a80c3e3b34557ddbe26eb Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 18 Nov 2022 21:21:54 +0300 Subject: [PATCH 05/16] Add TODOs for myself --- utbot-intellij/build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index 8fc00ff496..94b7eaa14c 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -114,7 +114,10 @@ abstract class SettingsToConfigTask : DefaultTask() { if (i > 0) { s = s.substring(i + 1) var defaultValue = s.substring(0, s.indexOf(')')) + //TODO DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS -> 1000L defaultValue = constMap[defaultValue] ?:defaultValue + //TODO remove class names for Enum type + //TODO get documentation from Enum values to property key documentation if (byteArrayOutputStream.size() > 0) { writer.println() writer.println("#") From e5b879ca69323dd32ab5744d074710216d0ffa2b Mon Sep 17 00:00:00 2001 From: Vassiliy-Kudryashov Date: Sun, 20 Nov 2022 13:52:01 +0300 Subject: [PATCH 06/16] Implementation of added TODOs --- .../kotlin/org/utbot/framework/UtSettings.kt | 12 - utbot-intellij/build.gradle.kts | 99 ++++-- .../src/main/resources/settings.properties | 309 ------------------ .../utbot/testing/UtValueTestCaseChecker.kt | 5 - 4 files changed, 75 insertions(+), 350 deletions(-) delete mode 100644 utbot-intellij/src/main/resources/settings.properties diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index 2ac46750e2..1a376f9073 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -173,13 +173,6 @@ object UtSettings : AbstractSettings( */ var useConcreteExecution by getBooleanProperty(true) - /** - * Enable check of full coverage for methods with code generations tests. - * - * TODO doesn't work for now JIRA:1407 - */ - var checkCoverageInCodeGenerationTests by getBooleanProperty(true) - /** * Enable code generation tests with every possible configuration * for every method in samples. @@ -340,11 +333,6 @@ object UtSettings : AbstractSettings( */ var subpathGuidedSelectorIndex by getIntProperty(1) - /** - * Set of indexes, which will use [SubpathGuidedSelector] in not single mode - */ - var subpathGuidedSelectorIndexes = listOf(0, 1, 2, 3) - /** * Flag that indicates whether feature processing for execution states enabled or not */ diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index 94b7eaa14c..bb3e08c57d 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import java.io.ByteArrayOutputStream import java.io.PrintWriter @@ -75,20 +76,40 @@ abstract class SettingsToConfigTask : DefaultTask() { @get:Internal val settingsFileName = "settings.properties" + data class PropertyModel( + val key: String, + var type: String = "", + var defaultValue: String = "", + var docLines: MutableList = mutableListOf() + ) + + data class EnumInfo(var className: String, var docMap: MutableMap> = linkedMapOf()) + @TaskAction fun proceed() { try { - val constMap = mutableMapOf() + val dictionary = mutableMapOf().also { + it["Int.MAX_VALUE"] = Int.MAX_VALUE.toString() + } + val models = mutableListOf() + val enums = mutableListOf() + val acc = StringBuilder() val docLines = mutableListOf() val byteArrayOutputStream = ByteArrayOutputStream() val writer = PrintWriter(byteArrayOutputStream) - File(settingsSourceDir, sourceFileName).useLines { + File(settingsSourceDir, sourceFileName).useLines { it -> it.iterator().forEach { line -> var s = line.trim() - if (s.startsWith("const val ")) { + if (s.startsWith("enum class ")) { + enums.add(EnumInfo(s.substring(11, s.length - 2))) + } else if (s.matches(Regex("[A-Z_]+,?")) && enums.isNotEmpty()) { + var enumValue = s.substring(0, s.length - 1) + if (enumValue.endsWith(",")) enumValue = enumValue.substring(0, enumValue.length - 1) + enums.last().docMap[enumValue] = docLines.toMutableList() + } else if (s.startsWith("const val ")) { val pos = s.indexOf(" = ") - constMap[s.substring(10, pos)] = s.substring(pos + 3) + dictionary[s.substring(10, pos)] = s.substring(pos + 3) } else if (s == "/**") { docLines.clear() } else if (s.startsWith("* ")) { @@ -96,39 +117,44 @@ abstract class SettingsToConfigTask : DefaultTask() { } else if (s.startsWith("var")) { acc.clear() acc.append(s) - } else if (s.isEmpty() && !acc.isEmpty()) { + } else if (s.isEmpty() && acc.isNotEmpty()) { s = acc.toString() acc.clear() if (s.startsWith("var")) { var i = s.indexOf(" by ", 3) if (i > 0) { - var propertyName = s.substring(3, i).trim() - if (propertyName.contains(':')) { - propertyName = propertyName.substring(0, propertyName.lastIndexOf(':')) + var key = s.substring(3, i).trim() + if (key.contains(':')) { + key = key.substring(0, key.lastIndexOf(':')) } + val model = PropertyModel(key) + models.add(model) s = s.substring(i + 7) i = s.indexOf("Property") - if (i > 0) { - val type = s.subSequence(0, i) + if (i > 0) model.type = s.substring(0, i) + if (i == 0) { + i = s.indexOf('<', i) + if (i != -1) { + s = s.substring(i+1) + i = s.indexOf('>') + if (i != -1) { + model.type = s.substring(0, i) + } + } + } + i = s.indexOf('(', i) if (i > 0) { s = s.substring(i + 1) - var defaultValue = s.substring(0, s.indexOf(')')) - //TODO DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS -> 1000L - defaultValue = constMap[defaultValue] ?:defaultValue - //TODO remove class names for Enum type - //TODO get documentation from Enum values to property key documentation - if (byteArrayOutputStream.size() > 0) { - writer.println() - writer.println("#") + var defaultValue = s.substring(0, s.indexOf(')')).trim() + if (defaultValue.contains(',')) defaultValue = defaultValue.substring(0, defaultValue.indexOf(',')) + defaultValue = dictionary[defaultValue] ?:defaultValue + if (defaultValue.matches(Regex("[\\d_]+L"))) { + defaultValue = defaultValue.substring(0, defaultValue.length - 1).replace("_", "") } - for (docLine in docLines) { - writer.println("# $docLine") - } - writer.println("$propertyName=$defaultValue") - writer.flush() + model.defaultValue = defaultValue + model.docLines.addAll(docLines) } - } } else { System.err.println(s) } @@ -137,6 +163,31 @@ abstract class SettingsToConfigTask : DefaultTask() { acc.append(" $s") } } + for (model in models) { + if (model.type == "Enum") { + val split = model.defaultValue.split('.') + if (split.size > 1) { + model.defaultValue = split[1] + val enumInfo = enums.find { info -> info.className == split[0] } + enumInfo?.docMap?.forEach { + model.docLines.add(it.key) + it.value.forEach { line -> model.docLines.add(line) } + } + } + } + if (byteArrayOutputStream.size() > 0) { + writer.println() + writer.println("#") + } + for (docLine in model.docLines) { + writer.println("# $docLine") + } + if (!model.docLines.any({ s -> s.toLowerCaseAsciiOnly().contains("default") })) { + writer.println("# ${model.defaultValue} by default") + } + writer.println("${model.key}=${model.defaultValue}") + writer.flush() + } writer.flush() writer.close() File(settingsResourceDir, settingsFileName).writeBytes(byteArrayOutputStream.toByteArray()) diff --git a/utbot-intellij/src/main/resources/settings.properties b/utbot-intellij/src/main/resources/settings.properties deleted file mode 100644 index 4607fd8c32..0000000000 --- a/utbot-intellij/src/main/resources/settings.properties +++ /dev/null @@ -1,309 +0,0 @@ -# Setting to disable coroutines debug explicitly. -# True by default, set it to false if debug info is required. -disableCoroutinesDebug=true - -# -# Make `true` for interactive mode (like Intellij plugin). If `false` UTBot can apply certain optimizations. -classfilesCanChange=true - -# -# Timeout for Z3 solver.check calls. -# Set it to 0 to disable timeout. -checkSolverTimeoutMillis=1000 - -# -# Timeout for symbolic execution -utBotGenerationTimeoutInMillis=60000L - -# -# Type of path selector. -pathSelectorType=PathSelectorType.INHERITORS_SELECTOR - -# -# Type of MLSelector recalculation. -mlSelectorRecalculationType=MLSelectorRecalculationType.WITHOUT_RECALCULATION - -# -# Type of [MLPredictor]. -mlPredictorType=MLPredictorType.MLP - -# -# Steps limit for path selector. -pathSelectorStepsLimit=3500 - -# -# Determines whether path selector should save remaining states for concrete execution after stopping by strategy. -# False for all framework tests by default. -saveRemainingStatesForConcreteExecution=true - -# -# Use debug visualization. -# False by default, set it to true if debug visualization is needed. -useDebugVisualization=false - -# -# Method is paused after this timeout to give an opportunity other methods -# to work -timeslotForOneToplevelMethodTraversalMs=2000 - -# -# Use simplification of UtExpressions. -# True by default, set it to false to disable expression simplification. -# @see -# UtBot Expression Optimizations -useExpressionSimplification=true - -# -# Use simplification of UtExpressions. -# True by default, set it to false to disable expression simplification. -# @see -# UtBot Expression Optimizations -# Activate or deactivate tests on comments && names/displayNames -# */ -testDisplayName=true - -# -# Generate summaries using plugin's custom JavaDoc tags. -useCustomJavaDocTags=true - -# -# Enable the Summarization module to generate summaries for methods under test. -# True by default. -# Note: if it is false, all the execution for a particular method will be stored at the same nameless region. -enableSummariesGeneration=true - -# -# Options below regulate which [NullPointerException] check should be performed. -# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. -checkNpeInNestedNotPrivateMethods=false - -# -# This option determines whether we should generate [NullPointerException] checks for final or non-public fields -# in non-application classes. Set by true, this option highly decreases test's readability in some cases -# because of using reflection API for setting final/non-public fields in non-application classes. -# NOTE: default false value loses some executions with NPE in system classes, but often most of these executions -# are not expected by user. -maximizeCoverageUsingReflection=false - -# -# Activate or deactivate substituting static fields values set in static initializer -# with symbolic variable to try to set them another value than in initializer. -substituteStaticsWithSymbolicVariable=true - -# -# Use concrete execution. -# True by default. -useConcreteExecution=true - -# -# Enable check of full coverage for methods with code generations tests. -# TODO doesn't work for now JIRA:1407 -checkCoverageInCodeGenerationTests=true - -# -# Enable code generation tests with every possible configuration -# for every method in samples. -# Important: disabled by default. This check requires enormous amount of time. -checkAllCombinationsForEveryTestInSamples=false - -# -# Enable transformation UtCompositeModels into UtAssembleModels using AssembleModelGenerator. -# True by default. -# Note: false doesn't mean that there will be no assemble models, it means that the generator will be turned off. -# Assemble models will present for lists, sets, etc. -useAssembleModelGenerator=true - -# -# Test related files from the temp directory that are older than [daysLimitForTempFiles] -# will be removed at the beginning of the test run. -daysLimitForTempFiles=3 - -# -# Enables soft constraints in the engine. -# True by default. -preferredCexOption=true - -# -# Type of test minimization strategy. -testMinimizationStrategyType=TestSelectionStrategyType.COVERAGE_STRATEGY - -# -# Set to true to start fuzzing if symbolic execution haven't return anything -useFuzzing=true - -# -# Set the total attempts to improve coverage by fuzzer. -fuzzingMaxAttempts=Int.MAX_VALUE - -# -# Fuzzer tries to generate and run tests during this time. -fuzzingTimeoutInMillis=3_000L - -# -# Generate tests that treat possible overflows in arithmetic operations as errors -# that throw Arithmetic Exception. -# False by default. -treatOverflowAsError=false - -# -# Generate tests that treat assertions as error suits. -# True by default. -treatAssertAsErrorSuit=true - -# -# Instrument all classes before start -warmupConcreteExecution=false - -# -# Ignore string literals during the code analysis to make possible to analyze antlr. -# It is a hack and must be removed after the competition. -ignoreStringLiterals=false - -# -# Timeout for specific concrete execution (in milliseconds). -concreteExecutionTimeoutInChildProcess= DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS - -# -# Log level for engine process, which started in idea on generate tests action. -engineProcessLogLevel=LogLevel.Info - -# -# Log level for concrete executor process. -childProcessLogLevel=LogLevel.Info - -# -# Determines whether should errors from a child process be written to a log file or suppressed. -# Note: being enabled, this option can highly increase disk usage when using ContestEstimator. -# False by default (for saving disk space). -logConcreteExecutionErrors=false - -# -# Property useful only for idea -# If true - runs engine process with the ability to attach a debugger -# @see runChildProcessWithDebug -# @see org.utbot.intellij.plugin.process.EngineProcess -runIdeaProcessWithDebug=false - -# -# If true, runs the child process with the ability to attach a debugger. -# To debug the child process, set the breakpoint in the childProcessRunner.start() line -# and in the child process's main function and run the main process. -# Then run the remote JVM debug configuration in IDEA. -# If you see the message in console about successful connection, then -# the debugger is attached successfully. -# Now you can put the breakpoints in the child process and debug -# both processes simultaneously. -# @see [org.utbot.instrumentation.process.ChildProcessRunner.cmds] -runChildProcessWithDebug=false - -# -# Number of branch instructions using for clustering executions in the test minimization phase. -numberOfBranchInstructionsForClustering=4 - -# -# Determines should we choose only one crash execution with "minimal" model or keep all. -minimizeCrashExecutions=true - -# -# Enable it to calculate unsat cores for hard constraints as well. -# It may be usefull during debug. -# Note: it might highly impact performance, so do not enable it in release mode. -# False by default. -enableUnsatCoreCalculationForHardConstraints=false - -# -# Enable it to process states with unknown solver status -# from the queue to concrete execution. -# True by default. -processUnknownStatesDuringConcreteExecution=true - -# -# 2^{this} will be the length of observed subpath. -# See [SubpathGuidedSelector] -subpathGuidedSelectorIndex=1 - -# -# Flag that indicates whether feature processing for execution states enabled or not -enableFeatureProcess=false - -# -# Path to deserialized ML models -modelPath="../models/0" - -# -# Full class name of the class containing the configuration for the ML models to solve path selection task. -analyticsConfigurationClassPath="org.utbot.AnalyticsConfiguration" - -# -# Full class name of the class containing the configuration for the ML models exported from the PyTorch to solve path selection task. -analyticsTorchConfigurationClassPath="org.utbot.AnalyticsTorchConfiguration" - -# -# Number of model iterations that will be used during ContestEstimator -iterations=1 - -# -# Path for state features dir -featurePath="eval/secondFeatures/antlr/INHERITORS_SELECTOR" - -# -# Counter for tests during testGeneration for one project in ContestEstimator -testCounter=0 - -# -# Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models) -singleSelector=true - -# -# Flag that indicates whether tests for synthetic (see [Executable.isSynthetic]) and implicitly declared methods (like values, valueOf in enums) should be generated, or not -skipTestGenerationForSyntheticAndImplicitlyDeclaredMethods=true - -# -# Flag that indicates whether should we branch on and set static fields from trusted libraries or not. -# @see [org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES] -ignoreStaticsFromTrustedLibraries=true - -# -# Use the sandbox in the concrete executor. -# If true (default), the sandbox will prevent potentially dangerous calls, e.g., file access, reading -# or modifying the environment, calls to `Unsafe` methods etc. -# If false, all these operations will be enabled and may lead to data loss during code analysis -# and test generation. -useSandbox=true - -# -# Limit for number of generated tests per method (in each region) -maxTestsPerMethodInRegion=50 - -# -# If this options set in true, all soot classes will be removed from a Soot Scene, -# therefore, you will be unable to test soot classes. -removeSootClassesFromHierarchy=true - -# -# If this options set in true, all UtBot classes will be removed from a Soot Scene, -# therefore, you will be unable to test UtBot classes. -removeUtBotClassesFromHierarchy=true - -# -# Use this option to enable calculation and logging of MD5 for dropped states by statistics. -# Example of such logging: -# Dropping state (lastStatus=UNDEFINED) by the distance statistics. MD5: 5d0bccc242e87d53578ca0ef64aa5864 -# Default value is false. -enableLoggingForDroppedStates=false - -# -# If this option set in true, depending on the number of possible types for -# a particular object will be used either type system based on conjunction -# or on bit vectors. -# @see useBitVecBasedTypeSystem -useBitVecBasedTypeSystem=true - -# -# The number of types on which the choice of the type system depends. -maxTypeNumberForEnumeration=64 - -# -# The threshold for numbers of types for which they will be encoded into solver. -# It is used to do not encode big type storages due to significand performance degradation. -maxNumberOfTypesToEncode=512 diff --git a/utbot-testing/src/main/kotlin/org/utbot/testing/UtValueTestCaseChecker.kt b/utbot-testing/src/main/kotlin/org/utbot/testing/UtValueTestCaseChecker.kt index 190d76654d..eb3812898b 100644 --- a/utbot-testing/src/main/kotlin/org/utbot/testing/UtValueTestCaseChecker.kt +++ b/utbot-testing/src/main/kotlin/org/utbot/testing/UtValueTestCaseChecker.kt @@ -9,7 +9,6 @@ import org.utbot.common.FileUtil.findPathToClassFiles import org.utbot.common.FileUtil.locateClass import org.utbot.engine.prettify import org.utbot.framework.UtSettings -import org.utbot.framework.UtSettings.checkCoverageInCodeGenerationTests import org.utbot.framework.UtSettings.daysLimitForTempFiles import org.utbot.framework.UtSettings.testDisplayName import org.utbot.framework.UtSettings.testName @@ -2403,10 +2402,6 @@ abstract class UtValueTestCaseChecker( return } - if (checkCoverageInCodeGenerationTests) { - // TODO JIRA:1407 - } - val methodUnderTestOwnerId = testSet.method.classId val classUnderTest = if (generateWithNested) { generateSequence(methodUnderTestOwnerId) { clazz -> clazz.enclosingClass }.last().kClass From 8a39fc2768e80b95b6cf0903b3c96612a096b0b1 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Mon, 21 Nov 2022 21:53:54 +0300 Subject: [PATCH 07/16] Compact one-line documentation in output file for enum values Split Single description for bunch options to dedicated ones in code Get rid of default value description in code Skip - * UtBot Expression Optimizations + * Set it to false to disable expression simplification. + * @see UtBot Expression Optimizations */ var useExpressionSimplification by getBooleanProperty(true) - /* - * Activate or deactivate tests on comments && names/displayNames - * */ + /** + * Activate or deactivate tests on comments + */ var testSummary by getBooleanProperty(true) + + /** + * Activate or deactivate tests on names + */ var testName by getBooleanProperty(true) + + /** + * Activate or deactivate tests on displayNames + */ var testDisplayName by getBooleanProperty(true) /** @@ -135,18 +139,23 @@ object UtSettings : AbstractSettings( /** * Enable the Summarization module to generate summaries for methods under test. - * True by default. * * Note: if it is false, all the execution for a particular method will be stored at the same nameless region. */ var enableSummariesGeneration by getBooleanProperty(true) /** - * Options below regulate which [NullPointerException] check should be performed. + * This option regulates which [NullPointerException] check should be performed for nested methods. * * Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. */ var checkNpeInNestedMethods by getBooleanProperty(true) + + /** + * This option regulates which [NullPointerException] check should be performed for nested not private methods. + * + * Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. + */ var checkNpeInNestedNotPrivateMethods by getBooleanProperty(false) /** @@ -154,7 +163,7 @@ object UtSettings : AbstractSettings( * in non-application classes. Set by true, this option highly decreases test's readability in some cases * because of using reflection API for setting final/non-public fields in non-application classes. * - * NOTE: default false value loses some executions with NPE in system classes, but often most of these executions + * NOTE: With false value loses some executions with NPE in system classes, but often most of these executions * are not expected by user. */ var maximizeCoverageUsingReflection by getBooleanProperty(false) @@ -168,8 +177,6 @@ object UtSettings : AbstractSettings( /** * Use concrete execution. - * - * True by default. */ var useConcreteExecution by getBooleanProperty(true) @@ -177,13 +184,12 @@ object UtSettings : AbstractSettings( * Enable code generation tests with every possible configuration * for every method in samples. * - * Important: disabled by default. This check requires enormous amount of time. + * Important: is enabled generation requires enormous amount of time. */ var checkAllCombinationsForEveryTestInSamples by getBooleanProperty(false) /** * Enable transformation UtCompositeModels into UtAssembleModels using AssembleModelGenerator. - * True by default. * * Note: false doesn't mean that there will be no assemble models, it means that the generator will be turned off. * Assemble models will present for lists, sets, etc. @@ -198,8 +204,6 @@ object UtSettings : AbstractSettings( /** * Enables soft constraints in the engine. - * - * True by default. */ var preferredCexOption by getBooleanProperty(true) @@ -227,15 +231,11 @@ object UtSettings : AbstractSettings( /** * Generate tests that treat possible overflows in arithmetic operations as errors * that throw Arithmetic Exception. - * - * False by default. */ var treatOverflowAsError: Boolean by getBooleanProperty(false) /** * Generate tests that treat assertions as error suits. - * - * True by default. */ var treatAssertAsErrorSuit: Boolean by getBooleanProperty(true) @@ -271,7 +271,7 @@ object UtSettings : AbstractSettings( * Determines whether should errors from a child process be written to a log file or suppressed. * Note: being enabled, this option can highly increase disk usage when using ContestEstimator. * - * False by default (for saving disk space). + * In enabled it consumes a lot of disk space. */ var logConcreteExecutionErrors by getBooleanProperty(false) @@ -314,16 +314,12 @@ object UtSettings : AbstractSettings( * It may be usefull during debug. * * Note: it might highly impact performance, so do not enable it in release mode. - * - * False by default. */ var enableUnsatCoreCalculationForHardConstraints by getBooleanProperty(false) /** * Enable it to process states with unknown solver status * from the queue to concrete execution. - * - * True by default. */ var processUnknownStatesDuringConcreteExecution by getBooleanProperty(true) @@ -388,7 +384,7 @@ object UtSettings : AbstractSettings( /** * Use the sandbox in the concrete executor. * - * If true (default), the sandbox will prevent potentially dangerous calls, e.g., file access, reading + * If true, the sandbox will prevent potentially dangerous calls, e.g., file access, reading * or modifying the environment, calls to `Unsafe` methods etc. * * If false, all these operations will be enabled and may lead to data loss during code analysis @@ -441,8 +437,6 @@ object UtSettings : AbstractSettings( * Use this option to enable calculation and logging of MD5 for dropped states by statistics. * Example of such logging: * Dropping state (lastStatus=UNDEFINED) by the distance statistics. MD5: 5d0bccc242e87d53578ca0ef64aa5864 - * - * Default value is false. */ var enableLoggingForDroppedStates by getBooleanProperty(false) @@ -518,8 +512,15 @@ enum class PathSelectorType { } enum class TestSelectionStrategyType { - DO_NOT_MINIMIZE_STRATEGY, // Always adds new test - COVERAGE_STRATEGY // Adds new test only if it increases coverage + /** + * Always adds new test + */ + DO_NOT_MINIMIZE_STRATEGY, + + /** + * Adds new test only if it increases coverage + */ + COVERAGE_STRATEGY } /** diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index bb3e08c57d..128848fd48 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -104,7 +104,7 @@ abstract class SettingsToConfigTask : DefaultTask() { if (s.startsWith("enum class ")) { enums.add(EnumInfo(s.substring(11, s.length - 2))) } else if (s.matches(Regex("[A-Z_]+,?")) && enums.isNotEmpty()) { - var enumValue = s.substring(0, s.length - 1) + var enumValue = s.substring(0, s.length) if (enumValue.endsWith(",")) enumValue = enumValue.substring(0, enumValue.length - 1) enums.last().docMap[enumValue] = docLines.toMutableList() } else if (s.startsWith("const val ")) { @@ -113,14 +113,16 @@ abstract class SettingsToConfigTask : DefaultTask() { } else if (s == "/**") { docLines.clear() } else if (s.startsWith("* ")) { - docLines.add(s.substring(2)) - } else if (s.startsWith("var")) { + if (!s.contains("href")) {//Links are not supported + docLines.add(s.substring(2)) + } + } else if (s.startsWith("var") || s.startsWith("val")) { acc.clear() acc.append(s) } else if (s.isEmpty() && acc.isNotEmpty()) { s = acc.toString() acc.clear() - if (s.startsWith("var")) { + if (s.startsWith("var") || s.startsWith("val")) { var i = s.indexOf(" by ", 3) if (i > 0) { var key = s.substring(3, i).trim() @@ -152,6 +154,9 @@ abstract class SettingsToConfigTask : DefaultTask() { if (defaultValue.matches(Regex("[\\d_]+L"))) { defaultValue = defaultValue.substring(0, defaultValue.length - 1).replace("_", "") } + if (defaultValue.matches(Regex("^\".+\"$"))) { + defaultValue = defaultValue.substring(1, defaultValue.length - 1) + } model.defaultValue = defaultValue model.docLines.addAll(docLines) } @@ -169,9 +174,16 @@ abstract class SettingsToConfigTask : DefaultTask() { if (split.size > 1) { model.defaultValue = split[1] val enumInfo = enums.find { info -> info.className == split[0] } + if (enumInfo!= null) { + model.docLines.add("") + } enumInfo?.docMap?.forEach { - model.docLines.add(it.key) - it.value.forEach { line -> model.docLines.add(line) } + if (it.value.size == 1) { + model.docLines.add("${it.key}: ${it.value.first()}") + } else { + model.docLines.add(it.key) + it.value.forEach { line -> model.docLines.add(line) } + } } } } @@ -180,10 +192,15 @@ abstract class SettingsToConfigTask : DefaultTask() { writer.println("#") } for (docLine in model.docLines) { - writer.println("# $docLine") + if (docLine.isEmpty()) { + writer.println("#") + } else { + writer.println("# $docLine") + } } if (!model.docLines.any({ s -> s.toLowerCaseAsciiOnly().contains("default") })) { - writer.println("# ${model.defaultValue} by default") + writer.println("#") + writer.println("# Default value is [${model.defaultValue}]") } writer.println("${model.key}=${model.defaultValue}") writer.flush() From 02cc183f3008bd4f1fbc3dfc8f6789a22616fb07 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 22 Nov 2022 21:03:39 +0300 Subject: [PATCH 08/16] Add Apache 2.0 license to settings.properties output and tune comments wording in sourcecode --- .../kotlin/org/utbot/framework/UtSettings.kt | 10 +++---- utbot-intellij/build.gradle.kts | 29 +++++++++++++++---- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index 8797054a9a..34dee09281 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -22,9 +22,7 @@ private const val defaultKeyForSettingsPath = "utbot.settings.path" */ const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS = 1000L -object UtSettings : AbstractSettings( - logger, defaultKeyForSettingsPath, defaultSettingsPath -) { +object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultSettingsPath) { /** * Setting to disable coroutines debug explicitly. @@ -258,7 +256,7 @@ object UtSettings : AbstractSettings( ) /** - * Log level for engine process, which started in idea on generate tests action. + * Log level for engine process, which started in IntelliJ IDEA on generate tests action. */ var engineProcessLogLevel by getEnumProperty(LogLevel.Info) @@ -277,7 +275,7 @@ object UtSettings : AbstractSettings( /** - * Property useful only for idea + * Property useful only for IntelliJ IDEA * If true - runs engine process with the ability to attach a debugger * @see runChildProcessWithDebug * @see org.utbot.intellij.plugin.process.EngineProcess @@ -289,7 +287,7 @@ object UtSettings : AbstractSettings( * * To debug the child process, set the breakpoint in the childProcessRunner.start() line * and in the child process's main function and run the main process. - * Then run the remote JVM debug configuration in IDEA. + * Then run the remote JVM debug configuration in IntelliJ IDEA. * If you see the message in console about successful connection, then * the debugger is attached successfully. * Now you can put the breakpoints in the child process and debug diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index 128848fd48..c07bdc7e43 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -1,6 +1,7 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import java.io.ByteArrayOutputStream import java.io.PrintWriter +import java.text.SimpleDateFormat val intellijPluginVersion: String? by rootProject val kotlinLoggingVersion: String? by rootProject @@ -67,6 +68,21 @@ intellij { } abstract class SettingsToConfigTask : DefaultTask() { + @get:Internal + val apacheLines = +"""Copyright (c) ${SimpleDateFormat("yyyy").format(System.currentTimeMillis())} The UnitTestBot Authors + +Licensed under the Apache License, Version 2.0 (the \License\); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an \AS IS\ BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.""".split("\n") @get:Internal val settingsSourceDir = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") @get:Internal @@ -96,8 +112,6 @@ abstract class SettingsToConfigTask : DefaultTask() { val acc = StringBuilder() val docLines = mutableListOf() - val byteArrayOutputStream = ByteArrayOutputStream() - val writer = PrintWriter(byteArrayOutputStream) File(settingsSourceDir, sourceFileName).useLines { it -> it.iterator().forEach { line -> var s = line.trim() @@ -126,6 +140,7 @@ abstract class SettingsToConfigTask : DefaultTask() { var i = s.indexOf(" by ", 3) if (i > 0) { var key = s.substring(3, i).trim() + println(key) if (key.contains(':')) { key = key.substring(0, key.lastIndexOf(':')) } @@ -168,6 +183,10 @@ abstract class SettingsToConfigTask : DefaultTask() { acc.append(" $s") } } + val byteArrayOutputStream = ByteArrayOutputStream() + val writer = PrintWriter(byteArrayOutputStream) + apacheLines.forEach { writer.println("# $it") } + for (model in models) { if (model.type == "Enum") { val split = model.defaultValue.split('.') @@ -187,10 +206,8 @@ abstract class SettingsToConfigTask : DefaultTask() { } } } - if (byteArrayOutputStream.size() > 0) { - writer.println() - writer.println("#") - } + writer.println() + writer.println("#") for (docLine in model.docLines) { if (docLine.isEmpty()) { writer.println("#") From b2a458168800f597a112a92e7a2dfc9da25af2fd Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 22 Nov 2022 21:28:24 +0300 Subject: [PATCH 09/16] Add generated template to keep is in repository as well --- .../src/main/resources/settings.properties | 477 ++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 utbot-intellij/src/main/resources/settings.properties diff --git a/utbot-intellij/src/main/resources/settings.properties b/utbot-intellij/src/main/resources/settings.properties new file mode 100644 index 0000000000..762f3ba565 --- /dev/null +++ b/utbot-intellij/src/main/resources/settings.properties @@ -0,0 +1,477 @@ +# Copyright (c) 2022 The UnitTestBot Authors +# +# Licensed under the Apache License, Version 2.0 (the \License\); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an \AS IS\ BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Setting to disable coroutines debug explicitly. +# Set it to false if debug info is required. +# +# Default value is [true] +disableCoroutinesDebug=true + +# +# Make `true` for interactive mode (like Intellij plugin). If `false` UTBot can apply certain optimizations. +# +# Default value is [true] +classfilesCanChange=true + +# +# Timeout for Z3 solver.check calls. +# Set it to 0 to disable timeout. +# +# Default value is [1000] +checkSolverTimeoutMillis=1000 + +# +# Timeout for symbolic execution +# +# Default value is [60000] +utBotGenerationTimeoutInMillis=60000 + +# +# Random seed in path selector. +# Set null to disable random. +# +# Default value is [42] +seedInPathSelector=42 + +# +# Type of path selector. +# +# COVERED_NEW_SELECTOR: [CoveredNewSelector] +# INHERITORS_SELECTOR: [InheritorsSelector] +# SUBPATH_GUIDED_SELECTOR: [SubpathGuidedSelector] +# CPI_SELECTOR: [CPInstSelector] +# FORK_DEPTH_SELECTOR: [ForkDepthSelector] +# ML_SELECTOR: [MLSelector] +# TORCH_SELECTOR: [TorchSelector] +# RANDOM_SELECTOR: [RandomSelector] +# RANDOM_PATH_SELECTOR: [RandomPathSelector] +# +# Default value is [INHERITORS_SELECTOR] +pathSelectorType=INHERITORS_SELECTOR + +# +# Type of MLSelector recalculation. +# +# WITH_RECALCULATION: [MLSelectorWithRecalculation] +# WITHOUT_RECALCULATION: [MLSelectorWithoutRecalculation] +# +# Default value is [WITHOUT_RECALCULATION] +mlSelectorRecalculationType=WITHOUT_RECALCULATION + +# +# Type of [MLPredictor]. +# +# MLP: [MultilayerPerceptronPredictor] +# LINREG: [LinearRegressionPredictor] +# +# Default value is [MLP] +mlPredictorType=MLP + +# +# Steps limit for path selector. +# +# Default value is [3500] +pathSelectorStepsLimit=3500 + +# +# Determines whether path selector should save remaining states for concrete execution after stopping by strategy. +# False for all framework tests by default. +saveRemainingStatesForConcreteExecution=true + +# +# Use debug visualization. +# Set it to true if debug visualization is needed. +# +# Default value is [false] +useDebugVisualization=false + +# +# Set the value to true to show library classes' graphs in visualization. +# +# Default value is [false] +showLibraryClassesInVisualization=false + +# +# Method is paused after this timeout to give an opportunity other methods to work +# +# Default value is [2000] +timeslotForOneToplevelMethodTraversalMs=2000 + +# +# Use simplification of UtExpressions. +# Set it to false to disable expression simplification. +# +# Default value is [true] +useExpressionSimplification=true + +# +# Activate or deactivate tests on comments +# +# Default value is [true] +testSummary=true + +# +# Activate or deactivate tests on names +# +# Default value is [true] +testName=true + +# +# Activate or deactivate tests on displayNames +# +# Default value is [true] +testDisplayName=true + +# +# Generate summaries using plugin's custom JavaDoc tags. +# +# Default value is [true] +useCustomJavaDocTags=true + +# +# Enable the Summarization module to generate summaries for methods under test. +# Note: if it is false, all the execution for a particular method will be stored at the same nameless region. +# +# Default value is [true] +enableSummariesGeneration=true + +# +# This option regulates which [NullPointerException] check should be performed for nested methods. +# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. +# +# Default value is [true] +checkNpeInNestedMethods=true + +# +# This option regulates which [NullPointerException] check should be performed for nested not private methods. +# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. +# +# Default value is [false] +checkNpeInNestedNotPrivateMethods=false + +# +# This option determines whether we should generate [NullPointerException] checks for final or non-public fields +# in non-application classes. Set by true, this option highly decreases test's readability in some cases +# because of using reflection API for setting final/non-public fields in non-application classes. +# NOTE: With false value loses some executions with NPE in system classes, but often most of these executions +# are not expected by user. +# +# Default value is [false] +maximizeCoverageUsingReflection=false + +# +# Activate or deactivate substituting static fields values set in static initializer +# with symbolic variable to try to set them another value than in initializer. +# +# Default value is [true] +substituteStaticsWithSymbolicVariable=true + +# +# Use concrete execution. +# +# Default value is [true] +useConcreteExecution=true + +# +# Enable code generation tests with every possible configuration +# for every method in samples. +# Important: is enabled generation requires enormous amount of time. +# +# Default value is [false] +checkAllCombinationsForEveryTestInSamples=false + +# +# Enable transformation UtCompositeModels into UtAssembleModels using AssembleModelGenerator. +# Note: false doesn't mean that there will be no assemble models, it means that the generator will be turned off. +# Assemble models will present for lists, sets, etc. +# +# Default value is [true] +useAssembleModelGenerator=true + +# +# Test related files from the temp directory that are older than [daysLimitForTempFiles] +# will be removed at the beginning of the test run. +# +# Default value is [3] +daysLimitForTempFiles=3 + +# +# Enables soft constraints in the engine. +# +# Default value is [true] +preferredCexOption=true + +# +# Type of test minimization strategy. +# +# DO_NOT_MINIMIZE_STRATEGY: Always adds new test +# COVERAGE_STRATEGY: Adds new test only if it increases coverage +# +# Default value is [COVERAGE_STRATEGY] +testMinimizationStrategyType=COVERAGE_STRATEGY + +# +# Set to true to start fuzzing if symbolic execution haven't return anything +# +# Default value is [true] +useFuzzing=true + +# +# Set the total attempts to improve coverage by fuzzer. +# +# Default value is [2147483647] +fuzzingMaxAttempts=2147483647 + +# +# Fuzzer tries to generate and run tests during this time. +# +# Default value is [3000] +fuzzingTimeoutInMillis=3000 + +# +# Generate tests that treat possible overflows in arithmetic operations as errors +# that throw Arithmetic Exception. +# +# Default value is [false] +treatOverflowAsError=false + +# +# Generate tests that treat assertions as error suits. +# +# Default value is [true] +treatAssertAsErrorSuit=true + +# +# Instrument all classes before start +# +# Default value is [false] +warmupConcreteExecution=false + +# +# Ignore string literals during the code analysis to make possible to analyze antlr. +# It is a hack and must be removed after the competition. +# +# Default value is [false] +ignoreStringLiterals=false + +# +# Timeout for specific concrete execution (in milliseconds). +# +# Default value is [1000] +concreteExecutionTimeoutInChildProcess=1000 + +# +# Log level for engine process, which started in IntelliJ IDEA on generate tests action. +# +# Default value is [Info] +engineProcessLogLevel=Info + +# +# Log level for concrete executor process. +# +# Default value is [Info] +childProcessLogLevel=Info + +# +# Determines whether should errors from a child process be written to a log file or suppressed. +# Note: being enabled, this option can highly increase disk usage when using ContestEstimator. +# In enabled it consumes a lot of disk space. +# +# Default value is [false] +logConcreteExecutionErrors=false + +# +# Property useful only for IntelliJ IDEA +# If true - runs engine process with the ability to attach a debugger +# @see runChildProcessWithDebug +# @see org.utbot.intellij.plugin.process.EngineProcess +# +# Default value is [false] +runIdeaProcessWithDebug=false + +# +# If true, runs the child process with the ability to attach a debugger. +# To debug the child process, set the breakpoint in the childProcessRunner.start() line +# and in the child process's main function and run the main process. +# Then run the remote JVM debug configuration in IntelliJ IDEA. +# If you see the message in console about successful connection, then +# the debugger is attached successfully. +# Now you can put the breakpoints in the child process and debug +# both processes simultaneously. +# @see [org.utbot.instrumentation.process.ChildProcessRunner.cmds] +# +# Default value is [false] +runChildProcessWithDebug=false + +# +# Number of branch instructions using for clustering executions in the test minimization phase. +# +# Default value is [4] +numberOfBranchInstructionsForClustering=4 + +# +# Determines should we choose only one crash execution with "minimal" model or keep all. +# +# Default value is [true] +minimizeCrashExecutions=true + +# +# Enable it to calculate unsat cores for hard constraints as well. +# It may be usefull during debug. +# Note: it might highly impact performance, so do not enable it in release mode. +# +# Default value is [false] +enableUnsatCoreCalculationForHardConstraints=false + +# +# Enable it to process states with unknown solver status +# from the queue to concrete execution. +# +# Default value is [true] +processUnknownStatesDuringConcreteExecution=true + +# +# 2^{this} will be the length of observed subpath. +# See [SubpathGuidedSelector] +# +# Default value is [1] +subpathGuidedSelectorIndex=1 + +# +# Flag that indicates whether feature processing for execution states enabled or not +# +# Default value is [false] +enableFeatureProcess=false + +# +# Path to deserialized ML models +# +# Default value is [../models/0] +modelPath=../models/0 + +# +# Full class name of the class containing the configuration for the ML models to solve path selection task. +# +# Default value is [org.utbot.AnalyticsConfiguration] +analyticsConfigurationClassPath=org.utbot.AnalyticsConfiguration + +# +# Full class name of the class containing the configuration for the ML models exported from the PyTorch to solve path selection task. +# +# Default value is [org.utbot.AnalyticsTorchConfiguration] +analyticsTorchConfigurationClassPath=org.utbot.AnalyticsTorchConfiguration + +# +# Number of model iterations that will be used during ContestEstimator +# +# Default value is [1] +iterations=1 + +# +# Path for state features dir +# +# Default value is [eval/secondFeatures/antlr/INHERITORS_SELECTOR] +featurePath=eval/secondFeatures/antlr/INHERITORS_SELECTOR + +# +# Counter for tests during testGeneration for one project in ContestEstimator +# +# Default value is [0] +testCounter=0 + +# +# Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models) +# +# Default value is [true] +singleSelector=true + +# +# Flag that indicates whether tests for synthetic (see [Executable.isSynthetic]) and implicitly declared methods (like values, valueOf in enums) should be generated, or not +# +# Default value is [true] +skipTestGenerationForSyntheticAndImplicitlyDeclaredMethods=true + +# +# Flag that indicates whether should we branch on and set static fields from trusted libraries or not. +# @see [org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES] +# +# Default value is [true] +ignoreStaticsFromTrustedLibraries=true + +# +# Use the sandbox in the concrete executor. +# If true, the sandbox will prevent potentially dangerous calls, e.g., file access, reading +# or modifying the environment, calls to `Unsafe` methods etc. +# If false, all these operations will be enabled and may lead to data loss during code analysis +# and test generation. +# +# Default value is [true] +useSandbox=true + +# +# Limit for number of generated tests per method (in each region) +# +# Default value is [50] +maxTestsPerMethodInRegion=50 + +# +# Max file length for generated test file +# +# Default value is [1000000] +maxTestFileSize=1000000 + +# +# If this options set in true, all soot classes will be removed from a Soot Scene, +# therefore, you will be unable to test soot classes. +# +# Default value is [true] +removeSootClassesFromHierarchy=true + +# +# If this options set in true, all UtBot classes will be removed from a Soot Scene, +# therefore, you will be unable to test UtBot classes. +# +# Default value is [true] +removeUtBotClassesFromHierarchy=true + +# +# Use this option to enable calculation and logging of MD5 for dropped states by statistics. +# Example of such logging: +# Dropping state (lastStatus=UNDEFINED) by the distance statistics. MD5: 5d0bccc242e87d53578ca0ef64aa5864 +# +# Default value is [false] +enableLoggingForDroppedStates=false + +# +# If this option set in true, depending on the number of possible types for +# a particular object will be used either type system based on conjunction +# or on bit vectors. +# @see useBitVecBasedTypeSystem +# +# Default value is [true] +useBitVecBasedTypeSystem=true + +# +# The number of types on which the choice of the type system depends. +# +# Default value is [64] +maxTypeNumberForEnumeration=64 + +# +# The threshold for numbers of types for which they will be encoded into solver. +# It is used to do not encode big type storages due to significand performance degradation. +# +# Default value is [512] +maxNumberOfTypesToEncode=512 From 52c60b74f9138a9b49b45d4babc80625bcb93772 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 23 Nov 2022 20:55:25 +0300 Subject: [PATCH 10/16] Add template generation to gradle build process Save template to user's local file if absent Add some documentation comments --- .../src/main/java/SettingsTemplateHelper.java | 197 ++++++++++++++++++ .../kotlin/org/utbot/framework/UtSettings.kt | 2 + utbot-intellij/build.gradle.kts | 173 +-------------- .../intellij/plugin/settings/Settings.kt | 22 +- 4 files changed, 221 insertions(+), 173 deletions(-) create mode 100644 buildSrc/src/main/java/SettingsTemplateHelper.java diff --git a/buildSrc/src/main/java/SettingsTemplateHelper.java b/buildSrc/src/main/java/SettingsTemplateHelper.java new file mode 100644 index 0000000000..0555feedcb --- /dev/null +++ b/buildSrc/src/main/java/SettingsTemplateHelper.java @@ -0,0 +1,197 @@ +import org.gradle.api.*; + +import java.io.*; +import java.text.*; +import java.util.*; +import java.util.function.*; + +/** + * The purpose of this helper is to convert UtSettings.kt source code + * to template resource file settings.properties (top-level entry in plugin JAR file). + * There are two stages: parsing of input to build models and then rendering models to output file + */ + +public class SettingsTemplateHelper { + private static final String[] apacheLines = + ("Copyright (c) " + new SimpleDateFormat("yyyy").format(System.currentTimeMillis()) + " The UnitTestBot Authors\n" + + "\n" + + "Licensed under the Apache License, Version 2.0 (the \\License\\);\n" + + "you may not use this file except in compliance with the License.\n" + + "You may obtain a copy of the License at\n" + + "\n" + + " http://www.apache.org/licenses/LICENSE-2.0\n" + + "\n" + + "Unless required by applicable law or agreed to in writing, software\n" + + "distributed under the License is distributed on an \\AS IS\\ BASIS,\n" + + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + "See the License for the specific language governing permissions and\n" + + "limitations under the License.").split("\n"); + + public static void proceed(Project project) { + File settingsSourceDir = new File(project.getBuildDir().getParentFile().getParentFile(), "utbot-framework-api/src/main/kotlin/org/utbot/framework/"); + String sourceFileName = "UtSettings.kt"; + File settingsResourceDir = new File(project.getBuildDir().getParentFile().getParentFile(), "utbot-intellij/src/main/resources/"); + String settingsFileName = "settings.properties"; + + Map dictionary = new HashMap<>(); + dictionary.put("Int.MAX_VALUE", String.valueOf(Integer.MAX_VALUE)); + + List models = new ArrayList<>(); + List enums = new ArrayList<>(); + StringBuilder acc = new StringBuilder(); + List docAcc = new ArrayList<>(); + // Stage one: parsing sourcecode + try(BufferedReader reader = new BufferedReader(new FileReader(new File(settingsSourceDir, sourceFileName)))) { + for (String s = reader.readLine(); s != null; s = reader.readLine()) { + s = s.trim(); + if (s.startsWith("enum class ")) {//Enum class declaration + enums.add(new EnumInfo(s.substring(11, s.length() - 2))); + } else if (s.matches("[A-Z_]+,?") && !enums.isEmpty()) {//Enum value + var enumValue = s.substring(0, s.length()); + if (enumValue.endsWith(",")) enumValue = enumValue.substring(0, enumValue.length() - 1); + enums.get(enums.size() - 1).docMap.put(enumValue, new ArrayList<>(docAcc)); + } else if (s.startsWith("const val ")) {//Constand value to be substitute later if need + int pos = s.indexOf(" = "); + dictionary.put(s.substring(10, pos), s.substring(pos + 3)); + } else if (s.equals("/**")) {//Start of docuemntation block + docAcc.clear(); + } else if (s.startsWith("* ")) { + if (!s.contains("href")) {//Links are not supported, skip them + docAcc.add(s.substring(2)); + } + } else if (s.startsWith("var") || s.startsWith("val")) {//Restart accumulation + acc.delete(0, acc.length()); + acc.append(s); + } else if (s.isEmpty() && acc.length() > 0) {//Build model from accumulated lines + s = acc.toString(); + acc.delete(0, acc.length()); + if (s.startsWith("var") || s.startsWith("val")) { + var i = s.indexOf(" by ", 3); + if (i > 0) { + var key = s.substring(3, i).trim(); + if (key.contains(":")) { + key = key.substring(0, key.lastIndexOf(':')); + } + PropertyModel model = new PropertyModel(key); + models.add(model); + s = s.substring(i + 7); + i = s.indexOf("Property"); + if (i > 0) model.type = s.substring(0, i); + if (i == 0) { + i = s.indexOf('<', i); + if (i != -1) { + s = s.substring(i+1); + i = s.indexOf('>'); + if (i != -1) { + model.type = s.substring(0, i); + } + } + } + + i = s.indexOf('(', i); + if (i > 0) { + s = s.substring(i + 1); + var defaultValue = s.substring(0, s.indexOf(')')).trim(); + if (defaultValue.contains(",")) defaultValue = defaultValue.substring(0, defaultValue.indexOf(',')); + defaultValue = dictionary.getOrDefault(defaultValue, defaultValue); + if (defaultValue.matches("[\\d_]+L")) { + defaultValue = defaultValue.substring(0, defaultValue.length() - 1).replace("_", ""); + } + if (defaultValue.matches("^\".+\"$")) { + defaultValue = defaultValue.substring(1, defaultValue.length() - 1); + } + model.defaultValue = defaultValue; + model.docLines.addAll(docAcc); + } + } + } + } else if (acc.length() > 0) { + acc.append(" " + s); + } + } + } catch (IOException ioe) { + System.err.println("Unexpected error when processing " + sourceFileName); + ioe.printStackTrace(); + } + + // Stage two: properties file rendering + try (PrintWriter writer = new PrintWriter(new File(settingsResourceDir, settingsFileName))) { + for (String apacheLine : apacheLines) { + writer.println("# " + apacheLine); + } + for (PropertyModel model : models) { + if (model.type.equals("Enum")) { + String[] split = model.defaultValue.split("\\."); + if (split.length > 1) { + model.defaultValue = split[1]; + EnumInfo enumInfo = enums.stream().filter(new Predicate() { + @Override + public boolean test(EnumInfo enumInfo) { + return enumInfo.className.equals(split[0]); + } + }).findFirst().orElse(null); + if (enumInfo != null) { + model.docLines.add(""); + for (Map.Entry> entry : enumInfo.docMap.entrySet()) { + String enumValue = entry.getKey(); + if (entry.getValue().size() == 1) { + model.docLines.add(enumValue + ": " + entry.getValue().get(0)); + } else { + model.docLines.add(enumValue); + for (String line : entry.getValue()) { + model.docLines.add(line); + } + } + } + } + } + } + writer.println(); + writer.println("#"); + for (String docLine : model.docLines) { + if (docLine.isEmpty()) { + writer.println("#"); + } else { + writer.println("# " + docLine); + } + } + boolean defaultIsAlreadyMentioned = model.docLines.stream().anyMatch(new Predicate() { + @Override + public boolean test(String s) { + return s.toLowerCase(Locale.ROOT).contains("default"); + } + }); + if (!defaultIsAlreadyMentioned) { + writer.println("#"); + writer.println("# Default value is [" + model.defaultValue + "]"); + } + writer.println(model.key + "=" + model.defaultValue); + } + writer.flush(); + writer.close(); + } catch (IOException ioe) { + System.err.println("Unexpected error when saving " + settingsFileName); + ioe.printStackTrace(); + } + } + + private static class PropertyModel { + final String key; + String type = ""; + String defaultValue = ""; + List docLines = new ArrayList<>(); + + PropertyModel(String key) { + this.key = key; + } + } + + private static class EnumInfo { + final String className; + Map> docMap = new LinkedHashMap<>(); + + public EnumInfo(String className) { + this.className = className; + } + } +} \ No newline at end of file diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index 34dee09281..0ec8c06d9c 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -24,6 +24,8 @@ const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS = 1000L object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultSettingsPath) { + fun defaultSettingsPath() = defaultSettingsPath + /** * Setting to disable coroutines debug explicitly. * diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index c07bdc7e43..3a9852451b 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -1,8 +1,3 @@ -import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly -import java.io.ByteArrayOutputStream -import java.io.PrintWriter -import java.text.SimpleDateFormat - val intellijPluginVersion: String? by rootProject val kotlinLoggingVersion: String? by rootProject val apacheCommonsTextVersion: String? by rootProject @@ -65,175 +60,9 @@ intellij { version.set(ideVersion) type.set(ideTypeOrAndroidStudio) + SettingsTemplateHelper.proceed(project) } -abstract class SettingsToConfigTask : DefaultTask() { - @get:Internal - val apacheLines = -"""Copyright (c) ${SimpleDateFormat("yyyy").format(System.currentTimeMillis())} The UnitTestBot Authors - -Licensed under the Apache License, Version 2.0 (the \License\); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an \AS IS\ BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License.""".split("\n") - @get:Internal - val settingsSourceDir = File(project.buildDir.parentFile.parentFile, "utbot-framework-api/src/main/kotlin/org/utbot/framework/") - @get:Internal - val sourceFileName = "UtSettings.kt" - @get:Internal - val settingsResourceDir = File(project.buildDir.parentFile.parentFile, "utbot-intellij/src/main/resources/") - @get:Internal - val settingsFileName = "settings.properties" - - data class PropertyModel( - val key: String, - var type: String = "", - var defaultValue: String = "", - var docLines: MutableList = mutableListOf() - ) - - data class EnumInfo(var className: String, var docMap: MutableMap> = linkedMapOf()) - - @TaskAction - fun proceed() { - try { - val dictionary = mutableMapOf().also { - it["Int.MAX_VALUE"] = Int.MAX_VALUE.toString() - } - val models = mutableListOf() - val enums = mutableListOf() - - val acc = StringBuilder() - val docLines = mutableListOf() - File(settingsSourceDir, sourceFileName).useLines { it -> - it.iterator().forEach { line -> - var s = line.trim() - if (s.startsWith("enum class ")) { - enums.add(EnumInfo(s.substring(11, s.length - 2))) - } else if (s.matches(Regex("[A-Z_]+,?")) && enums.isNotEmpty()) { - var enumValue = s.substring(0, s.length) - if (enumValue.endsWith(",")) enumValue = enumValue.substring(0, enumValue.length - 1) - enums.last().docMap[enumValue] = docLines.toMutableList() - } else if (s.startsWith("const val ")) { - val pos = s.indexOf(" = ") - dictionary[s.substring(10, pos)] = s.substring(pos + 3) - } else if (s == "/**") { - docLines.clear() - } else if (s.startsWith("* ")) { - if (!s.contains("href")) {//Links are not supported - docLines.add(s.substring(2)) - } - } else if (s.startsWith("var") || s.startsWith("val")) { - acc.clear() - acc.append(s) - } else if (s.isEmpty() && acc.isNotEmpty()) { - s = acc.toString() - acc.clear() - if (s.startsWith("var") || s.startsWith("val")) { - var i = s.indexOf(" by ", 3) - if (i > 0) { - var key = s.substring(3, i).trim() - println(key) - if (key.contains(':')) { - key = key.substring(0, key.lastIndexOf(':')) - } - val model = PropertyModel(key) - models.add(model) - s = s.substring(i + 7) - i = s.indexOf("Property") - if (i > 0) model.type = s.substring(0, i) - if (i == 0) { - i = s.indexOf('<', i) - if (i != -1) { - s = s.substring(i+1) - i = s.indexOf('>') - if (i != -1) { - model.type = s.substring(0, i) - } - } - } - - i = s.indexOf('(', i) - if (i > 0) { - s = s.substring(i + 1) - var defaultValue = s.substring(0, s.indexOf(')')).trim() - if (defaultValue.contains(',')) defaultValue = defaultValue.substring(0, defaultValue.indexOf(',')) - defaultValue = dictionary[defaultValue] ?:defaultValue - if (defaultValue.matches(Regex("[\\d_]+L"))) { - defaultValue = defaultValue.substring(0, defaultValue.length - 1).replace("_", "") - } - if (defaultValue.matches(Regex("^\".+\"$"))) { - defaultValue = defaultValue.substring(1, defaultValue.length - 1) - } - model.defaultValue = defaultValue - model.docLines.addAll(docLines) - } - } else { - System.err.println(s) - } - } - } else if (acc.isNotEmpty()) { - acc.append(" $s") - } - } - val byteArrayOutputStream = ByteArrayOutputStream() - val writer = PrintWriter(byteArrayOutputStream) - apacheLines.forEach { writer.println("# $it") } - - for (model in models) { - if (model.type == "Enum") { - val split = model.defaultValue.split('.') - if (split.size > 1) { - model.defaultValue = split[1] - val enumInfo = enums.find { info -> info.className == split[0] } - if (enumInfo!= null) { - model.docLines.add("") - } - enumInfo?.docMap?.forEach { - if (it.value.size == 1) { - model.docLines.add("${it.key}: ${it.value.first()}") - } else { - model.docLines.add(it.key) - it.value.forEach { line -> model.docLines.add(line) } - } - } - } - } - writer.println() - writer.println("#") - for (docLine in model.docLines) { - if (docLine.isEmpty()) { - writer.println("#") - } else { - writer.println("# $docLine") - } - } - if (!model.docLines.any({ s -> s.toLowerCaseAsciiOnly().contains("default") })) { - writer.println("#") - writer.println("# Default value is [${model.defaultValue}]") - } - writer.println("${model.key}=${model.defaultValue}") - writer.flush() - } - writer.flush() - writer.close() - File(settingsResourceDir, settingsFileName).writeBytes(byteArrayOutputStream.toByteArray()) - } - } catch (e : java.io.IOException) { - logger.error("Unexpected error when processing $sourceFileName", e) - } - } -} - -tasks.register("generateConfigTemplate") - tasks { compileKotlin { kotlinOptions { diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt index 062b2606b1..67855c30c7 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt @@ -8,6 +8,9 @@ import com.intellij.openapi.components.Storage import com.intellij.openapi.project.Project import com.intellij.util.xmlb.Converter import com.intellij.util.xmlb.annotations.OptionTag +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Paths import org.utbot.common.FileUtil import org.utbot.engine.Mocker import org.utbot.framework.UtSettings @@ -171,7 +174,24 @@ class Settings(val project: Project) : PersistentStateComponent override fun initializeComponent() { super.initializeComponent() - CompletableFuture.runAsync { FileUtil.clearTempDirectory(UtSettings.daysLimitForTempFiles) } + CompletableFuture.runAsync { + FileUtil.clearTempDirectory(UtSettings.daysLimitForTempFiles) + // In case settings.properties file is not yet presented in {homeDir}/.utbot folder + // we copy it from plugin resource file + val settingsClass = javaClass + Paths.get(UtSettings.defaultSettingsPath()).toFile().apply { + if (!this.isFile) { + val parentFile = this.parentFile + if (parentFile.mkdirs()) Files.setAttribute(parentFile.toPath(), "dos:hidden", true) + try { + settingsClass.getResource("../../../../../settings.properties")?.let { + this.writeBytes(it.openStream().readBytes()) + } + } catch (ignored: IOException) { + } + } + } + } } override fun loadState(state: State) { From bc40dbf6710deee752fbcfe0ee951244c944b322 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 24 Nov 2022 11:59:49 +0300 Subject: [PATCH 11/16] Get rid of unused property timeslotForOneToplevelMethodTraversalMs (Went to TestCaseGenerator.kt:300 some time ago) Get rid of unused property singleSelector Delete resource file settings.properties that is designed to be re-generated locally from the repository --- .../kotlin/org/utbot/framework/UtSettings.kt | 10 - .../src/main/resources/settings.properties | 477 ------------------ 2 files changed, 487 deletions(-) delete mode 100644 utbot-intellij/src/main/resources/settings.properties diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index 0ec8c06d9c..391091c3ef 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -104,11 +104,6 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS */ val showLibraryClassesInVisualization by getBooleanProperty(false) - /** - * Method is paused after this timeout to give an opportunity other methods to work - */ - var timeslotForOneToplevelMethodTraversalMs by getIntProperty(2000) - /** * Use simplification of UtExpressions. * @@ -364,11 +359,6 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS */ var testCounter by getIntProperty(0) - /** - * Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models) - */ - var singleSelector by getBooleanProperty(true) - /** * Flag that indicates whether tests for synthetic (see [Executable.isSynthetic]) and implicitly declared methods (like values, valueOf in enums) should be generated, or not */ diff --git a/utbot-intellij/src/main/resources/settings.properties b/utbot-intellij/src/main/resources/settings.properties deleted file mode 100644 index 762f3ba565..0000000000 --- a/utbot-intellij/src/main/resources/settings.properties +++ /dev/null @@ -1,477 +0,0 @@ -# Copyright (c) 2022 The UnitTestBot Authors -# -# Licensed under the Apache License, Version 2.0 (the \License\); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an \AS IS\ BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Setting to disable coroutines debug explicitly. -# Set it to false if debug info is required. -# -# Default value is [true] -disableCoroutinesDebug=true - -# -# Make `true` for interactive mode (like Intellij plugin). If `false` UTBot can apply certain optimizations. -# -# Default value is [true] -classfilesCanChange=true - -# -# Timeout for Z3 solver.check calls. -# Set it to 0 to disable timeout. -# -# Default value is [1000] -checkSolverTimeoutMillis=1000 - -# -# Timeout for symbolic execution -# -# Default value is [60000] -utBotGenerationTimeoutInMillis=60000 - -# -# Random seed in path selector. -# Set null to disable random. -# -# Default value is [42] -seedInPathSelector=42 - -# -# Type of path selector. -# -# COVERED_NEW_SELECTOR: [CoveredNewSelector] -# INHERITORS_SELECTOR: [InheritorsSelector] -# SUBPATH_GUIDED_SELECTOR: [SubpathGuidedSelector] -# CPI_SELECTOR: [CPInstSelector] -# FORK_DEPTH_SELECTOR: [ForkDepthSelector] -# ML_SELECTOR: [MLSelector] -# TORCH_SELECTOR: [TorchSelector] -# RANDOM_SELECTOR: [RandomSelector] -# RANDOM_PATH_SELECTOR: [RandomPathSelector] -# -# Default value is [INHERITORS_SELECTOR] -pathSelectorType=INHERITORS_SELECTOR - -# -# Type of MLSelector recalculation. -# -# WITH_RECALCULATION: [MLSelectorWithRecalculation] -# WITHOUT_RECALCULATION: [MLSelectorWithoutRecalculation] -# -# Default value is [WITHOUT_RECALCULATION] -mlSelectorRecalculationType=WITHOUT_RECALCULATION - -# -# Type of [MLPredictor]. -# -# MLP: [MultilayerPerceptronPredictor] -# LINREG: [LinearRegressionPredictor] -# -# Default value is [MLP] -mlPredictorType=MLP - -# -# Steps limit for path selector. -# -# Default value is [3500] -pathSelectorStepsLimit=3500 - -# -# Determines whether path selector should save remaining states for concrete execution after stopping by strategy. -# False for all framework tests by default. -saveRemainingStatesForConcreteExecution=true - -# -# Use debug visualization. -# Set it to true if debug visualization is needed. -# -# Default value is [false] -useDebugVisualization=false - -# -# Set the value to true to show library classes' graphs in visualization. -# -# Default value is [false] -showLibraryClassesInVisualization=false - -# -# Method is paused after this timeout to give an opportunity other methods to work -# -# Default value is [2000] -timeslotForOneToplevelMethodTraversalMs=2000 - -# -# Use simplification of UtExpressions. -# Set it to false to disable expression simplification. -# -# Default value is [true] -useExpressionSimplification=true - -# -# Activate or deactivate tests on comments -# -# Default value is [true] -testSummary=true - -# -# Activate or deactivate tests on names -# -# Default value is [true] -testName=true - -# -# Activate or deactivate tests on displayNames -# -# Default value is [true] -testDisplayName=true - -# -# Generate summaries using plugin's custom JavaDoc tags. -# -# Default value is [true] -useCustomJavaDocTags=true - -# -# Enable the Summarization module to generate summaries for methods under test. -# Note: if it is false, all the execution for a particular method will be stored at the same nameless region. -# -# Default value is [true] -enableSummariesGeneration=true - -# -# This option regulates which [NullPointerException] check should be performed for nested methods. -# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. -# -# Default value is [true] -checkNpeInNestedMethods=true - -# -# This option regulates which [NullPointerException] check should be performed for nested not private methods. -# Set an option in true if you want to perform NPE check in the corresponding situations, otherwise set false. -# -# Default value is [false] -checkNpeInNestedNotPrivateMethods=false - -# -# This option determines whether we should generate [NullPointerException] checks for final or non-public fields -# in non-application classes. Set by true, this option highly decreases test's readability in some cases -# because of using reflection API for setting final/non-public fields in non-application classes. -# NOTE: With false value loses some executions with NPE in system classes, but often most of these executions -# are not expected by user. -# -# Default value is [false] -maximizeCoverageUsingReflection=false - -# -# Activate or deactivate substituting static fields values set in static initializer -# with symbolic variable to try to set them another value than in initializer. -# -# Default value is [true] -substituteStaticsWithSymbolicVariable=true - -# -# Use concrete execution. -# -# Default value is [true] -useConcreteExecution=true - -# -# Enable code generation tests with every possible configuration -# for every method in samples. -# Important: is enabled generation requires enormous amount of time. -# -# Default value is [false] -checkAllCombinationsForEveryTestInSamples=false - -# -# Enable transformation UtCompositeModels into UtAssembleModels using AssembleModelGenerator. -# Note: false doesn't mean that there will be no assemble models, it means that the generator will be turned off. -# Assemble models will present for lists, sets, etc. -# -# Default value is [true] -useAssembleModelGenerator=true - -# -# Test related files from the temp directory that are older than [daysLimitForTempFiles] -# will be removed at the beginning of the test run. -# -# Default value is [3] -daysLimitForTempFiles=3 - -# -# Enables soft constraints in the engine. -# -# Default value is [true] -preferredCexOption=true - -# -# Type of test minimization strategy. -# -# DO_NOT_MINIMIZE_STRATEGY: Always adds new test -# COVERAGE_STRATEGY: Adds new test only if it increases coverage -# -# Default value is [COVERAGE_STRATEGY] -testMinimizationStrategyType=COVERAGE_STRATEGY - -# -# Set to true to start fuzzing if symbolic execution haven't return anything -# -# Default value is [true] -useFuzzing=true - -# -# Set the total attempts to improve coverage by fuzzer. -# -# Default value is [2147483647] -fuzzingMaxAttempts=2147483647 - -# -# Fuzzer tries to generate and run tests during this time. -# -# Default value is [3000] -fuzzingTimeoutInMillis=3000 - -# -# Generate tests that treat possible overflows in arithmetic operations as errors -# that throw Arithmetic Exception. -# -# Default value is [false] -treatOverflowAsError=false - -# -# Generate tests that treat assertions as error suits. -# -# Default value is [true] -treatAssertAsErrorSuit=true - -# -# Instrument all classes before start -# -# Default value is [false] -warmupConcreteExecution=false - -# -# Ignore string literals during the code analysis to make possible to analyze antlr. -# It is a hack and must be removed after the competition. -# -# Default value is [false] -ignoreStringLiterals=false - -# -# Timeout for specific concrete execution (in milliseconds). -# -# Default value is [1000] -concreteExecutionTimeoutInChildProcess=1000 - -# -# Log level for engine process, which started in IntelliJ IDEA on generate tests action. -# -# Default value is [Info] -engineProcessLogLevel=Info - -# -# Log level for concrete executor process. -# -# Default value is [Info] -childProcessLogLevel=Info - -# -# Determines whether should errors from a child process be written to a log file or suppressed. -# Note: being enabled, this option can highly increase disk usage when using ContestEstimator. -# In enabled it consumes a lot of disk space. -# -# Default value is [false] -logConcreteExecutionErrors=false - -# -# Property useful only for IntelliJ IDEA -# If true - runs engine process with the ability to attach a debugger -# @see runChildProcessWithDebug -# @see org.utbot.intellij.plugin.process.EngineProcess -# -# Default value is [false] -runIdeaProcessWithDebug=false - -# -# If true, runs the child process with the ability to attach a debugger. -# To debug the child process, set the breakpoint in the childProcessRunner.start() line -# and in the child process's main function and run the main process. -# Then run the remote JVM debug configuration in IntelliJ IDEA. -# If you see the message in console about successful connection, then -# the debugger is attached successfully. -# Now you can put the breakpoints in the child process and debug -# both processes simultaneously. -# @see [org.utbot.instrumentation.process.ChildProcessRunner.cmds] -# -# Default value is [false] -runChildProcessWithDebug=false - -# -# Number of branch instructions using for clustering executions in the test minimization phase. -# -# Default value is [4] -numberOfBranchInstructionsForClustering=4 - -# -# Determines should we choose only one crash execution with "minimal" model or keep all. -# -# Default value is [true] -minimizeCrashExecutions=true - -# -# Enable it to calculate unsat cores for hard constraints as well. -# It may be usefull during debug. -# Note: it might highly impact performance, so do not enable it in release mode. -# -# Default value is [false] -enableUnsatCoreCalculationForHardConstraints=false - -# -# Enable it to process states with unknown solver status -# from the queue to concrete execution. -# -# Default value is [true] -processUnknownStatesDuringConcreteExecution=true - -# -# 2^{this} will be the length of observed subpath. -# See [SubpathGuidedSelector] -# -# Default value is [1] -subpathGuidedSelectorIndex=1 - -# -# Flag that indicates whether feature processing for execution states enabled or not -# -# Default value is [false] -enableFeatureProcess=false - -# -# Path to deserialized ML models -# -# Default value is [../models/0] -modelPath=../models/0 - -# -# Full class name of the class containing the configuration for the ML models to solve path selection task. -# -# Default value is [org.utbot.AnalyticsConfiguration] -analyticsConfigurationClassPath=org.utbot.AnalyticsConfiguration - -# -# Full class name of the class containing the configuration for the ML models exported from the PyTorch to solve path selection task. -# -# Default value is [org.utbot.AnalyticsTorchConfiguration] -analyticsTorchConfigurationClassPath=org.utbot.AnalyticsTorchConfiguration - -# -# Number of model iterations that will be used during ContestEstimator -# -# Default value is [1] -iterations=1 - -# -# Path for state features dir -# -# Default value is [eval/secondFeatures/antlr/INHERITORS_SELECTOR] -featurePath=eval/secondFeatures/antlr/INHERITORS_SELECTOR - -# -# Counter for tests during testGeneration for one project in ContestEstimator -# -# Default value is [0] -testCounter=0 - -# -# Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models) -# -# Default value is [true] -singleSelector=true - -# -# Flag that indicates whether tests for synthetic (see [Executable.isSynthetic]) and implicitly declared methods (like values, valueOf in enums) should be generated, or not -# -# Default value is [true] -skipTestGenerationForSyntheticAndImplicitlyDeclaredMethods=true - -# -# Flag that indicates whether should we branch on and set static fields from trusted libraries or not. -# @see [org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES] -# -# Default value is [true] -ignoreStaticsFromTrustedLibraries=true - -# -# Use the sandbox in the concrete executor. -# If true, the sandbox will prevent potentially dangerous calls, e.g., file access, reading -# or modifying the environment, calls to `Unsafe` methods etc. -# If false, all these operations will be enabled and may lead to data loss during code analysis -# and test generation. -# -# Default value is [true] -useSandbox=true - -# -# Limit for number of generated tests per method (in each region) -# -# Default value is [50] -maxTestsPerMethodInRegion=50 - -# -# Max file length for generated test file -# -# Default value is [1000000] -maxTestFileSize=1000000 - -# -# If this options set in true, all soot classes will be removed from a Soot Scene, -# therefore, you will be unable to test soot classes. -# -# Default value is [true] -removeSootClassesFromHierarchy=true - -# -# If this options set in true, all UtBot classes will be removed from a Soot Scene, -# therefore, you will be unable to test UtBot classes. -# -# Default value is [true] -removeUtBotClassesFromHierarchy=true - -# -# Use this option to enable calculation and logging of MD5 for dropped states by statistics. -# Example of such logging: -# Dropping state (lastStatus=UNDEFINED) by the distance statistics. MD5: 5d0bccc242e87d53578ca0ef64aa5864 -# -# Default value is [false] -enableLoggingForDroppedStates=false - -# -# If this option set in true, depending on the number of possible types for -# a particular object will be used either type system based on conjunction -# or on bit vectors. -# @see useBitVecBasedTypeSystem -# -# Default value is [true] -useBitVecBasedTypeSystem=true - -# -# The number of types on which the choice of the type system depends. -# -# Default value is [64] -maxTypeNumberForEnumeration=64 - -# -# The threshold for numbers of types for which they will be encoded into solver. -# It is used to do not encode big type storages due to significand performance degradation. -# -# Default value is [512] -maxNumberOfTypesToEncode=512 From 8ab15789e69ff40bfd596570c21399caec4cb532 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 24 Nov 2022 17:18:57 +0300 Subject: [PATCH 12/16] Add AbstractSettings.areCustomized() ability to tell template from user-defined custom settings Make newly created ".utbot" folder hidden under Windows only --- .../org/utbot/common/AbstractSettings.kt | 17 ++++++++++++- .../intellij/plugin/settings/Settings.kt | 24 +++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt b/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt index d3db9a002e..0b3cd81b30 100644 --- a/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt +++ b/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt @@ -11,6 +11,9 @@ import kotlin.reflect.KProperty interface SettingsContainer { fun settingFor(defaultValue: T, converter: (String) -> T): PropertyDelegateProvider> + + // Returns true iff some properties have non-default values + fun isCustomized() = false } interface SettingsContainerFactory { @@ -47,6 +50,7 @@ class PropertiesSettingsContainer( } private val settingsValues: MutableMap, Any?> = mutableMapOf() + private var customized: Boolean = false inner class SettingDelegate(val property: KProperty<*>, val initializer: () -> T): ReadWriteProperty { private var value = initializer() @@ -74,7 +78,12 @@ class PropertiesSettingsContainer( return PropertyDelegateProvider { _, property -> SettingDelegate(property) { try { - properties.getProperty(property.name)?.let(converter) ?: defaultValue + properties.getProperty(property.name)?.let { + val parsedValue = converter.invoke(it) + customized = customized or (parsedValue != defaultValue) + parsedValue + } + defaultValue } catch (e: Throwable) { logger.info(e) { e.message } defaultValue @@ -83,6 +92,10 @@ class PropertiesSettingsContainer( } } + override fun isCustomized(): Boolean { + return customized + } + override fun toString(): String = settingsValues .mapKeys { it.key.name } @@ -115,6 +128,8 @@ abstract class AbstractSettings( } } + fun areCustomized(): Boolean = container.isCustomized() + protected fun getProperty( defaultValue: T, converter: (String) -> T diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt index 67855c30c7..cbff6ceaec 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/Settings.kt @@ -35,6 +35,7 @@ import org.utbot.framework.plugin.api.TreatOverflowAsError import org.utbot.intellij.plugin.models.GenerateTestsModel import java.util.concurrent.CompletableFuture import kotlin.reflect.KClass +import org.utbot.common.isWindows import org.utbot.framework.plugin.api.isSummarizationCompatible @State( @@ -176,19 +177,22 @@ class Settings(val project: Project) : PersistentStateComponent super.initializeComponent() CompletableFuture.runAsync { FileUtil.clearTempDirectory(UtSettings.daysLimitForTempFiles) - // In case settings.properties file is not yet presented in {homeDir}/.utbot folder - // we copy it from plugin resource file + + // Don't replace file with custom user's settings + if (UtSettings.areCustomized()) return@runAsync + // In case settings.properties file is not yet presented + // (or stays with all default template values) in {homeDir}/.utbot folder + // we copy (or re-write) it from plugin resource file val settingsClass = javaClass Paths.get(UtSettings.defaultSettingsPath()).toFile().apply { - if (!this.isFile) { - val parentFile = this.parentFile - if (parentFile.mkdirs()) Files.setAttribute(parentFile.toPath(), "dos:hidden", true) - try { - settingsClass.getResource("../../../../../settings.properties")?.let { - this.writeBytes(it.openStream().readBytes()) - } - } catch (ignored: IOException) { + try { + this.parentFile.apply { + if (this.mkdirs() && isWindows) Files.setAttribute(this.toPath(), "dos:hidden", true) + } + settingsClass.getResource("../../../../../settings.properties")?.let { + this.writeBytes(it.openStream().readBytes()) } + } catch (ignored: IOException) { } } } From 7cc19c0e1369893c109f330412dad04e803ae98d Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 24 Nov 2022 19:53:36 +0300 Subject: [PATCH 13/16] Fix misprints in Apache license text. Make all properties commented to be free switch our hardcoded defaults later if any. --- buildSrc/src/main/java/SettingsTemplateHelper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/java/SettingsTemplateHelper.java b/buildSrc/src/main/java/SettingsTemplateHelper.java index 0555feedcb..529496ad95 100644 --- a/buildSrc/src/main/java/SettingsTemplateHelper.java +++ b/buildSrc/src/main/java/SettingsTemplateHelper.java @@ -15,14 +15,14 @@ public class SettingsTemplateHelper { private static final String[] apacheLines = ("Copyright (c) " + new SimpleDateFormat("yyyy").format(System.currentTimeMillis()) + " The UnitTestBot Authors\n" + "\n" + - "Licensed under the Apache License, Version 2.0 (the \\License\\);\n" + + "Licensed under the Apache License, Version 2.0 (the \"License\");\n" + "you may not use this file except in compliance with the License.\n" + "You may obtain a copy of the License at\n" + "\n" + " http://www.apache.org/licenses/LICENSE-2.0\n" + "\n" + "Unless required by applicable law or agreed to in writing, software\n" + - "distributed under the License is distributed on an \\AS IS\\ BASIS,\n" + + "distributed under the License is distributed on an \"AS IS\" BASIS,\n" + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + "See the License for the specific language governing permissions and\n" + "limitations under the License.").split("\n"); @@ -165,7 +165,7 @@ public boolean test(String s) { writer.println("#"); writer.println("# Default value is [" + model.defaultValue + "]"); } - writer.println(model.key + "=" + model.defaultValue); + writer.println("#" + model.key + "=" + model.defaultValue); } writer.flush(); writer.close(); From 5c1328fca40f577a0354a6aa82281e4dac2d8d6f Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 2 Dec 2022 18:52:23 +0300 Subject: [PATCH 14/16] Fix an issue with always-default settings state. Change copyright in the license template to utbot.org --- buildSrc/src/main/java/SettingsTemplateHelper.java | 2 +- utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/java/SettingsTemplateHelper.java b/buildSrc/src/main/java/SettingsTemplateHelper.java index 529496ad95..099d019456 100644 --- a/buildSrc/src/main/java/SettingsTemplateHelper.java +++ b/buildSrc/src/main/java/SettingsTemplateHelper.java @@ -13,7 +13,7 @@ public class SettingsTemplateHelper { private static final String[] apacheLines = - ("Copyright (c) " + new SimpleDateFormat("yyyy").format(System.currentTimeMillis()) + " The UnitTestBot Authors\n" + + ("Copyright (c) " + new SimpleDateFormat("yyyy").format(System.currentTimeMillis()) + " utbot.org\n" + "\n" + "Licensed under the Apache License, Version 2.0 (the \"License\");\n" + "you may not use this file except in compliance with the License.\n" + diff --git a/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt b/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt index 0b3cd81b30..d40ae54134 100644 --- a/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt +++ b/utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt @@ -81,7 +81,7 @@ class PropertiesSettingsContainer( properties.getProperty(property.name)?.let { val parsedValue = converter.invoke(it) customized = customized or (parsedValue != defaultValue) - parsedValue + return@SettingDelegate parsedValue } defaultValue } catch (e: Throwable) { From 270aa3c92fd1750992a0e21cc98e330f87fb595e Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 2 Dec 2022 18:54:57 +0300 Subject: [PATCH 15/16] Fix a misprint in UtSettings property name "treatAssertAsErrorSuite" --- .../src/main/kotlin/org/utbot/framework/UtSettings.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index d6f261323f..fc34064e43 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -232,7 +232,7 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS /** * Generate tests that treat assertions as error suits. */ - var treatAssertAsErrorSuit: Boolean by getBooleanProperty(true) + var treatAssertAsErrorSuite: Boolean by getBooleanProperty(true) /** * Instrument all classes before start From b6e4ea7e6a3cc7d8565f86f39d475ba6cebbf21d Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 2 Dec 2022 19:04:26 +0300 Subject: [PATCH 16/16] Fix a misprint in UtSettings property name "treatAssertAsErrorSuite" --- .../org/utbot/framework/codegen/tree/CgMethodConstructor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMethodConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMethodConstructor.kt index 8b8d5b8ebc..4e8a7c8133 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMethodConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMethodConstructor.kt @@ -405,7 +405,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte if (exception is AccessControlException) return false // tests with timeout or crash should be processed differently if (exception is TimeoutException || exception is ConcreteExecutionFailureException) return false - if (UtSettings.treatAssertAsErrorSuit && exception is AssertionError) return false + if (UtSettings.treatAssertAsErrorSuite && exception is AssertionError) return false val exceptionRequiresAssert = exception !is RuntimeException || runtimeExceptionTestsBehaviour == PASS val exceptionIsExplicit = execution.result is UtExplicitlyThrownException