Skip to content

Rd & logs refactoring #1399

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 26, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[rd-refactoring]
Enabling suspend and port choosing by utsettings
Run configurations for debugging
Instant process death detection
Orphan processes termination system
Some text loading optimization
ChildProcess -> InstrumentedProcess
Rd-based UtSettings for InstrumentedProcess
  • Loading branch information
Domonion committed Nov 25, 2022
commit a2c9b5a829f55a7319ba39e232c706cb1a31649e
2 changes: 1 addition & 1 deletion .github/workflows/build-and-run-tests-from-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ jobs:
name: utbot_temp ${{ matrix.project.PART_NAME }}
path: |
/tmp/UTBot/generated*/*
/tmp/UTBot/utbot-childprocess-errors/*
/tmp/UTBot/utbot-instrumentedprocess-errors/*
- name: Upload test report if tests have failed
if: ${{ failure() }}
uses: actions/upload-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-chosen-tests-from-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
name: generated-tests
path: |
/tmp/UTBot/generated*/*
/tmp/UTBot/utbot-childprocess-errors/*
/tmp/UTBot/utbot-instrumentedprocess-errors/*
- name: Upload utbot-framework logs
if: ${{ always() && github.event.inputs.project-name == 'utbot-framework' }}
uses: actions/upload-artifact@v3
Expand Down
8 changes: 8 additions & 0 deletions .run/Debug All.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Debug All" type="CompoundRunConfigurationType">
<toRun name="Run IDE" type="GradleRunConfiguration" />
<toRun name="Listen for Concrete Executor Process" type="Remote" />
<toRun name="Listen for Engine Process" type="Remote" />
<method v="2" />
</configuration>
</component>
7 changes: 7 additions & 0 deletions .run/Debug Engine Process.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Debug Engine Process" type="CompoundRunConfigurationType">
<toRun name="Run IDE" type="GradleRunConfiguration" />
<toRun name="Listen for Engine Process" type="Remote" />
<method v="2" />
</configuration>
</component>
7 changes: 7 additions & 0 deletions .run/Debug Instrumented Process.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Debug Instrumented Process" type="CompoundRunConfigurationType">
<toRun name="Run IDE" type="GradleRunConfiguration" />
<toRun name="Listen for Instrumented Process" type="Remote" />
<method v="2" />
</configuration>
</component>
15 changes: 15 additions & 0 deletions .run/Listen for Engine Process.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Listen for Engine Process" type="Remote" folderName="Utility Configurations">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="true" />
<option name="SHMEM_ADDRESS" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<option name="AUTO_RESTART" value="true" />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="5005" />
<option name="LOCAL" value="false" />
</RunnerSettings>
<method v="2" />
</configuration>
</component>
15 changes: 15 additions & 0 deletions .run/Listen for Instrumented Process.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Listen for Instrumented Process" type="Remote" folderName="Utility Configurations">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="true" />
<option name="SHMEM_ADDRESS" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5006" />
<option name="AUTO_RESTART" value="true" />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="5006" />
<option name="LOCAL" value="false" />
</RunnerSettings>
<method v="2" />
</configuration>
</component>
23 changes: 23 additions & 0 deletions .run/Run IDE.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run IDE" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/utbot-intellij" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>
10 changes: 5 additions & 5 deletions docs/RD for UnitTestBot.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,21 @@ Usefull:
2. There are some usefull classes to work with processes & rd:
- ```LifetimedProcess``` - binds ```Lifetime``` to process. If process dies - lifetime terminates and vice versa. You can terminate lifetime manually - this will destroy process.
- ```ProcessWithRdServer``` - also starts Rd server and waits for connection.
- ```UtInstrumentationProcess``` - encapsulates logic for preparing child process for executing arbitary commands. Exposes ```protocolModel``` for communicating with child process.
- ```UtInstrumentationProcess``` - encapsulates logic for preparing instrumented process for executing arbitary commands. Exposes ```protocolModel``` for communicating with instrumented process.
- ```ConcreteExecutor``` is convenient wrapper for executing commands and managing resources.
3. How child communication works:
- Choosing free port
- Creating child process, passing port as argument
- Creating instrumented process, passing port as argument
- Both processes create protocols and bind model
- Child process setups all callbacks
- Instrumented process setups all callbacks
- Parent process cannot send messages before child creates protocol, otherwise messages will be lost. So child process needs to signal that he is ready.
- Child proces creates special file in temp dir, that is observed by parent process.
- Instrumented proces creates special file in temp dir, that is observed by parent process.
- When parent process spots file - he deletes it, and then sends special message for preparing child proccess instrumentation
- Only then process is ready for executing commands
4. How to write custom commands for child process
- Add new ```call``` in ```ProtocolModel```
- Regenerate models
- Add callback for new ```call``` in ```ChildProcess.kt```
- Add callback for new ```call``` in ```InstrumentedProcess.kt```
- Use ```ConcreteExecutor.withProcess``` method
- ___Important___ - do not add `Rdgen` as implementation dependency, it breaks some `.jar`s as it contains `kotlin-compiler-embeddable`.
5. Logs
Expand Down
6 changes: 5 additions & 1 deletion docs/contributing/InterProcessDebugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ The most straightforward way to debug the Engine process is the following.

1. Open `org/utbot/framework/UtSettings.kt`.
2. Set `runIdeaProcessWithDebug` property to _true_. This enables `EngineProcess.debugArgument`.
3. Find `EngineProcess.debugArgument` at `org/utbot/intellij/plugin/process/EngineProcess` and check the parameters of the debug run:
* Alternatively you can create `~/.utbot/settings.properties` file and write following:
```
runIdeaProcessWithDebug=true
```
4. Find `EngineProcess.debugArgument` at `org/utbot/intellij/plugin/process/EngineProcess` and check the parameters of the debug run:

`"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=5005"`

Expand Down
5 changes: 1 addition & 4 deletions utbot-core/src/main/kotlin/org/utbot/common/JvmUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,4 @@ private val javaSpecificationVersion = System.getProperty("java.specification.ve
val isJvm8 = javaSpecificationVersion.equals("1.8")
val isJvm9Plus = !javaSpecificationVersion.contains(".") && javaSpecificationVersion.toInt() >= 9

fun osSpecificJavaExecutable() = if (isWindows) "javaw" else "java"

const val engineProcessDebugPort = 5005
const val childProcessDebugPort = 5006
fun osSpecificJavaExecutable() = if (isWindows) "javaw" else "java"
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private const val defaultKeyForSettingsPath = "utbot.settings.path"
/**
* Default concrete execution timeout (in milliseconds).
*/
const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS = 1000L
const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS = 1000L

object UtSettings : AbstractSettings(
logger, defaultKeyForSettingsPath, defaultSettingsPath
Expand Down Expand Up @@ -260,44 +260,64 @@ object UtSettings : AbstractSettings(
/**
* Timeout for specific concrete execution (in milliseconds).
*/
var concreteExecutionTimeoutInChildProcess: Long by getLongProperty(
DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS
var concreteExecutionTimeoutInInstrumentedProcess: Long by getLongProperty(
DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
)

/**
* Log level for concrete executor process.
* Log level for instrumented process.
*/
var childProcessLogLevel by getEnumProperty(LogLevel.Info)
var instrumentedProcessLogLevel by getEnumProperty(LogLevel.Info)

/**
* Path to custom log4j2 configuration file for EngineProcess.
* By default utbot-intellij/src/main/resources/log4j2.xml is used.
* Also default value is used if provided value is not a file.
*/
var ideaProcessLogConfigFile by getStringProperty("")
var engineProcessLogConfigFile by getStringProperty("")

/**
* Property useful only for idea
* If true - runs engine process with the ability to attach a debugger
* @see runChildProcessWithDebug
* @see runInstrumentedProcessWithDebug
* @see org.utbot.intellij.plugin.process.EngineProcess
*/
var runIdeaProcessWithDebug by getBooleanProperty(false)
var runEngineProcessWithDebug by getBooleanProperty(false)

/**
* If true, runs the child process with the ability to attach a debugger.
* Port which will be used for debugging engine process
*/
var engineProcessDebugPort by getIntProperty(5005)

/**
* Whether engine process should suspend until debugger attached
*/
var engineProcessDebugSuspendPolicy by getBooleanProperty(true)

/**
* Port which will be used for debugging instrumented process
*/
var instrumentedProcessDebugPort by getIntProperty(5006)

/**
* Whether instrumented process should suspend until debugger attached
*/
var instrumentedProcessSuspendPolicy by getBooleanProperty(true)

/**
* If true, runs the instrumented 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.
* To debug the instrumented process, set the breakpoint in the instrumentedProcessRunner.start() line
* and in the instrumented 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
* Now you can put the breakpoints in the instrumented process and debug
* both processes simultaneously.
*
* @see [org.utbot.instrumentation.process.ChildProcessRunner.cmds]
* @see [org.utbot.instrumentation.process.InstrumentedProcessRunner.cmds]
*/
var runChildProcessWithDebug by getBooleanProperty(false)
var runInstrumentedProcessWithDebug by getBooleanProperty(false)

/**
* Number of branch instructions using for clustering executions in the test minimization phase.
Expand Down Expand Up @@ -391,7 +411,7 @@ object UtSettings : AbstractSettings(
var ignoreStaticsFromTrustedLibraries by getBooleanProperty(true)

/**
* Use the sandbox in the concrete executor.
* Use the sandbox in the instrumented process.
*
* If true (default), the sandbox will prevent potentially dangerous calls, e.g., file access, reading
* or modifying the environment, calls to `Unsafe` methods etc.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ data class UtTimeoutException(override val exception: TimeoutException) : UtExec

/**
* Indicates failure in concrete execution.
* For now it is explicitly throwing by ConcreteExecutor in case child process death.
* For now it is explicitly throwing by ConcreteExecutor in case instrumented process death.
*/
class ConcreteExecutionFailureException(cause: Throwable, errorFile: File, val processStdout: List<String>) :
Exception(
buildString {
appendLine()
appendLine("----------------------------------------")
appendLine("The child process is dead")
appendLine("The instrumented process is dead")
appendLine("Cause:\n${cause.message}")
appendLine("Last 1000 lines of the error log ${errorFile.absolutePath}:")
appendLine("----------------------------------------")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ data class JdkInfo(
/**
* Singleton to enable abstract access to path to JDK.

* Used in [org.utbot.instrumentation.process.ChildProcessRunner].
* Used in [org.utbot.instrumentation.process.InstrumentedProcessRunner].
* The purpose is to use the same JDK in [org.utbot.instrumentation.ConcreteExecutor] and in the test runs.
* This is necessary because the engine can be run from the various starting points, like IDEA plugin, CLI, etc.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.nio.file.Paths
/**
* Singleton to enable abstract access to the working directory.
*
* Used in [org.utbot.instrumentation.process.ChildProcessRunner].
* Used in [org.utbot.instrumentation.process.InstrumentedProcessRunner].
* The purpose is to use the same working directory in [org.utbot.instrumentation.ConcreteExecutor]
* and in the test runs.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ internal class StringExamplesTest : UtValueTestCaseChecker(
{ _, i, r -> i <= 0 && r.isException<IllegalArgumentException>() },
{ cs, i, r -> i > 0 && cs == null && !r.getOrThrow() },
{ cs, i, r -> i > 0 && cs != null && cs.length > i && r.getOrThrow() },
coverage = DoNotCalculate // TODO: Coverage calculation fails in the child process with Illegal Argument Exception
coverage = DoNotCalculate // TODO: Coverage calculation fails in the instrumented process with Illegal Argument Exception
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class UtBotSymbolicEngine(
*/
fun fuzzing(until: Long = Long.MAX_VALUE, modelProvider: (ModelProvider) -> ModelProvider = { it }) = flow {
val isFuzzable = methodUnderTest.parameters.all { classId ->
classId != Method::class.java.id && // causes the child process crash at invocation
classId != Method::class.java.id && // causes the instrumented process crash at invocation
classId != Class::class.java.id // causes java.lang.IllegalAccessException: java.lang.Class at sun.misc.Unsafe.allocateInstance(Native Method)
}
if (!isFuzzable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.utbot.framework.codegen.domain

import org.utbot.framework.DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS
import org.utbot.framework.DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
import org.utbot.framework.codegen.domain.builtin.mockitoClassId
import org.utbot.framework.codegen.domain.builtin.ongoingStubbingClassId
import org.utbot.framework.codegen.domain.models.CgClassId
Expand Down Expand Up @@ -581,7 +581,7 @@ data class HangingTestsTimeout(val timeoutMs: Long) {
constructor() : this(DEFAULT_TIMEOUT_MS)

companion object {
const val DEFAULT_TIMEOUT_MS = DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS
const val DEFAULT_TIMEOUT_MS = DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
const val MIN_TIMEOUT_MS = 100L
const val MAX_TIMEOUT_MS = 1_000_000L
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ import kotlin.reflect.jvm.javaMethod
* @property [stateBefore] is necessary for construction of parameters of a concrete call.
* @property [instrumentation] is necessary for mocking static methods and new instances.
* @property [timeout] is timeout for specific concrete execution (in milliseconds).
* By default is initialized from [UtSettings.concreteExecutionTimeoutInChildProcess]
* By default is initialized from [UtSettings.concreteExecutionTimeoutInInstrumentedProcess]
*/
data class UtConcreteExecutionData(
val stateBefore: EnvironmentModels,
val instrumentation: List<UtInstrumentation>,
val timeout: Long = UtSettings.concreteExecutionTimeoutInChildProcess
val timeout: Long = UtSettings.concreteExecutionTimeoutInInstrumentedProcess
)

class UtConcreteExecutionResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import org.utbot.framework.plugin.api.UtVoidModel
* We have 4 different test suites:
* * Regression suite
* * Error suite (invocations in which implicitly thrown unchecked exceptions reached to the top)
* * Crash suite (invocations in which the child process crashed or unexpected exception in our code occurred)
* * Crash suite (invocations in which the instrumented process crashed or unexpected exception in our code occurred)
* * Timeout suite
*
* We want to minimize tests independently in each of these suites.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ open class TestCaseGenerator(
}
}
}
ConcreteExecutor.defaultPool.close() // TODO: think on appropriate way to close child processes
ConcreteExecutor.defaultPool.close() // TODO: think on appropriate way to close instrumented processes


return methods.map { method ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private val logger = KotlinLogging.logger {}
* and their versions correspond to our requirements.
*
* Note: [UtExecutionInstrumentation] must be in dependency path too
* as it is used by Engine in the child process in Concrete Executor.
* as it is used by Engine in the instrumented process in Concrete Executor.
*/
fun checkFrameworkDependencies(dependencyPaths: String?) {
if (dependencyPaths.isNullOrEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
import org.utbot.instrumentation.util.KryoHelper
import org.utbot.rd.IdleWatchdog
import org.utbot.rd.ClientProtocolBuilder
import org.utbot.rd.RdSettingsContainerFactory
import org.utbot.rd.findRdPort
import org.utbot.rd.generated.settingsModel
import org.utbot.rd.loggers.UtRdKLoggerFactory
import org.utbot.sarif.RdSourceFindingStrategyFacade
import org.utbot.sarif.SarifReport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class EngineProcessModel private constructor(
@JvmStatic
@Deprecated("Use protocol.engineProcessModel or revise the extension scope instead", ReplaceWith("protocol.engineProcessModel"))
fun create(lifetime: Lifetime, protocol: IProtocol): EngineProcessModel {
EngineProcessProtocolRoot.register(protocol.serializers)
EngineProcessRoot.register(protocol.serializers)

return EngineProcessModel().apply {
identify(protocol.identity, RdId.Null.mix("EngineProcessModel"))
Expand Down
Loading