diff --git a/.github/workflows/build-and-run-tests-from-branch.yml b/.github/workflows/build-and-run-tests-from-branch.yml
index d21242d320..ff5f7e456c 100644
--- a/.github/workflows/build-and-run-tests-from-branch.yml
+++ b/.github/workflows/build-and-run-tests-from-branch.yml
@@ -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
diff --git a/.github/workflows/run-chosen-tests-from-branch.yml b/.github/workflows/run-chosen-tests-from-branch.yml
index 97264dac0d..786c55eeb7 100644
--- a/.github/workflows/run-chosen-tests-from-branch.yml
+++ b/.github/workflows/run-chosen-tests-from-branch.yml
@@ -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
diff --git a/.run/Debug All.run.xml b/.run/Debug All.run.xml
new file mode 100644
index 0000000000..1bca69c71e
--- /dev/null
+++ b/.run/Debug All.run.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Debug Engine Process.run.xml b/.run/Debug Engine Process.run.xml
new file mode 100644
index 0000000000..1b6d823900
--- /dev/null
+++ b/.run/Debug Engine Process.run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Debug Instrumented Process.run.xml b/.run/Debug Instrumented Process.run.xml
new file mode 100644
index 0000000000..a687624701
--- /dev/null
+++ b/.run/Debug Instrumented Process.run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Listen for Engine Process.run.xml b/.run/Listen for Engine Process.run.xml
new file mode 100644
index 0000000000..b6e8bbca90
--- /dev/null
+++ b/.run/Listen for Engine Process.run.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Listen for Instrumented Process.run.xml b/.run/Listen for Instrumented Process.run.xml
new file mode 100644
index 0000000000..bf7dda5c5c
--- /dev/null
+++ b/.run/Listen for Instrumented Process.run.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Run IDE.run.xml b/.run/Run IDE.run.xml
new file mode 100644
index 0000000000..10d313f7d7
--- /dev/null
+++ b/.run/Run IDE.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/docs/RD for UnitTestBot.md b/docs/RD for UnitTestBot.md
index 7b88a2798b..48064d5424 100644
--- a/docs/RD for UnitTestBot.md
+++ b/docs/RD for UnitTestBot.md
@@ -1,5 +1,31 @@
-# RD
-New child process communication involves 3 different things:
+# Multi-process architecture
+
+## Table of content
+- [Overview](#overview)
+- [Lifetimes](#lifetimes)
+ - [Lifetime](#lifetime)
+ - [LifetimeDefinition](#lifetimedefinition)
+- [Rd](#rd)
+- [Rdgen](#rdgen)
+ - [Model DSL](#model-dsl)
+ - [Gradle](#gradle)
+- [UtBot project](#utbot-project)
+ - [IDEA process](#idea-process)
+ - [Engine process](#engine-process)
+ - [Instrumented process](#instrumented-process)
+ - [Commons](#useful)
+
+## Overview
+UtBot consists of 3 different processes:
+1. `IDEA process` - the one where plugin part executes. Also can be called `plugin process`, `IDE process`.
+2. `Engine process` - process where unit test generation engine executes.
+3. `InstrumentedProces` - process where concrete execution takes place.
+
+These processes are built on top of [JetBrains.RD](https://github.com/JetBrains/rd). It is crucial to understand
+this library, so it's better describing it first(as there are no documentation about it in repo;)).
+
+RD is mostly about 3 components:
+
1. Lifetimes
2. Rd entities
3. Rdgen
@@ -21,7 +47,7 @@ And so Lifetime was introduced.
### Lifetime:
```Lifetime``` is a class, where you can register callbacks and which can be terminated once, thus executing all registered callbacks.
-```Lifetime``` is an abstract class, it's inheritor - ```LifetimeDefinition```. The only difference - only ```LifetimeDefinition``` can be terminated. Though all ```Lifetime``` are instances of ```LifetimeDefinition```, there are some conventions:
+```Lifetime``` is an abstract class, it's inheritor - ```LifetimeDefinition```. The only difference - ```LifetimeDefinition``` can be terminated. Though all ```Lifetime``` are instances of ```LifetimeDefinition```, there are some conventions:
1. Do not cast ```Lifetime``` to ```LifetimeDefinion``` unless you are the one who created ```LifetimeDefinition```.
2. If you introduce somewhere ```LifetimeDefinition``` - either attach it to another ```Lifetime``` or provide code that terminates it.
@@ -100,42 +126,67 @@ DSL:
## UtBot project
-There is another gradle project ```utbot-rd``` which contains model sources in ```rdgenModels``` sources. Look for ```org.utbot.rd.models.ProtocolRoot```.
+There is another gradle project ```utbot-rd``` which contains model sources in ```rdgenModels```.
+Look at [```utbot-rd/src/main/rdgen/org/utbot/rd/models```](../utbot-rd/src/main/rdgen/org/utbot/rd/models)
+
+### IDEA process
+Uses bundled JetBrains JDK. Code in `utbot-intellij` ___must___ be compatible will all JDKs and plugin SDKs, which are used by our officially supported IntellijIDEA versions.
+See [`utbot-intellij/build.gradle.kts`](../utbot-intellij/build.gradle.kts), parts `sinceBuild` and `untilBuild`.
+
+Starts `Engine process`. Maintains `UtSettings` instance in memory and updates it from IDEA.
+Other processes ask this process for settings via RD RPC.
+
+### Engine process
+
+`TestCaseGenerator` and `UtBotSymbolicEngine` run here. Process classpath contains all plugin jars(more precisely - it uses plugin classpath).
+
+___Must___ run on JDK, which uses project we analyze. Otherwise there will be numerous problems with code analysis, soot, reflection and
+devirgention of generated code Java API.
+
+Currently, it is prohibited to run more than 1 generation process simultaneously(something with native libs).
+However, logging for processes relies on that fact, so they can exclusively write to log file.
+
+IDEA starting point - class [`EngineProcess`](../utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt).
+Process start file - [`EngineProcessMain`](../utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt).
+Starts `Instrumented process`.
+
+### Instrumented process
+
+Start points at `Engine process`: classes [`InstrumentedProcess`](../utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/rd/InstrumentedProcess.kt) and [`ConcreteExecutor`](../utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/ConcreteExecutor.kt).
+First one is state encapsulation, second is used to implement request logic for concrete execution.
+
+Runs on the same JDK as `Engine process` to erase deviation from `Engine process`.
+Sometimes might unexpectedly die due concrete execution.
+
+
+### Useful
-Usefull:
1. if you need to use rd somewhere - add following dependencies:
```
- implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: 'actual.version'
+ implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: rdVersion
- implementation group: 'com.jetbrains.rd', name: 'rd-core', version: 'actual.version'
+ implementation group: 'com.jetbrains.rd', name: 'rd-core', version: rdVersion
```
-2. There are some usefull classes to work with processes & rd:
+2. There are some useful classes in `utbot-rd` 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.
- - ```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
- - Both processes create protocols and bind model
- - Child 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.
- - 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```
- - 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
-
- There is ```UtRdLogger``` where you can configure level via ```log4j2.xml```.
-
+ - ```ProcessWithRdServer``` - also starts Rd server and waits for connection.
+ - `ClientProtocolBuilder` - use in client process to correctly connect to `ProcessWithRdServer`.
+3. How ```ProcessWithRdServer``` communication works:
+ - Choose free port
+ - Create client process, pass port as argument
+ - Both processes create protocols, bind model and setup callbacks
+ - Server process cannot send messages before child creates protocol, otherwise messages will be lost. So client process needs to signal that he is ready.
+ - Client process 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 client process confirming communication succeed.
+ - Only after client process answer reaches server - then processes are ready.
+4. How to write custom RPC commands
+ - Add new ```call``` in some model, for example in ```EngineProcessModel```.
+ - Regenerate models: there are special gradle tasks for it in `utbot-rd/build.gradle` file.
+ - Add callback for new ```call``` in corresponding start files, for example in `EngineProcessMain.kt`.
+ - ___Important___ - do not add [`Rdgen`](https://mvnrepository.com/artifact/com.jetbrains.rd/rd-gen) as implementation dependency, it breaks some `.jar`s as it contains `kotlin-compiler-embeddable`.
+5. Logs & Debug
+ - Logs - [inter process logging](./contributing/InterProcessLogging.md)
+ - Debug - [inter process debugging](./contributing/InterProcessDebugging.md)
6. Custom protocol marshalling types
-
- Do not spend time on it until:
- - Cyclic dependencies removed from UtModels
- - Kotlinx.serialization is used
+ Do not spend time on it until UtModels would get simpler, for example Kotlinx.serialization compatible.
diff --git a/docs/contributing/InterProcessDebugging.md b/docs/contributing/InterProcessDebugging.md
index b3b4ca363e..959f0ec20d 100644
--- a/docs/contributing/InterProcessDebugging.md
+++ b/docs/contributing/InterProcessDebugging.md
@@ -2,81 +2,107 @@
### Background
-We have split the UnitTestBot machinery into three processes. This approach has improved UnitTestBot capabilities, e.g.
-provided support for various JVMs and scenarios, but also complicated the debugging flow.
+We have split the UnitTestBot machinery into three processes. See [doc about processes](../RD%20for%20UnitTestBot.md).
+This approach has improved UnitTestBot capabilities, e.g. provided support for various JVMs and scenarios, but also complicated the debugging flow.
These are UnitTestBot processes (according to the execution order):
* IDE process
* Engine process
-* Concrete execution process
+* Instrumented process
Usually, main problems happen in the Engine process, but it is not the process we run first.
The most straightforward way to debug the Engine process is the following.
-### Enable debugging for the Engine process
-
-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:
-
- `"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=5005"`
-
-* The `suspend` mode is enabled. Modify it in the case of some tricky timeouts in your scenario.
-* The port that will be used for debugging (`address`) is set to `5005`. Modify it if the port is already in use on your system.
-
-### Create a new run configuration for debugging the Engine process
-
-In addition to the `runIde` Gradle task that is supposed to run a new IDE instance, we should create another run
-configuration.
-
-1. In your IntelliJ IDEA go to **Ru**n > **Edit configurations…**.
-2. In the **Run/Debug Configuration** dialog, click **`+`** on the toolbar.
-3. In the **Run/Debug Configuration Templates** dialog that opens, select a **Remote JVM Debug** configuration type.
-4. Check that **Port** has the same number as the `address` parameter from the `EngineProcess.debugArgument` mentioned above.
-5. Give the new run configuration a meaningful name and save the run configuration.
+### Enable Debugging
+
+IDE debugging is pretty straightforward - start `runIde` task in `utbot-intellij` project from IDEA with debug.
+
+For engine and instrumented processes you need to enable some options:
+1. Open [`UtSettings.kt`](../../utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt)
+2. There are 2 similar options: `runEngineProcessWithDebug` and `runInstrumentedProcessWithDebug`.
+3. Enable for processes you need to debug. It can be done in 2 ways:
+ * Can create `~/.utbot/settings.properties` file and write following:
+ ```
+ runEngineProcessWithDebug=true
+ runInstrumentedProcessWithDebug=true
+ ```
+ After you will need to restart IDEA you want to debug.
+ * ***Discouraged***: change in source file, but this will involve moderate project recompilation.
+4. Additionally, you can set additional options for JDWP agent if debug is enabled:
+ * `engineProcessDebugPort` and `instrumentedProcessDebugPort` - port for debugging.
+ Default values - 5005 for Engine and 5006 for Instrumented processes.
+ * `suspendEngineProcessExecutionInDebugMode` and `suspendInstrumentedProcessExecutionInDebugMode` - whether JDWP agent should
+ suspend process until debugger is connected.
+
+ More formally, if debug is enabled following switch is added to engine process JVM at start by default:
+
+ ```
+ -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=5005"
+ ```
+ These options regulate values for parts `suspend` and `address`, for example with following in `~/.utbot/settings.properties`:
+ ```
+ runEngineProcessWithDebug=true
+ engineProcessDebugPort=12345
+ suspendEngineProcessExecutionInDebugMode=false
+ ```
+ result switch will be:
+ ```
+ -agentlib:jdwp=transport=dt_socket,server=n,suspend=y,quiet=y,address=12345"
+ ```
+ See `org.utbot.intellij.plugin.process.EngineProcess.Companion.getDebugArgument`
+5. For information about logs - see [this](InterProcessLogging.md).
+
+### Run configurations for debugging the Engine process
+
+There are 3 basic run configurations:
+1. `Run IDE` - run plugin in IDEA
+2. `Utility configuration/Listen for Instrumented Process` - listen on 5006 port if instrumented process is available for debug
+3. `Utility configuration/Listen for Engine Process` - listen on 5005 port if engine process is available for debug
+
+On top of them, there are 3 compound run configurations for debugging:
+1. `Debug Engine Process` and `Debug Instrumented Process` - combo for debug IDE and selected process
+3. `Debug All` - debug all 3 processes.
+
+For debug configurations to work you need to provide required properties in `~/.utbot/settings.properties`.
+If you either change port and/or suspend mode - do review utility configuration to change default values as well.
### How to debug
-1. In your current IntelliJ IDEA, use breakpoints to define where the program needs to be stopped. For example, set the breakpoints at
-
- `EngineProcess.createTestGenerator()`
- `engineModel().createTestGenerator.startSuspending()`
+Let's see through example of how to debug IDE to engine process communication.
-2. Start the debugger session (**Shift+F9**) for the `runIde` Gradle task (wait for the debug IDE instance to open).
-3. Generate tests with UnitTestBot in the debug IDE instance. Make sure symbolic execution is turned on.
+1. In your current IntelliJ IDEA with source, use breakpoints to define where the program needs to be stopped. For example, set the breakpoints at `EngineProcess.generate`
+ and somewhere in `watchdog.wrapActiveCall(generate)`.
+2. Select `Debug Engine Process` configuration, add required parameters to `~/.utbot/settings.properties` and start debug.
+3. Generate tests with UnitTestBot in the debug IDE instance.
4. The debug IDE instance will stop generation (if you have not changed the debug parameters). If you take no action, test generation will be cancelled by timeout.
5. When the Engine process started (build processes have finished, and the progress bar says: _"Generate tests: read
- classes"_), start the debugger session (**Shift+F9**) for your newly created Remote JVM Debug run configuration.
-6. Wait for the program to be suspended upon reaching the first breakpoint.
+ classes"_), there will be
+6. Wait for the program to be suspended upon reaching the first breakpoint in Engine proces.
+7. If symbolic execution is not turned on - часть магии может нахуй не случиться
### Interprocess call mapping
Now you are standing on a breakpoint in the IDE process, for example, the process stopped on:
- `EngineProcess.createTestGenerator()`
+ `EngineProcess.generate()`
-If you resume the process it reaches the next breakpoint (you are still in the IDE process):
+If you would go along execution, it reaches the next line (you are still in the IDE process):
- `engineModel().createTestGenerator.startSuspending()`
+ `engineModel.generate.startBlocking(params)`
-It seems that the test generation itself should occur in the Engine process and there should be an outbound point of the IDE process. How can we find it? An how can we reach the inbound point of the Engine process?
+It seems that the test generation itself should occur in the Engine process and there should be an entry point in the Engine process.
+How can we find it?
-Standing on the breakpoint` engineModel().createTestGenerator.startSuspending()`, you may **Go to Declaration or
-Usage** and navigate to the definition of `RdCall` (which is responsible for cross-process communication) in `EngineProcessModel.createTestGenerator`.
+Standing on the breakpoint `engineModel.generate.startBlocking(params)`, you may right-click in IDE on `EngineProcessModel.generate` and **Go to Declaration or
+Usage**. This would navigate to the definition of `RdCall` (which is responsible for cross-process communication) in file `EngineProcesModel.Generated.kt`.
-Now **Find Usages** for `EngineProcessModel.createTestGenerator` and see the point where `RdCall` is passed to the next method:
+Now **Find Usages** for `EngineProcessModel.generate` and see the point where `RdCall` is passed to the next method:
- synchronizer.measureExecutionForTermination()
+ watchdog.wrapActiveCall(generate)
This is the point where `RdCall` is called in the Engine process.
Actually you could have skipped the previous step and used **Find Usages** right away, but it is useful to know where `RdCall` is defined.
-If you are interested in the trailing lambda of `synchronizer.measureExecutionForTermination()`, set the breakpoint here.
-
-#### Architectural notice
-
-We must place the outbound point of the IDE process and the inbound point of the Engine process as close as possible.
-They may be two lambda-parameters of the same function. In this case we hope that the developer will not spend time on straying around.
-
+If you are interested in the trailing lambda of `watchdog.wrapActiveCall(generate)`, set the breakpoint here.
\ No newline at end of file
diff --git a/docs/contributing/InterProcessLogging.md b/docs/contributing/InterProcessLogging.md
new file mode 100644
index 0000000000..7377b09bbb
--- /dev/null
+++ b/docs/contributing/InterProcessLogging.md
@@ -0,0 +1,129 @@
+# Logging of UnitTestBot Java
+
+## Table of content
+- [IDE and Engine processes logs](#ide-and-engine-processes-logs)
+- [RD logs](#rd-logs)
+- [Instrumented process logs](#instrumented-process-logs)
+- [Useful & misc](#useful--misc)
+
+## IDE and Engine processes logs
+
+Logging for both IDE and engine processes are based on [`utbot-intellij/log4j2.xml`](../../utbot-intellij/src/main/resources/log4j2.xml).
+
+### IDE process
+Log configuration file is used as is, so if you want to configure logs in IDEA part - use it straight.
+If you want to change log configuration in already built plugin -
+use `Help > Diagnostic Tools > Debug Log Settings...` to change `log4j2.xml` configuration for plugin.
+
+### Engine process
+Things are a bit more complicated here.
+[`utbot-intellij/log4j2.xml`](../../utbot-intellij/src/main/resources/log4j2.xml) is copied in
+UtBot temporary directory - `org.utbot.common.FileUtilKt.getUtBotTempDirectory`,
+and then provided to JVM via following CLI switch:
+ ```
+ -Dlog4j2.configurationFile=%configuration_file%
+ ```
+
+where `%configuration_file%` will be either:
+1. Modified copy of [`utbot-intellij/log4j2.xml`](../../utbot-intellij/src/main/resources/log4j2.xml) at UtBot temp directory.
+
+ More precisely, there are 2 appenders in configuration file:
+ ```xml
+
+
+
+
+
+
+
+
+ ```
+ By default `IdeaAppender` is used everywhere in file.
+ Idea catches plugin stdout log and wraps with own format, so in IDE log only `%msg` is logged.
+
+ When working as engine process - temporary `log4j2.`xml would be created, in which
+ substring `ref="IdeaAppender"` will be replaced with `ref="EngineProcessAppender"`,
+ thus changing all appenders and log pattern, but preserving same categories and log level.
+
+2. Path from `UtSettings.engineProcessLogConfigFile`.
+
+ This option allows to provide path to external Log4j2 configuration file instead of [`utbot-intellij/log4j2.xml`](../../utbot-intellij/src/main/resources/log4j2.xml).
+ At `~/.utbot/settings.properties` you can set path to custom configuration file,
+ which would apply for engine process, for example:
+ ```
+ engineProcessLogConfigFile=C:\wrk\UTBotJava\engineProcessLog4j2.xml
+ ```
+ This allows you to configure logs even for already built plugin,
+ you need only to restart IDE.
+
+## RD logs
+
+RD has its own logging system with different interface for logging,
+see `com.jetbrains.rd.util.Logger`.
+
+Obtain logger via global function `getLogger()` from `rd-core.jar`.
+By default, logger writes to `stderr` messages with `Warn` or higher log level,
+and stdout for others.
+
+You can set which logger you want RD to use via `com.jetbrains.rd.util.ILoggerFactory` interface.
+To set factory use `Logger.set(Lifetime, ILoggerFactory)` method,
+for example this code overrides RD logs with `KotlinLogging`:
+
+```kotlin
+Logger.set(object: ILoggerFactory {
+ override fun getLogger(category: String): Logger {
+ return KotlinLogging.logger(category)
+ }
+})
+```
+
+There are already 2 factories:
+1. `UtRdConsoleLoggeFactory` - allows to write stdin/stdout in a format compatible with IDEA `logj42` configuration.
+2. `UtRdKLoggerFactory` - smart adapter from RD to KotlinLogger loggers.
+
+### Details
+Setup logger factory before any RD logs occurred, as you might lose some at RD start when loggers are configured to stdout.
+The only way to configure RD logs - programmatically. There are no configuration files and/or services.
+
+Rd logger dynamically reconfigures as new logger factories arrive, see `com.jetbrains.rd.util.SwitchLogger` for
+more details.
+
+Although RD produce ___A LOT OF LOGS___ - for 2-3 test generation logs
+file will contain ~800mb of text related to logs, nearly all RD logs has `Trace` log level. You `Trace` with care!
+
+## Instrumented process logs
+
+Instrumented process have different logging due to class mocking limitation:
+in some cases we want to mock loggers, and for that we would need to mock static function like `getLogger` etc.
+In that case if we use that logger in UtBot - we might get incorrect version which in fact is mock.
+
+Instead, you should use hand-made logging based on RD as described in [RD logs section](#rd-logs).
+
+To configure instrumented process log level - use `UtSettings.instrumentedProcessLogLevel` property,
+for example add in settings.properties:
+
+```kotlin
+instrumentedProcessLogLevel=Debug
+```
+
+## Useful & misc
+
+### Log4j2
+
+Sometimes your log entries might duplicate when using log4j or similar.
+One of the reason might be *additivity*, read [here](https://logging.apache.org/log4j/2.x/manual/configuration.html#Additivity)
+about how to solve it.
+
+Also, log4j2 automatically reconfigures when detects changes in log file. Default check timeout - 30s.
+
+### Output files for processes
+
+In `idea.log` there will be a path to engine process log file:
+```
+Engine process log file - %path-to-engine-process-log%
+```
+
+And similarly in engine process log file will be entry:
+```
+Instrumented process log file: %path-to-instrumented-process-log%
+```
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 1392b4d345..df3c1d4b4d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -28,6 +28,11 @@ kotlinVersion=1.7.20
log4j2Version=2.13.3
coroutinesVersion=1.6.3
collectionsVersion=0.3.4
+# after updating plugin version you should manually bump corresponding versions in plugin
+# as they cannot be set from properties
+# utbot-intellij/build.gradle.kts
+# utbot-rd/build.gradle
+rdVersion=2022.3.4
intellijPluginVersion=1.7.0
jacocoVersion=0.8.8
commonsLangVersion=3.11
diff --git a/utbot-analytics/src/main/kotlin/org/utbot/visual/AbstractHtmlReport.kt b/utbot-analytics/src/main/kotlin/org/utbot/visual/AbstractHtmlReport.kt
index 9f1673a57e..ce7ff03e6f 100644
--- a/utbot-analytics/src/main/kotlin/org/utbot/visual/AbstractHtmlReport.kt
+++ b/utbot-analytics/src/main/kotlin/org/utbot/visual/AbstractHtmlReport.kt
@@ -1,5 +1,6 @@
package org.utbot.visual
+import org.utbot.common.dateTimeFormatter
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@@ -7,8 +8,6 @@ import java.time.format.DateTimeFormatter
abstract class AbstractHtmlReport(bodyWidth: Int = 600) {
val builder = HtmlBuilder(bodyMaxWidth = bodyWidth)
- private val dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy_HH-mm-ss")
-
private fun nameWithDate() =
"logs/Report_" + dateTimeFormatter.format(LocalDateTime.now()) + ".html"
diff --git a/utbot-core/src/main/kotlin/org/utbot/common/Logging.kt b/utbot-core/src/main/kotlin/org/utbot/common/Logging.kt
index 381d7328b9..99d1b7a7a2 100644
--- a/utbot-core/src/main/kotlin/org/utbot/common/Logging.kt
+++ b/utbot-core/src/main/kotlin/org/utbot/common/Logging.kt
@@ -3,7 +3,8 @@ package org.utbot.common
import mu.KLogger
import java.time.format.DateTimeFormatter
-val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS")
+val timeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS")
+val dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy_HH-mm-ss")
class LoggerWithLogMethod(val logger: KLogger, val logMethod: (() -> Any?) -> Unit)
@@ -11,18 +12,12 @@ fun KLogger.info(): LoggerWithLogMethod = LoggerWithLogMethod(this, this::info)
fun KLogger.debug(): LoggerWithLogMethod = LoggerWithLogMethod(this, this::debug)
fun KLogger.trace(): LoggerWithLogMethod = LoggerWithLogMethod(this, this::trace)
-
-/**
- *
- */
fun elapsedSecFrom(startNano: Long): String {
val elapsedNano = System.nanoTime() - startNano
val elapsedS = elapsedNano.toDouble() / 1_000_000_000
return String.format("%.3f", elapsedS) + " sec"
}
-
-
/**
* Structured logging.
*
diff --git a/utbot-core/src/main/kotlin/org/utbot/common/PathUtil.kt b/utbot-core/src/main/kotlin/org/utbot/common/PathUtil.kt
index 762eff83e7..b74cb39a56 100644
--- a/utbot-core/src/main/kotlin/org/utbot/common/PathUtil.kt
+++ b/utbot-core/src/main/kotlin/org/utbot/common/PathUtil.kt
@@ -10,6 +10,12 @@ import java.util.*
object PathUtil {
+ fun String.toPathOrNull(): Path? = try {
+ Paths.get(this)
+ } catch (e: Throwable) {
+ null
+ }
+
/**
* Creates a Path from the String.
*/
diff --git a/utbot-framework-api/build.gradle.kts b/utbot-framework-api/build.gradle.kts
index 6874294048..47e85e3bc6 100644
--- a/utbot-framework-api/build.gradle.kts
+++ b/utbot-framework-api/build.gradle.kts
@@ -4,6 +4,7 @@ val junit4Version: String by rootProject
val sootVersion: String by rootProject
val commonsLangVersion: String by rootProject
val kotlinLoggingVersion: String? by rootProject
+val rdVersion: String? by rootProject
plugins {
id("com.github.johnrengelman.shadow") version "7.1.2"
@@ -13,8 +14,8 @@ dependencies {
api(project(":utbot-core"))
api(project(":utbot-api"))
api(project(":utbot-rd"))
- implementation(group ="com.jetbrains.rd", name = "rd-framework", version = "2022.3.1")
- implementation(group ="com.jetbrains.rd", name = "rd-core", version = "2022.3.1")
+ implementation(group ="com.jetbrains.rd", name = "rd-framework", version = rdVersion)
+ implementation(group ="com.jetbrains.rd", name = "rd-core", version = rdVersion)
implementation("org.unittestbot.soot:soot-utbot-fork:${sootVersion}") {
exclude(group="com.google.guava", module="guava")
}
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..5babe937ca 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
@@ -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_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS = 1000L
object UtSettings : AbstractSettings(
logger, defaultKeyForSettingsPath, defaultSettingsPath
@@ -260,51 +260,74 @@ 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_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
)
+// region engine process debug
+
/**
- * Log level for engine process, which started in idea on generate tests action.
+ * 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 engineProcessLogLevel by getEnumProperty(LogLevel.Info)
+ var engineProcessLogConfigFile by getStringProperty("")
/**
- * Log level for concrete executor process.
+ * The property is useful only for the IntelliJ IDEs.
+ * If the property is set in true the engine process opens a debug port.
+ * @see runInstrumentedProcessWithDebug
+ * @see org.utbot.intellij.plugin.process.EngineProcess
*/
- var childProcessLogLevel by getEnumProperty(LogLevel.Info)
+ var runEngineProcessWithDebug by getBooleanProperty(false)
/**
- * 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).
+ * The engine process JDWP agent's port of the instrumented process.
+ * A debugger attaches to the port in order to debug the process.
*/
- var logConcreteExecutionErrors by getBooleanProperty(false)
+ var engineProcessDebugPort by getIntProperty(5005)
+ /**
+ * Value of the suspend mode for the JDWP agent of the engine process.
+ * If the value is true, the engine process will suspend until a debugger attaches to it.
+ */
+ var suspendEngineProcessExecutionInDebugMode by getBooleanProperty(true)
+
+// endregion
+// region instrumented process debug
/**
- * 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
+ * The instrumented process JDWP agent's port of the instrumented process.
+ * A debugger attaches to the port in order to debug the process.
*/
- var runIdeaProcessWithDebug by getBooleanProperty(false)
+ var instrumentedProcessDebugPort by getIntProperty(5006)
/**
- * If true, runs the child process with the ability to attach a debugger.
+ * Value of the suspend mode for the JDWP agent of the instrumented process.
+ * If the value is true, the instrumented process will suspend until a debugger attaches to it.
+ */
+ var suspendInstrumentedProcessExecutionInDebugMode 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 runInstrumentedProcessWithDebug by getBooleanProperty(false)
+
+ /**
+ * Log level for instrumented process.
*/
- var runChildProcessWithDebug by getBooleanProperty(false)
+ var instrumentedProcessLogLevel by getEnumProperty(LogLevel.Info)
+// endregion
/**
* Number of branch instructions using for clustering executions in the test minimization phase.
@@ -398,7 +421,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.
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt
index fd58b9795f..20748404fa 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt
@@ -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) :
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("----------------------------------------")
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/JdkInfoService.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/JdkInfoService.kt
index fd4d27bd9b..62ed3560c2 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/JdkInfoService.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/JdkInfoService.kt
@@ -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.
*/
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/WorkingDirService.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/WorkingDirService.kt
index a714fa64b4..d7ce174bdd 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/WorkingDirService.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/WorkingDirService.kt
@@ -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.
*/
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/process/OpenModulesContainer.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/process/OpenModulesContainer.kt
index 650e7d40c4..a868f42df9 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/process/OpenModulesContainer.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/process/OpenModulesContainer.kt
@@ -6,8 +6,7 @@ object OpenModulesContainer {
private val modulesContainer: List
val javaVersionSpecificArguments: List
get() = modulesContainer
- .takeIf { JdkInfoService.provide().version > 8 }
- ?: emptyList()
+ .takeIf { JdkInfoService.provide().version > 8 } ?: emptyList()
init {
modulesContainer = buildList {
diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/strings/StringExamplesTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/strings/StringExamplesTest.kt
index 75f58922ce..53c540dbe8 100644
--- a/utbot-framework-test/src/test/kotlin/org/utbot/examples/strings/StringExamplesTest.kt
+++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/strings/StringExamplesTest.kt
@@ -382,7 +382,7 @@ internal class StringExamplesTest : UtValueTestCaseChecker(
{ _, i, r -> i <= 0 && r.isException() },
{ 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
)
}
diff --git a/utbot-framework-test/src/test/resources/log4j2.xml b/utbot-framework-test/src/test/resources/log4j2.xml
index 11a2d0701c..ac3d2f2abf 100644
--- a/utbot-framework-test/src/test/resources/log4j2.xml
+++ b/utbot-framework-test/src/test/resources/log4j2.xml
@@ -7,12 +7,12 @@
filePattern="logs/framework-%d{MM-dd-yyyy}.log.gz"
ignoreExceptions="false">
-
+
-
+
diff --git a/utbot-framework/build.gradle b/utbot-framework/build.gradle
index 1ffb748050..a46be75524 100644
--- a/utbot-framework/build.gradle
+++ b/utbot-framework/build.gradle
@@ -16,8 +16,8 @@ dependencies {
api project(':utbot-framework-api')
api project(':utbot-rd')
- implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: '2022.3.1'
- implementation group: 'com.jetbrains.rd', name: 'rd-core', version: '2022.3.1'
+ implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: rdVersion
+ implementation group: 'com.jetbrains.rd', name: 'rd-core', version: rdVersion
implementation("org.unittestbot.soot:soot-utbot-fork:${sootVersion}") {
exclude group:'com.google.guava', module:'guava'
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt
index b4ea2a84a2..c5519721a9 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt
@@ -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) {
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt
index bfc721c52c..929b647e38 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt
@@ -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_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
@@ -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_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
const val MIN_TIMEOUT_MS = 100L
const val MAX_TIMEOUT_MS = 1_000_000L
}
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt
index e8da79b550..75a210f776 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt
@@ -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,
- val timeout: Long = UtSettings.concreteExecutionTimeoutInChildProcess
+ val timeout: Long = UtSettings.concreteExecutionTimeoutInInstrumentedProcess
)
class UtConcreteExecutionResult(
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/minimization/Minimization.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/minimization/Minimization.kt
index 546e0624f2..d3b2c19918 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/minimization/Minimization.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/minimization/Minimization.kt
@@ -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.
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt
index ec51997b6b..7ed73a6c51 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt
@@ -204,7 +204,7 @@ open class TestCaseGenerator(
method2controller.values.forEach { it.paused = true }
controller.paused = false
- logger.info { "|> Resuming method $method" }
+ logger.info { "Resuming method $method" }
val startTime = System.currentTimeMillis()
while (controller.job!!.isActive &&
(System.currentTimeMillis() - startTime) < executionTimeEstimator.timeslotForOneToplevelMethodTraversalInMillis
@@ -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 ->
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyUtils.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyUtils.kt
index c3c3701c21..4075602138 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyUtils.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyUtils.kt
@@ -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()) {
diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineMain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt
similarity index 90%
rename from utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineMain.kt
rename to utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt
index 4b45922d60..fb252c3915 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineMain.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt
@@ -32,9 +32,11 @@ import org.utbot.framework.process.generated.*
import org.utbot.framework.util.ConflictTriggers
import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
import org.utbot.instrumentation.util.KryoHelper
-import org.utbot.rd.CallsSynchronizer
+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
@@ -56,11 +58,7 @@ suspend fun main(args: Array) = runBlocking {
Logger.set(Lifetime.Eternal, UtRdKLoggerFactory(logger))
ClientProtocolBuilder().withProtocolTimeout(messageFromMainTimeoutMillis).start(port) {
- settingsModel
- rdSourceFindingStrategy
- rdInstrumenterAdapter
-
- AbstractSettings.setupFactory(RdSettingsContainerFactory(protocol))
+ AbstractSettings.setupFactory(RdSettingsContainerFactory(protocol.settingsModel))
val kryoHelper = KryoHelper(lifetime)
engineProcessModel.setup(kryoHelper, it, protocol)
}
@@ -74,18 +72,16 @@ private val testSets: MutableMap> = mutableMapOf()
private val testGenerationReports: MutableList = mutableListOf()
private var idCounter: Long = 0
-private fun EngineProcessModel.setup(
- kryoHelper: KryoHelper, synchronizer: CallsSynchronizer, realProtocol: IProtocol
-) {
+private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatchdog, realProtocol: IProtocol) {
val model = this
- synchronizer.measureExecutionForTermination(setupUtContext) { params ->
+ watchdog.wrapActiveCall(setupUtContext) { params ->
UtContext.setUtContext(UtContext(URLClassLoader(params.classpathForUrlsClassloader.map {
File(it).toURI().toURL()
}.toTypedArray())))
}
- synchronizer.measureExecutionForTermination(createTestGenerator) { params ->
+ watchdog.wrapActiveCall(createTestGenerator) { params ->
AnalyticsConfigureUtil.configureML()
- Instrumenter.adapter = RdInstrumenter(realProtocol)
+ Instrumenter.adapter = RdInstrumenter(realProtocol.rdInstrumenterAdapter)
testGenerator = TestCaseGenerator(buildDirs = params.buildDir.map { Paths.get(it) },
classpath = params.classpath,
dependencyPaths = params.dependencyPaths,
@@ -96,7 +92,7 @@ private fun EngineProcessModel.setup(
}
})
}
- synchronizer.measureExecutionForTermination(generate) { params ->
+ watchdog.wrapActiveCall(generate) { params ->
val mockFrameworkInstalled = params.mockInstalled
val conflictTriggers = ConflictTriggers(kryoHelper.readObject(params.conflictTriggers))
if (!mockFrameworkInstalled) {
@@ -126,7 +122,7 @@ private fun EngineProcessModel.setup(
testSets[id] = result
GenerateResult(result.size, id)
}
- synchronizer.measureExecutionForTermination(render) { params ->
+ watchdog.wrapActiveCall(render) { params ->
val testFramework = testFrameworkByName(params.testFramework)
val staticMocking = if (params.staticsMocking.startsWith("No")) {
NoStaticMocking
@@ -157,11 +153,11 @@ private fun EngineProcessModel.setup(
RenderResult(it.generatedCode, it.utilClassKind?.javaClass?.simpleName)
}
}
- synchronizer.measureExecutionForTermination(stopProcess) { synchronizer.stopProtocol() }
- synchronizer.measureExecutionForTermination(obtainClassId) { canonicalName ->
+ watchdog.wrapActiveCall(stopProcess) { watchdog.stopProtocol() }
+ watchdog.wrapActiveCall(obtainClassId) { canonicalName ->
kryoHelper.writeObject(UtContext.currentContext()!!.classLoader.loadClass(canonicalName).id)
}
- synchronizer.measureExecutionForTermination(findMethodsInClassMatchingSelected) { params ->
+ watchdog.wrapActiveCall(findMethodsInClassMatchingSelected) { params ->
val classId = kryoHelper.readObject(params.classId)
val selectedSignatures = params.signatures.map { Signature(it.name, it.parametersTypes) }
FindMethodsInClassMatchingSelectedResult(kryoHelper.writeObject(classId.jClass.allNestedClasses.flatMap { clazz ->
@@ -170,7 +166,7 @@ private fun EngineProcessModel.setup(
.map { it.executableId }
}))
}
- synchronizer.measureExecutionForTermination(findMethodParamNames) { params ->
+ watchdog.wrapActiveCall(findMethodParamNames) { params ->
val classId = kryoHelper.readObject(params.classId)
val bySignature = kryoHelper.readObject