From 7cff872de65fd69d52d06b680f314eb72aaa80d7 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 30 Dec 2025 09:52:29 +0100 Subject: [PATCH 01/14] refactor: merge the autotest agent with the application agent EPMDJ-11179 --- java-agent/build.gradle.kts | 2 + .../configuration/ParameterDefinitions.kt | 36 ++ .../cucumber/Cucumber4Transformer.kt | 20 + .../cucumber/Cucumber5Transformer.kt | 20 + .../cucumber/Cucumber6Transformer.kt | 20 + .../instrument/jmeter/JMeterTransformer.kt | 20 + .../junit/JUnit4PrioritizingTransformer.kt | 20 + .../instrument/junit/JUnit4Transformer.kt | 20 + .../instrument/junit/JUnit5Transformer.kt | 20 + .../JUnitPlatformPrioritizingTransformer.kt | 20 + .../selenium/SeleniumTransformer.kt | 20 + .../testng/TestNG6PrioritizingTransformer.kt | 20 + .../instrument/testng/TestNG6Transformer.kt | 20 + .../testng/TestNG7PrioritizingTransformer.kt | 20 + .../instrument/testng/TestNG7Transformer.kt | 20 + .../agent/test/session/SessionController.kt | 20 + .../kotlin/com/epam/drill/agent/Agent.kt | 29 ++ .../epam/drill/agent/test/GlobalConstants.kt | 34 ++ .../agent/test/devtools/AddSessionData.kt | 22 ++ .../ChromeDevToolTestExecutionListener.kt | 41 ++ .../test/devtools/DevToolsMessageSender.kt | 93 +++++ .../agent/test/devtools/JsCoverageSender.kt | 65 ++++ .../drill/agent/test/devtools/SessionData.kt | 25 ++ .../agent/test/execution/TestController.kt | 115 ++++++ .../agent/test/execution/TestExecutionInfo.kt | 24 ++ .../test/execution/TestExecutionListener.kt | 22 ++ .../test/execution/TestExecutionRecorder.kt | 36 ++ .../agent/test/execution/TestMethodInfo.kt | 45 +++ .../drill/agent/test/execution/TestResult.kt | 25 ++ .../execution/ThreadTestExecutionRecorder.kt | 135 +++++++ .../AbstractTestTransformerObject.kt | 51 +++ .../instrument/RuntimeClassPathProvider.kt | 26 ++ .../instrument/TestSessionHeadersProcessor.kt | 44 +++ .../cucumber/AbstractCucumber56Transformer.kt | 68 ++++ .../cucumber/AbstractCucumberTransformer.kt | 140 +++++++ .../cucumber/Cucumber4Transformer.kt | 66 ++++ .../cucumber/Cucumber5Transformer.kt | 37 ++ .../cucumber/Cucumber6Transformer.kt | 37 ++ .../instrument/jmeter/JMeterTransformer.kt | 54 +++ .../junit/AbstractJUnitTransformer.kt | 23 ++ .../junit/JUnit4PrioritizingTransformer.kt | 95 +++++ .../instrument/junit/JUnit4Transformer.kt | 162 ++++++++ .../instrument/junit/JUnit5Transformer.kt | 152 ++++++++ .../test/instrument/junit/JUnitClassNames.kt | 43 +++ .../JUnitPlatformPrioritizingTransformer.kt | 201 ++++++++++ .../test/instrument/selenium/ChromeDevTool.kt | 354 ++++++++++++++++++ .../instrument/selenium/DevToolStorage.kt | 32 ++ .../agent/test/instrument/selenium/Model.kt | 61 +++ .../selenium/SeleniumTransformer.kt | 278 ++++++++++++++ .../selenium/WebDriverThreadStorage.kt | 32 ++ .../testng/AbstractTestNG67Transformer.kt | 202 ++++++++++ .../AbstractTestNGPrioritizingTransformer.kt | 80 ++++ .../testng/AbstractTestNGTransformer.kt | 23 ++ .../testng/TestNG6PrioritizingTransformer.kt | 28 ++ .../instrument/testng/TestNG6Transformer.kt | 42 +++ .../testng/TestNG7PrioritizingTransformer.kt | 28 ++ .../instrument/testng/TestNG7Transformer.kt | 36 ++ .../test/prioritization/RecommendedTests.kt | 59 +++ .../RecommendedTestsReceiver.kt | 125 +++++++ .../agent/test/sending/AddTestsPayload.kt | 26 ++ .../test/sending/TestDefinitionPayload.kt | 28 ++ .../agent/test/sending/TestInfoSender.kt | 75 ++++ .../agent/test/sending/TestLaunchPayload.kt | 28 ++ .../drill/agent/test/serialization/Json.kt | 23 ++ .../test/serialization/PropertyDecoder.kt | 60 +++ .../agent/test/session/SessionController.kt | 118 ++++++ .../agent/test/session/SessionPayload.kt | 36 ++ .../drill/agent/test/session/SessionSender.kt | 37 ++ .../transport/TestAgentMessageReceiver.kt | 32 ++ .../test/transport/TestAgentMessageSender.kt | 69 ++++ .../HttpAgentMessageDestinationMapper.kt | 6 +- .../kotlin/com/epam/drill/agent/Agent.kt | 29 ++ .../AbstractTestTransformerObject.kt | 24 ++ .../cucumber/AbstractCucumberTransformer.kt | 24 ++ .../cucumber/Cucumber4Transformer.kt | 24 ++ .../cucumber/Cucumber5Transformer.kt | 24 ++ .../cucumber/Cucumber6Transformer.kt | 24 ++ .../instrument/jmeter/JMeterTransformer.kt | 29 ++ .../junit/AbstractJUnitTransformer.kt | 24 ++ .../junit/JUnit4PrioritizingTransformer.kt | 28 ++ .../instrument/junit/JUnit4Transformer.kt | 24 ++ .../instrument/junit/JUnit5Transformer.kt | 24 ++ .../JUnitPlatformPrioritizingTransformer.kt | 28 ++ .../selenium/SeleniumTransformer.kt | 29 ++ .../AbstractTestNGPrioritizingTransformer.kt | 27 ++ .../testng/AbstractTestNGTransformer.kt | 28 ++ .../testng/TestNG6PrioritizingTransformer.kt | 20 + .../instrument/testng/TestNG6Transformer.kt | 20 + .../testng/TestNG7PrioritizingTransformer.kt | 20 + .../instrument/testng/TestNG7Transformer.kt | 20 + .../agent/test/session/SessionController.kt | 26 ++ 91 files changed, 4638 insertions(+), 4 deletions(-) create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/GlobalConstants.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/AddSessionData.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/ChromeDevToolTestExecutionListener.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/DevToolsMessageSender.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/JsCoverageSender.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/SessionData.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestController.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionInfo.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionListener.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionRecorder.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestMethodInfo.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestResult.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/RuntimeClassPathProvider.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/TestSessionHeadersProcessor.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumber56Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitClassNames.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/ChromeDevTool.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/DevToolStorage.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/Model.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/WebDriverThreadStorage.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNG67Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTests.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/AddTestsPayload.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestDefinitionPayload.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestInfoSender.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestLaunchPayload.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/Json.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/PropertyDecoder.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionPayload.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionSender.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageReceiver.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageSender.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt diff --git a/java-agent/build.gradle.kts b/java-agent/build.gradle.kts index 79f47be4..9fc34e08 100644 --- a/java-agent/build.gradle.kts +++ b/java-agent/build.gradle.kts @@ -74,6 +74,7 @@ kotlin { languageSettings.optIn("kotlin.ExperimentalStdlibApi") languageSettings.optIn("kotlinx.serialization.ExperimentalSerializationApi") languageSettings.optIn("io.ktor.utils.io.core.ExperimentalIoApi") + languageSettings.optIn("kotlinx.serialization.InternalSerializationApi") } targets.withType()[HostManager.host.presetName].compilations.forEach { it.defaultSourceSet.kotlin.srcDir("src/native${it.compilationName.capitalize()}/kotlin") @@ -115,6 +116,7 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-cli:${kotlinxCliVersion}") + implementation("com.benasher44:uuid:${uuidVersion}") implementation(project(":common")) implementation(project(":agent-transport")) implementation(project(":agent-instrumentation")) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 058faaea..8879b1f7 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -44,4 +44,40 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val USE_PROTOBUF_SERIALIZER = AgentParameterDefinition.forBoolean(name = "useProtobufSerializer", defaultValue = true).register() val USE_GZIP_COMPRESSION = AgentParameterDefinition.forBoolean(name = "useGzipCompression", defaultValue = true).register() + + val TEST_AGENT_ENABLED = AgentParameterDefinition.forBoolean(name = "testAgentEnabled", defaultValue = false).register() + + val WITH_JS_COVERAGE = AgentParameterDefinition.forBoolean(name = "withJsCoverage", defaultValue = false).register() + val PROXY_ADDRESS = AgentParameterDefinition.forString(name = "browserProxyAddress", defaultValue = "").register() + val DEVTOOLS_PROXY_ADDRESS = AgentParameterDefinition.forString( + name = "devToolsProxyAddress", + defaultValue = "http://localhost:9222",//TODO + parser = { it.trim().takeIf(String::isBlank) ?: it.takeIf(URL_SCHEME_REGEX::matches) ?: "http://$it"} + ).register() + val DEVTOOLS_REPLACE_LOCALHOST = AgentParameterDefinition.forString(name = "devtoolsAddressReplaceLocalhost", defaultValue = "").register() + val SESSION_ID = NullableAgentParameterDefinition.forString(name = "sessionId").register() + val LAUNCH_TYPE = AgentParameterDefinition.forString(name = "launchType", defaultValue = "").register() + val FRAMEWORK_PLUGINS = AgentParameterDefinition.forType( + name = "rawFrameworkPlugins", + defaultValue = emptyList(), + parser = { it.split(";") } + ).register() + + private val URL_SCHEME_REGEX = Regex("\\w+://.+") + + val JS_AGENT_BUILD_VERSION = NullableAgentParameterDefinition.forString(name = "jsAgentBuildVersion").register() + val JS_AGENT_ID = NullableAgentParameterDefinition.forString(name = "jsAgentId").register() + + val TEST_TASK_ID = AgentParameterDefinition.forString(name = "testTaskId", defaultValue = "").register() + val RECOMMENDED_TESTS_ENABLED = AgentParameterDefinition.forBoolean(name = "recommendedTestsEnabled", defaultValue = false).register() + val RECOMMENDED_TESTS_COVERAGE_PERIOD_DAYS = AgentParameterDefinition.forInt(name = "recommendedTestsCoveragePeriodDays", defaultValue = 0).register() + val RECOMMENDED_TESTS_TARGET_APP_ID = AgentParameterDefinition.forString(name = "recommendedTestsTargetAppId", defaultValue = "").register() + val RECOMMENDED_TESTS_TARGET_COMMIT_SHA = AgentParameterDefinition.forString(name = "recommendedTestsTargetCommitSha", defaultValue = "").register() + val RECOMMENDED_TESTS_TARGET_BUILD_VERSION = AgentParameterDefinition.forString(name = "recommendedTestsTargetBuildVersion", defaultValue = "").register() + val RECOMMENDED_TESTS_BASELINE_COMMIT_SHA = AgentParameterDefinition.forString(name = "recommendedTestsBaselineCommitSha", defaultValue = "").register() + val RECOMMENDED_TESTS_BASELINE_BUILD_VERSION = AgentParameterDefinition.forString(name = "recommendedTestsBaselineBuildVersion", defaultValue = "").register() + val RECOMMENDED_TESTS_USE_MATERIALIZED_VIEWS = AgentParameterDefinition.forString(name = "recommendedTestsUseMaterializedViews", defaultValue = "").register() + + val TEST_TRACING_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingEnabled", defaultValue = true).register() + val TEST_LAUNCH_METADATA_SENDING_ENABLED = AgentParameterDefinition.forBoolean(name = "testLaunchMetadataSendingEnabled", defaultValue = true).register() } diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt new file mode 100644 index 00000000..5ffa4f42 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +expect object Cucumber4Transformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt new file mode 100644 index 00000000..00327b71 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +expect object Cucumber5Transformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt new file mode 100644 index 00000000..275e6dff --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +expect object Cucumber6Transformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt new file mode 100644 index 00000000..50d7aeec --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.jmeter + +import com.epam.drill.agent.instrument.TransformerObject + +expect object JMeterTransformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt new file mode 100644 index 00000000..fa485db6 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +expect object JUnit4PrioritizingTransformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt new file mode 100644 index 00000000..3f2e3940 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +expect object JUnit4Transformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt new file mode 100644 index 00000000..07b99ef2 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +expect object JUnit5Transformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt new file mode 100644 index 00000000..e1d6aa68 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +expect object JUnitPlatformPrioritizingTransformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt new file mode 100644 index 00000000..9eb4dcf1 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import com.epam.drill.agent.instrument.TransformerObject + +expect object SeleniumTransformer : TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt new file mode 100644 index 00000000..5112b468 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +expect object TestNG6PrioritizingTransformer: TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt new file mode 100644 index 00000000..109223d7 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +expect object TestNG6Transformer: TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt new file mode 100644 index 00000000..074a58b2 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +expect object TestNG7PrioritizingTransformer: TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt new file mode 100644 index 00000000..c18b6af1 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +expect object TestNG7Transformer: TransformerObject \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt new file mode 100644 index 00000000..bb6309f9 --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.session + +expect object SessionController { + fun startSession() +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt index 597cef82..555698f5 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt @@ -51,6 +51,20 @@ import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer import com.epam.drill.agent.logging.LoggingConfiguration import com.epam.drill.agent.module.JvmModuleLoader +import com.epam.drill.agent.test.instrument.cucumber.Cucumber4Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber5Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber6Transformer +import com.epam.drill.agent.test.instrument.jmeter.JMeterTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4PrioritizingTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4Transformer +import com.epam.drill.agent.test.instrument.junit.JUnit5Transformer +import com.epam.drill.agent.test.instrument.junit.JUnitPlatformPrioritizingTransformer +import com.epam.drill.agent.test.instrument.selenium.SeleniumTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6Transformer +import com.epam.drill.agent.test.instrument.testng.TestNG7PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG7Transformer +import com.epam.drill.agent.test.session.SessionController import com.epam.drill.agent.test2code.Test2Code import com.epam.drill.agent.test2code.configuration.Test2CodeParameterDefinitions import com.epam.drill.agent.transport.JvmModuleMessageSender @@ -103,6 +117,19 @@ private val transformers = setOf( UndertowWsServerTransformer, UndertowWsMessagesTransformer, CompatibilityTestsTransformer, + JUnit4Transformer, + JUnit5Transformer, + TestNG6Transformer, + TestNG7Transformer, + Cucumber4Transformer, + Cucumber5Transformer, + Cucumber6Transformer, + SeleniumTransformer, + JMeterTransformer, + JUnit4PrioritizingTransformer, + JUnitPlatformPrioritizingTransformer, + TestNG6PrioritizingTransformer, + TestNG7PrioritizingTransformer, ) fun premain(agentArgs: String?, inst: Instrumentation) { @@ -116,6 +143,8 @@ fun premain(agentArgs: String?, inst: Instrumentation) { inst.addTransformer(DrillClassFileTransformer, true) JvmModuleMessageSender.sendAgentMetadata() JvmModuleLoader.loadJvmModule(Test2Code::class.java.name).load() + + SessionController.startSession() } catch (e: Throwable) { println("Drill4J Initialization Error:\n${e.message ?: e::class.java.name}") } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/GlobalConstants.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/GlobalConstants.kt new file mode 100644 index 00000000..b2c468f9 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/GlobalConstants.kt @@ -0,0 +1,34 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test + +import com.epam.drill.agent.test.instrument.selenium.* +import com.epam.drill.agent.test.session.SessionController +import com.epam.drill.agent.test.execution.TestController +import kotlin.jvm.java + +const val TEST_ID_HEADER = "drill-test-id" +const val SESSION_ID_HEADER = "drill-session-id" + +val TEST_NAME_VALUE_CALC_LINE = "((String)${TestController::class.qualifiedName}.INSTANCE.${TestController::getTestLaunchId.name}())" +val TEST_NAME_CALC_LINE = "\"$TEST_ID_HEADER\", $TEST_NAME_VALUE_CALC_LINE" +val SESSION_ID_VALUE_CALC_LINE = "${SessionController::class.qualifiedName}.INSTANCE.${SessionController::getSessionId.name}()" +val SESSION_ID_CALC_LINE = "\"$SESSION_ID_HEADER\", $SESSION_ID_VALUE_CALC_LINE" +val IF_CONDITION = "$TEST_NAME_VALUE_CALC_LINE != null && $SESSION_ID_VALUE_CALC_LINE != null" +val DEV_TOOL = "((${ChromeDevTool::class.java.name})${DevToolStorage::class.java.name}.INSTANCE.${DevToolStorage::get.name}())" +val IS_DEV_TOOL_NOT_NULL = "$DEV_TOOL != null" +val IS_HEADER_ADDED = "($DEV_TOOL != null && $DEV_TOOL.${ChromeDevTool::isHeadersAdded.name}())" +val ARE_DRILL_HEADERS_PRESENT = "$TEST_NAME_VALUE_CALC_LINE != null && $SESSION_ID_VALUE_CALC_LINE != null" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/AddSessionData.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/AddSessionData.kt new file mode 100644 index 00000000..c99ff883 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/AddSessionData.kt @@ -0,0 +1,22 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.devtools + +import com.epam.drill.agent.common.transport.AgentMessage +import kotlinx.serialization.Serializable + +@Serializable +data class AddSessionData(val sessionId: String, val data: String): AgentMessage() \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/ChromeDevToolTestExecutionListener.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/ChromeDevToolTestExecutionListener.kt new file mode 100644 index 00000000..99786650 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/ChromeDevToolTestExecutionListener.kt @@ -0,0 +1,41 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.devtools + +import com.epam.drill.agent.test.instrument.selenium.DevToolStorage +import com.epam.drill.agent.test.instrument.selenium.WebDriverThreadStorage +import com.epam.drill.agent.test.execution.TestExecutionListener +import com.epam.drill.agent.test.execution.TestMethodInfo +import com.epam.drill.agent.test.execution.TestResult + +class ChromeDevToolTestExecutionListener( + private val jsCoverageSender: JsCoverageSender +): TestExecutionListener { + + override fun onTestStarted(testLaunchId: String, test: TestMethodInfo) { + DevToolStorage.get()?.startIntercept() + WebDriverThreadStorage.addCookies() + } + + override fun onTestFinished(testLaunchId: String, test: TestMethodInfo, result: TestResult) { + DevToolStorage.get()?.stopIntercept() + jsCoverageSender.sendJsCoverage(testLaunchId) + } + + override fun onTestIgnored(testLaunchId: String, test: TestMethodInfo) { + DevToolStorage.get()?.stopIntercept() + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/DevToolsMessageSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/DevToolsMessageSender.kt new file mode 100644 index 00000000..00bc632e --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/DevToolsMessageSender.kt @@ -0,0 +1,93 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.devtools + +import mu.KotlinLogging +import com.epam.drill.agent.transport.JsonAgentMessageSerializer +import com.epam.drill.agent.transport.http.HttpAgentMessageTransport +import com.epam.drill.agent.common.transport.AgentMessage +import com.epam.drill.agent.common.transport.AgentMessageDestination +import com.epam.drill.agent.common.transport.ResponseStatus +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.instrument.selenium.DevToolsMessage +import com.epam.drill.agent.transport.JsonAgentMessageDeserializer +import kotlin.reflect.KClass + +object DevToolsMessageSender { + + private val messageTransport = HttpAgentMessageTransport( + serverAddress = Configuration.parameters[ParameterDefinitions.DEVTOOLS_PROXY_ADDRESS], + drillInternal = false, + gzipCompression = false, + ) + private val messageSerializer = JsonAgentMessageSerializer() + private val messageDeserializer = JsonAgentMessageDeserializer() + private val logger = KotlinLogging.logger {} + + fun send( + method: String, + path: String, + message: DevToolsMessage + ) = messageTransport.send( + AgentMessageDestination(method, path), + messageSerializer.serialize(message, DevToolsMessage.serializer()), + messageSerializer.contentType() + ) + .mapContent { it.decodeToString() } + .also(DevToolsMessageSender::logResponseContent) + + fun send( + method: String, + path: String, + message: DevToolsMessage, + clazz: KClass + ) = messageTransport.send( + AgentMessageDestination(method, path), + messageSerializer.serialize(message, DevToolsMessage.serializer()), + messageSerializer.contentType() + ) + .mapContent { + messageDeserializer.deserialize(it, clazz) + } + .also(DevToolsMessageSender::logResponseContent) + + fun send( + serverAddress: String, + method: String, + path: String, + message: String + ): ResponseStatus = HttpAgentMessageTransport( + serverAddress = serverAddress, + drillInternal = false, + gzipCompression = false, + ).send( + AgentMessageDestination(method, path), + message.encodeToByteArray(), + messageSerializer.contentType() + ) + .mapContent { it.decodeToString() } + .also(DevToolsMessageSender::logResponseContent) + + private fun logResponseContent(responseContent: ResponseStatus<*>) = logger.trace { + val response = responseContent.content.toString() + .takeIf(String::isNotEmpty) + ?.let { "\n${it.prependIndent("\t")}" } + ?: " " + "send: Response received, success=${responseContent.success}: $response" + } + +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/JsCoverageSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/JsCoverageSender.kt new file mode 100644 index 00000000..eac17689 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/JsCoverageSender.kt @@ -0,0 +1,65 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.devtools + +import com.epam.drill.agent.common.transport.AgentMessageDestination +import com.epam.drill.agent.test.instrument.selenium.* +import com.epam.drill.agent.test.serialization.json +import com.epam.drill.agent.test.session.SessionController +import com.epam.drill.agent.test.transport.TestAgentMessageSender +import mu.KotlinLogging + +interface JsCoverageSender { + fun sendJsCoverage(testLaunchId: String) +} + +class JsCoverageSenderImpl : JsCoverageSender { + private val logger = KotlinLogging.logger {} + + override fun sendJsCoverage(testLaunchId: String) { + DevToolStorage.get()?.run { + val coverage = takePreciseCoverage() + if (coverage.isBlank()) { + logger.trace { "coverage is blank" } + return + } + val scripts = scriptParsed() + if (scripts.isBlank()) { + logger.trace { "script parsed is blank" } + return + } + logger.debug { "ThreadStorage.sendSessionData" } + sendSessionData(SessionData(coverage, scripts, testLaunchId)) + } + } + + private fun sendSessionData(data: SessionData) = runCatching { + val payload = AddSessionData( + sessionId = SessionController.getSessionId(), + data = json.encodeToString(SessionData.serializer(), data) + ) + TestAgentMessageSender.send( + destination = AgentMessageDestination( + "POST", + "raw-javascript-coverage" + ), + message = payload, + serializer = AddSessionData.serializer() + ) + }.onFailure { + logger.warn(it) { "can't send js raw coverage ${SessionController.getSessionId()}" } + }.getOrNull() +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/SessionData.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/SessionData.kt new file mode 100644 index 00000000..078c0740 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/devtools/SessionData.kt @@ -0,0 +1,25 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.devtools + +import kotlinx.serialization.* + +@Serializable +data class SessionData( + val coverage: String, + val scripts: String, + val testId: String, +) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestController.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestController.kt new file mode 100644 index 00000000..794554cb --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestController.kt @@ -0,0 +1,115 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +import com.epam.drill.agent.request.DrillRequestHolder +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.TEST_ID_HEADER +import com.epam.drill.agent.test.devtools.ChromeDevToolTestExecutionListener +import com.epam.drill.agent.test.devtools.JsCoverageSenderImpl + +object TestController : TestExecutionRecorder by testExecutionRecorder(testExecutionListeners()) { + + //TODO EPMDJ-10251 add browser name for ui tests + @JvmOverloads + fun testStarted( + engine: String, + className: String?, + method: String?, + methodParams: String = "()", + testTags: List = emptyList(), + ) { + if (className == null || method == null) + return + + recordTestStarting( + TestMethodInfo( + engine = engine, + className = className, + method = method, + methodParams = methodParams, + tags = testTags + ) + ) + } + + @JvmOverloads + fun testFinished( + engine: String, + className: String?, + method: String?, + status: String, + methodParams: String = "()", + testTags: List = emptyList(), + ) { + if (className == null || method == null) + return + + recordTestFinishing( + TestMethodInfo( + engine = engine, + className = className, + method = method, + methodParams = methodParams, + tags = testTags + ), + status + ) + } + + @JvmOverloads + fun testIgnored( + engine: String, + className: String?, + method: String?, + methodParams: String = "()", + testTags: List = emptyList(), + ) { + if (className == null || method == null) + return + + recordTestIgnoring( + TestMethodInfo( + engine = engine, + className = className, + method = method, + methodParams = methodParams, + tags = testTags + ) + ) + } + + @Deprecated("Use explicit retrieve() instead", ReplaceWith("retrieve()")) + fun getTestLaunchId(): String? = DrillRequestHolder.retrieve()?.headers?.get(TEST_ID_HEADER) +} + +fun testExecutionListeners(): List { + val listeners = arrayListOf() + if (Configuration.parameters[ParameterDefinitions.WITH_JS_COVERAGE]) { + listeners.add( + ChromeDevToolTestExecutionListener( + jsCoverageSender = JsCoverageSenderImpl() + ) + ) + } + return listeners +} + +fun testExecutionRecorder(listeners: List) = ThreadTestExecutionRecorder( + requestHolder = DrillRequestHolder, + listeners = listeners +) \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionInfo.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionInfo.kt new file mode 100644 index 00000000..81260b95 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionInfo.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +class TestExecutionInfo( + val testLaunchId: String, + val testMethod: TestMethodInfo, + var result: TestResult = TestResult.UNKNOWN, + var startedAt: Long? = null, + var finishedAt: Long? = null, +) \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionListener.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionListener.kt new file mode 100644 index 00000000..c5caa637 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionListener.kt @@ -0,0 +1,22 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +interface TestExecutionListener { + fun onTestStarted(testLaunchId: String, test: TestMethodInfo) {} + fun onTestFinished(testLaunchId: String, test: TestMethodInfo, result: TestResult) {} + fun onTestIgnored(testLaunchId: String, test: TestMethodInfo) {} +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionRecorder.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionRecorder.kt new file mode 100644 index 00000000..d6fc9f68 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestExecutionRecorder.kt @@ -0,0 +1,36 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +interface TestExecutionRecorder { + fun recordTestStarting( + testMethod: TestMethodInfo + ) + + fun recordTestFinishing( + testMethod: TestMethodInfo, + status: String + ) + + fun recordTestIgnoring( + testMethod: TestMethodInfo, + isSmartSkip: Boolean = false + ) + + fun getFinishedTests(): List + + fun reset() +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestMethodInfo.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestMethodInfo.kt new file mode 100644 index 00000000..7b2280b2 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestMethodInfo.kt @@ -0,0 +1,45 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +data class TestMethodInfo @JvmOverloads constructor( + val engine: String, + val className: String, + val method: String, + val methodParams: String = "()", + val metadata: Map = emptyMap(), + val tags: List = emptyList(), +) : Comparable { + + val signature: String + get() = "$engine:$className.$method${methodParams}" + + override fun compareTo(other: TestMethodInfo): Int { + return signature.compareTo(other.signature) + } + + override fun equals(other: Any?): Boolean { + return if (other is TestMethodInfo) compareTo(other) == 0 else false + } + + override fun hashCode(): Int { + return signature.hashCode() + } + + override fun toString(): String { + return signature + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestResult.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestResult.kt new file mode 100644 index 00000000..eef459ae --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/TestResult.kt @@ -0,0 +1,25 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +enum class TestResult { + PASSED, + FAILED, + ERROR, + SKIPPED, + SMART_SKIPPED, + UNKNOWN +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt new file mode 100644 index 00000000..5e7dd616 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt @@ -0,0 +1,135 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.execution + +import com.epam.drill.agent.common.request.DrillRequest +import com.epam.drill.agent.common.request.RequestHolder +import com.epam.drill.agent.test.TEST_ID_HEADER +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.session.SessionController +import mu.KotlinLogging +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class ThreadTestExecutionRecorder( + private val requestHolder: RequestHolder, + private val listeners: List = emptyList() +) : TestExecutionRecorder { + private val logger = KotlinLogging.logger {} + private val testExecutionData: ConcurrentHashMap = ConcurrentHashMap() + private val testLaunchHolder: ThreadLocal = ThreadLocal.withInitial { null } + + override fun recordTestStarting( + testMethod: TestMethodInfo + ) { + val testLaunchId = generateTestLaunchId() + testLaunchHolder.set(testLaunchId) + updateTestInfo(testLaunchId, testMethod) { + it.startedAt = System.currentTimeMillis() + } + addDrillHeaders(testLaunchId) + listeners.forEach { it.onTestStarted(testLaunchId, testMethod) } + logger.debug { "Test: $testMethod STARTED" } + } + + override fun recordTestFinishing( + testMethod: TestMethodInfo, + status: String + ) { + val testLaunchId = testLaunchHolder.get() + if (testLaunchId == null) { + logger.warn { "Test ${testMethod.className}::${testMethod.method} finished with result $status but no test launch id was found." } + return + } + testLaunchHolder.remove() + val testResult = mapToTestResult(status) + updateTestInfo(testLaunchId, testMethod) { + it.finishedAt = System.currentTimeMillis() + it.result = testResult + } + clearDrillHeaders() + listeners.forEach { it.onTestFinished(testLaunchId, testMethod, testResult) } + println("Test: $testMethod FINISHED") + logger.debug { "Test: $testMethod FINISHED. Result: $status" } + } + + override fun recordTestIgnoring( + testMethod: TestMethodInfo, + isSmartSkip: Boolean + ) { + val testLaunchId = testLaunchHolder.get() ?: generateTestLaunchId() + testLaunchHolder.remove() + val skipResult = if (isSmartSkip) TestResult.SMART_SKIPPED else TestResult.SKIPPED + updateTestInfo(testLaunchId, testMethod) { + it.startedAt = null + it.finishedAt = null + it.result = skipResult + } + clearDrillHeaders() + listeners.forEach { it.onTestIgnored(testLaunchId, testMethod) } + logger.debug { "Test: $testMethod FINISHED. Result: $skipResult" } + } + + override fun reset() { + testExecutionData.clear() + } + + override fun getFinishedTests(): List = testExecutionData + .filterValues { test -> test.result != TestResult.UNKNOWN } + .onEach { + testExecutionData.remove(it.key) + }.values.toList() + + private fun updateTestInfo( + testLaunchId: String, + testMethodInfo: TestMethodInfo, + updateTestExecutionInfo: (TestExecutionInfo) -> Unit, + ) { + testExecutionData.compute(testLaunchId) { _, value -> + val testExecutionInfo = value ?: TestExecutionInfo(testLaunchId, testMethodInfo) + if (testExecutionInfo.result == TestResult.UNKNOWN) { + updateTestExecutionInfo(testExecutionInfo) + } else { + logger.warn { "Test ${testMethodInfo.method} already finished with result ${testExecutionInfo.result}" } + } + testExecutionInfo + } + } + + private fun generateTestLaunchId() = UUID.randomUUID().toString() + + private fun addDrillHeaders(testLaunchId: String) { + val drillRequest = if (Configuration.parameters[ParameterDefinitions.TEST_TRACING_ENABLED]) { + DrillRequest( + drillSessionId = SessionController.getSessionId(), + headers = mapOf(TEST_ID_HEADER to (testLaunchId)) + ) + } else { + DrillRequest(drillSessionId = SessionController.getSessionId()) + } + requestHolder.store(drillRequest) + } + + private fun clearDrillHeaders() { + requestHolder.remove() + } + + private fun mapToTestResult(value: String): TestResult { + if (value == "SUCCESSFUL") return TestResult.PASSED + return TestResult.valueOf(value) + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt new file mode 100644 index 00000000..6a3ffbdb --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt @@ -0,0 +1,51 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_AGENT_ENABLED +import com.epam.drill.agent.instrument.AbstractTransformerObject +import com.epam.drill.agent.instrument.ClassPathProvider +import com.epam.drill.agent.instrument.RuntimeClassPathProvider +import javassist.ClassPool +import javassist.CtClass +import java.security.ProtectionDomain + +abstract class AbstractTestTransformerObject : AbstractTransformerObject(Configuration), + ClassPathProvider by RuntimeClassPathProvider { + override fun enabled() = super.enabled() && Configuration.parameters[TEST_AGENT_ENABLED] + + override fun transform(className: String, ctClass: CtClass) { + throw NotImplementedError("AbstractTestTransformerObject.transform is not implemented") + } + + override fun transform( + className: String, + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain? + ) { + instrument(ctClass, pool, classLoader, protectionDomain) + } + + abstract fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/RuntimeClassPathProvider.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/RuntimeClassPathProvider.kt new file mode 100644 index 00000000..85087676 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/RuntimeClassPathProvider.kt @@ -0,0 +1,26 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument + +import com.epam.drill.agent.configuration.DefaultParameterDefinitions.INSTALLATION_DIR +import com.epam.drill.agent.instrument.ClassPathProvider +import com.epam.drill.agent.configuration.Configuration + +object RuntimeClassPathProvider : ClassPathProvider { + + override fun getClassPath() = "${Configuration.parameters[INSTALLATION_DIR]}/drill-runtime.jar" + +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/TestSessionHeadersProcessor.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/TestSessionHeadersProcessor.kt new file mode 100644 index 00000000..de478380 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/TestSessionHeadersProcessor.kt @@ -0,0 +1,44 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument + +import com.epam.drill.agent.request.DrillRequestHolder +import com.epam.drill.agent.instrument.HeadersProcessor +import com.epam.drill.agent.test.SESSION_ID_HEADER +import com.epam.drill.agent.test.TEST_ID_HEADER + +object TestSessionHeadersProcessor : HeadersProcessor { + + override fun removeHeaders() = Unit + + override fun storeHeaders(headers: Map) = Unit + + override fun retrieveHeaders() = mutableMapOf().apply { + DrillRequestHolder.retrieve()?.let { + put(SESSION_ID_HEADER, it.drillSessionId) + putAll(it.headers) + } + } + + override fun hasHeaders() = retrieveHeaders().run { + this.isNotEmpty() && this.get(SESSION_ID_HEADER) != null && this.get(TEST_ID_HEADER) != null + } + + override fun isProcessRequests() = true + + override fun isProcessResponses() = false + +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumber56Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumber56Transformer.kt new file mode 100644 index 00000000..444d79bd --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumber56Transformer.kt @@ -0,0 +1,68 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import javassist.* + +abstract class AbstractCucumber56Transformer() : AbstractCucumberTransformer() { + override val Status = "io.cucumber.plugin.event.Status" + override val EventBus: String = "io.cucumber.core.eventbus.EventBus" + override val EventHandler = """io.cucumber.plugin.event.EventHandler""" + override val PickleStepDefinitionMatch: String = "io.cucumber.core.runner.PickleStepDefinitionMatch" + override val testPackage = "io.cucumber.plugin.event" + abstract val versionPattern: Regex + + /** + * From cucumber 5 TestStep class location doesn't change + */ + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "io/cucumber/core/runner/TestStep" + } + + override fun getFeaturePath(): String = """ + String[] paths = new java.io.File(".").toURI().relativize($1.getUri()).toString().split(":"); + int index = paths.length - 1; + String featurePath = paths[index]; + if (featurePath.startsWith("/")) { + featurePath = featurePath.replaceFirst("/", ""); + } + """.trimIndent() + + override fun getTestStatus(): String = """finishedTest.getResult().getStatus();""".trimIndent() + + override fun CtClass.implEventBusMethods() { + addMethod( + CtMethod.make( + """ + public java.time.Instant getInstant() { + return mainEventBus.getInstant(); + } + """.trimIndent(), + this + ) + ) + addMethod( + CtMethod.make( + """ + public java.util.UUID generateId() { + return mainEventBus.generateId(); + } + """.trimIndent(), + this + ) + ) + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt new file mode 100644 index 00000000..76e960b4 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt @@ -0,0 +1,140 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_CUCUMBER_ENABLED +import com.epam.drill.agent.test.execution.TestController +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject +import javassist.* +import mu.KotlinLogging +import java.security.* + +abstract class AbstractCucumberTransformer() : AbstractTestTransformerObject() { + val engineSegment = "cucumber" + val EventBusProxy = "EventBusProxy" + + override val logger = KotlinLogging.logger {} + abstract val Status: String + abstract val EventBus: String + abstract val EventHandler: String + abstract val Event: String + abstract val PickleStepDefinitionMatch: String + abstract val testPackage: String + + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_CUCUMBER_ENABLED] + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + val cc: CtClass = pool.makeClass(EventBusProxy) + cc.interfaces = arrayOf(pool.get(EventBus)) + cc.addField(CtField.make("$EventBus mainEventBus = null;", cc)) + cc.addField(CtField.make("String featurePath = \"\";", cc)) + cc.addConstructor( + CtNewConstructor.make( + """ + public $EventBusProxy($EventBus mainEventBus, String featurePath) { + this.mainEventBus = mainEventBus; + this.featurePath = featurePath; + } + """.trimMargin(), + cc + ) + ) + cc.implEventBusMethods() + + cc.addMethod( + CtMethod.make( + """ + public void send($Event event) { + mainEventBus.send(event); + if (event instanceof $testPackage.TestStepStarted) { + ${TestController::class.java.name}.INSTANCE.${TestController::testStarted.name}("$engineSegment", featurePath, (($testPackage.TestStepStarted) event).getTestCase().getName()); + } else if (event instanceof $testPackage.TestStepFinished) { + $testPackage.TestStepFinished finishedTest = ($testPackage.TestStepFinished) event; + $Status status = ${getTestStatus()} + if (status != $Status.PASSED) { + status = $Status.FAILED; + } + ${TestController::class.java.name}.INSTANCE.${TestController::testFinished.name}("$engineSegment", featurePath, finishedTest.getTestCase().getName(), status.name()); + } + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void sendAll(Iterable queue) { + mainEventBus.sendAll(queue); + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void removeHandlerFor(Class aClass, $EventHandler eventHandler) { + mainEventBus.removeHandlerFor(aClass, eventHandler); + } + """.trimIndent(), + cc + ) + ) + + cc.addMethod( + CtMethod.make( + """ + public void registerHandlerFor(Class aClass, $EventHandler eventHandler) { + mainEventBus.registerHandlerFor(aClass, eventHandler); + } + """.trimIndent(), + cc + ) + ) + cc.toClass(classLoader, protectionDomain) + + /** + * {@link PickleStepDefinitionMatch} is represent a step of scenario. + * Check for PickleStepDefinitionMatch is needed to determine what we are currently performing, + * a step from a scenario or before or after action. + * Instead of the class name, we use the path to the feature file. + * If the file is in the same repository as the tests, then we take the relative path, + * otherwise we take the absolute path without specifying the disk name + */ + ctClass.getDeclaredMethod("run").insertBefore( + """ + try { + if (stepDefinitionMatch instanceof $PickleStepDefinitionMatch) { + ${getFeaturePath()} + $2 = new $EventBusProxy($2, featurePath); + } + } catch (Throwable ignored) {} + """.trimIndent() + ) + } + + abstract fun getFeaturePath(): String + + abstract fun getTestStatus(): String + + abstract fun CtClass.implEventBusMethods() +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt new file mode 100644 index 00000000..eaac09c4 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -0,0 +1,66 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject +import javassist.* + +actual object Cucumber4Transformer : TransformerObject, AbstractCucumberTransformer() { + override val testPackage = "cucumber.api.event" + override val Status = "cucumber.api.Result.Type" + override val EventBus = "cucumber.runner.EventBus" + override val EventHandler: String = "cucumber.api.event.EventHandler" + override val Event = "cucumber.api.event.Event" + override val PickleStepDefinitionMatch = "cucumber.runner.PickleStepDefinitionMatch" + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == /*4.x.x*/"cucumber/runner/TestStep" + } + + override fun getFeaturePath(): String = """ + String[] paths = new java.io.File(".").toURI().resolve($1.getUri()).toString().split(":"); + int index = paths.length - 1; + String featurePath = paths[index]; + if (featurePath.startsWith("/")) { + featurePath = featurePath.replaceFirst("/", ""); + } + """.trimIndent() + + override fun getTestStatus(): String = """finishedTest.result.getStatus();""".trimIndent() + + override fun CtClass.implEventBusMethods() { + addMethod( + CtMethod.make( + """ + public Long getTime() { + return mainEventBus.getTime(); + } + """.trimIndent(), + this + ) + ) + addMethod( + CtMethod.make( + """ + public Long getTimeMillis() { + return mainEventBus.getTimeMillis(); + } + """.trimIndent(), + this + ) + ) + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt new file mode 100644 index 00000000..4b4c1ccc --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -0,0 +1,37 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject +import java.security.ProtectionDomain +import javassist.ClassPool +import javassist.CtClass + +actual object Cucumber5Transformer : TransformerObject, AbstractCucumber56Transformer() { + override val versionPattern: Regex = "5\\.[0-9]+\\.[0-9]+".toRegex() + override val Event: String = "io.cucumber.plugin.event.Event" + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + if ("${ctClass.url}".contains(versionPattern)) { + super.instrument(ctClass, pool, classLoader, protectionDomain) + } + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt new file mode 100644 index 00000000..2e592bae --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -0,0 +1,37 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject +import java.security.ProtectionDomain +import javassist.ClassPool +import javassist.CtClass + +actual object Cucumber6Transformer : TransformerObject, AbstractCucumber56Transformer() { + override val versionPattern: Regex = "6\\.[0-9]+\\.[0-9]+".toRegex() + override val Event: String = "java.lang.Object" + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + if ("${ctClass.url}".contains(versionPattern)) { + super.instrument(ctClass, pool, classLoader, protectionDomain) + } + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt new file mode 100644 index 00000000..b561d3a3 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -0,0 +1,54 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.jmeter + +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JMETER_ENABLED +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject +import javassist.* +import mu.KotlinLogging +import java.security.* + +actual object JMeterTransformer : TransformerObject, AbstractTestTransformerObject() { + override val logger = KotlinLogging.logger {} + + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_JMETER_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain? + ) { + val setupRequestMethod = ctClass.getMethod( + "setupRequest", + "(Ljava/net/URL;Lorg/apache/http/client/methods/HttpRequestBase;" + + "Lorg/apache/jmeter/protocol/http/sampler/HTTPSampleResult;)V" + ) + //TODO memorizeTestName is not exist + setupRequestMethod.insertBefore( + """ + String drillTestName = $3.getSampleLabel(); + AgentClassTransformer.memorizeTestName(drillTestName); + + """.trimIndent() + ) + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt new file mode 100644 index 00000000..d6bfaac9 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt @@ -0,0 +1,23 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JUNIT_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +abstract class AbstractJUnitTransformer(): AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_JUNIT_ENABLED] +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt new file mode 100644 index 00000000..f052f802 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -0,0 +1,95 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.prioritization.RecommendedTests +import javassist.* +import mu.KotlinLogging +import java.security.ProtectionDomain + +private const val Filter = "org.junit.runner.manipulation.Filter" +private const val Description = "org.junit.runner.Description" + +actual object JUnit4PrioritizingTransformer : TransformerObject, AbstractJUnitTransformer() { + override val logger = KotlinLogging.logger {} + private val engineSegment = "junit" + private val DrillJUnit4Filter = "${this.javaClass.`package`.name}.gen.DrillJUnit4Filter" + + override fun enabled(): Boolean = super.enabled() && agentConfiguration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/runners/JUnit4" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + createRecommendedTestsFilterClass(pool, classLoader, protectionDomain) + instrumentConstructor(ctClass) + } + + private fun instrumentConstructor(ctClass: CtClass) { + ctClass.constructors.forEach { constructor -> + constructor.insertAfter( + """ + $DrillJUnit4Filter drillFilter = new $DrillJUnit4Filter(); + filter(drillFilter); + """.trimIndent() + ) + } + } + + private fun createRecommendedTestsFilterClass( + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ): CtClass { + val cc = pool.makeClass(DrillJUnit4Filter, pool.get(Filter)) + cc.addMethod( + CtMethod.make( + """ + public boolean shouldRun($Description description) { + if (!description.isTest()) return true; + java.lang.String className = description.getClassName(); + if (className == null) return true; + java.lang.String methodName = description.getMethodName(); + if (methodName == null) return true; + boolean shouldSkip = ${RecommendedTests::class.java.name}.INSTANCE.${RecommendedTests::shouldSkip.name}("$engineSegment", className, methodName, null); + return !shouldSkip; + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public java.lang.String describe() { + return "skip tests by Drill4J"; + } + """.trimIndent(), + cc + ) + ) + cc.toClass(classLoader, protectionDomain) + return cc + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt new file mode 100644 index 00000000..b352ac6c --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -0,0 +1,162 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.execution.TestController +import com.epam.drill.agent.test.execution.TestResult +import javassist.ClassPool +import javassist.CtClass +import javassist.CtField +import javassist.CtMethod +import javassist.CtNewConstructor +import mu.KotlinLogging +import java.security.ProtectionDomain + +actual object JUnit4Transformer: + TransformerObject, + AbstractJUnitTransformer() { + override val logger = KotlinLogging.logger {} + const val engineSegment = "junit" + + override fun permit( + className: String, + superName: String?, + interfaces: Array + ): Boolean { + return className == "org/junit/runner/notification/RunNotifier" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain? + ) { + val cc: CtClass = pool.makeClass("MyList") + cc.superclass = pool.get("org.junit.runner.notification.RunListener") + cc.addField(CtField.make("org.junit.runner.notification.RunListener mainRunner = null;", cc)) + cc.addConstructor( + CtNewConstructor.make( + """ + public MyList(org.junit.runner.notification.RunListener mainRunner) { + this.mainRunner = mainRunner; + } + """.trimMargin(), cc + ) + ) + val dp = """description""" + cc.addMethod( + CtMethod.make( + """ + public void testRunStarted(org.junit.runner.Description $dp) throws Exception { + this.mainRunner.testRunStarted($dp); + } + """.trimIndent(), + cc + ) + ) + + cc.addMethod( + CtMethod.make( + """ + public void testStarted(org.junit.runner.Description $dp) throws Exception { + this.mainRunner.testStarted($dp); + ${TestController::class.java.name}.INSTANCE.${TestController::testStarted.name}("$engineSegment", $dp.getClassName(), $dp.getMethodName()); + } + """.trimIndent(), + cc + ) + ) + + + cc.addMethod( + CtMethod.make( + """ + public void testFinished(org.junit.runner.Description $dp) throws Exception { + this.mainRunner.testFinished(description); + ${TestController::class.java.name}.INSTANCE.${TestController::testFinished.name}("$engineSegment", $dp.getClassName(), $dp.getMethodName(), "${TestResult.PASSED.name}"); + } + """.trimIndent(), + cc + ) + ) + + cc.addMethod( + CtMethod.make( + """ + public void testRunFinished(org.junit.runner.Result result) throws Exception { + this.mainRunner.testRunFinished(result); + } + """.trimIndent(), + cc + ) + ) + + + val failureParamName = """failure""" + val desct = """$failureParamName.getDescription()""" + cc.addMethod( + CtMethod.make( + """ + public void testFailure(org.junit.runner.notification.Failure $failureParamName) throws Exception { + this.mainRunner.testFailure($failureParamName); + ${TestController::class.java.name}.INSTANCE.${TestController::testFinished.name}("$engineSegment", $desct.getClassName(), $desct.getMethodName(), "${TestResult.FAILED.name}"); + } + """.trimIndent(), + cc + ) + ) + + + cc.addMethod( + CtMethod.make( + """ + public void testAssumptionFailure(org.junit.runner.notification.Failure $failureParamName) { + this.mainRunner.testAssumptionFailure(failure); + } + """.trimIndent(), + cc + ) + ) + + + + cc.addMethod( + CtMethod.make( + """ + public void testIgnored(org.junit.runner.Description $dp) throws Exception { + this.mainRunner.testIgnored($dp); + ${TestController::class.java.name}.INSTANCE.${TestController::testIgnored.name}("$engineSegment", $dp.getClassName(), $dp.getMethodName()); + } + """.trimIndent(), + cc + ) + ) + + cc.toClass(classLoader, protectionDomain) + ctClass.getDeclaredMethod("addListener").insertBefore( + """ + $1= new MyList($1); + """.trimIndent() + ) + ctClass.getDeclaredMethod("addFirstListener").insertBefore( + """ + $1= new MyList($1); + """.trimIndent() + ) + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt new file mode 100644 index 00000000..b1f83fce --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -0,0 +1,152 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.execution.TestController +import com.epam.drill.agent.test.execution.TestMethodInfo +import javassist.* +import mu.KotlinLogging +import java.security.* + +actual object JUnit5Transformer: TransformerObject, AbstractJUnitTransformer() { + override val logger = KotlinLogging.logger {} + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/platform/engine/support/hierarchical/NodeTestTaskContext" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + val cc: CtClass = pool.makeClass("MyList") + cc.interfaces = arrayOf(pool.get("org.junit.platform.engine.EngineExecutionListener")) + cc.addField(CtField.make("org.junit.platform.engine.EngineExecutionListener mainRunner = null;", cc)) + cc.addConstructor( + CtNewConstructor.make( + """ + public MyList(org.junit.platform.engine.EngineExecutionListener mainRunner) { + this.mainRunner = mainRunner; + } + """.trimMargin(), cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void dynamicTestRegistered(org.junit.platform.engine.TestDescriptor testDescriptor) { + mainRunner.dynamicTestRegistered(testDescriptor); + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void executionSkipped(org.junit.platform.engine.TestDescriptor testDescriptor, String reason) { + mainRunner.executionSkipped(testDescriptor, reason); + if (!testDescriptor.isContainer()) { + ${getMetadata("testDescriptor")} + ${getTags("testDescriptor")} + ${TestMethodInfo::class.java.name} methodInfo = ${this::class.java.name}.INSTANCE.${this::convertToMethodInfo.name}(testMetadata, testTags); + if (methodInfo != null) { + ${TestController::class.java.name}.INSTANCE.${TestController::recordTestIgnoring.name}(methodInfo, false); + } + } + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void executionStarted(org.junit.platform.engine.TestDescriptor testDescriptor) { + mainRunner.executionStarted(testDescriptor); + if (!testDescriptor.isContainer()) { + ${getMetadata("testDescriptor")} + ${getTags("testDescriptor")} + ${TestMethodInfo::class.java.name} methodInfo = ${this::class.java.name}.INSTANCE.${this::convertToMethodInfo.name}(testMetadata, testTags); + if (methodInfo != null) { + ${TestController::class.java.name}.INSTANCE.${TestController::recordTestStarting.name}(methodInfo); + } + } + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void executionFinished(org.junit.platform.engine.TestDescriptor testDescriptor, org.junit.platform.engine.TestExecutionResult testExecutionResult) { + mainRunner.executionFinished(testDescriptor, testExecutionResult); + if (!testDescriptor.isContainer()) { + ${getMetadata("testDescriptor")} + ${getTags("testDescriptor")} + ${TestMethodInfo::class.java.name} methodInfo = ${this::class.java.name}.INSTANCE.${this::convertToMethodInfo.name}(testMetadata, testTags); + if (methodInfo != null) { + ${TestController::class.java.name}.INSTANCE.${TestController::recordTestFinishing.name}(methodInfo, testExecutionResult.getStatus().name()); + } + } + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public void reportingEntryPublished(org.junit.platform.engine.TestDescriptor testDescriptor, org.junit.platform.engine.reporting.ReportEntry entry) { + mainRunner.reportingEntryPublished(testDescriptor, entry); + } + """.trimIndent(), + cc + ) + ) + cc.toClass(classLoader, protectionDomain) + + ctClass.constructors.first().insertBefore( + """ + $1 = new MyList($1); + """.trimIndent() + ) + } + + @Suppress("MemberVisibilityCanBePrivate") + fun convertToMethodInfo( + testMetadata: Map, + testTags: List + ): TestMethodInfo? { + return TestMethodInfo( + engine = testMetadata["engine"] ?: "junit", + className = testMetadata["class"] ?: return null, + method = testMetadata["method"]?.substringBefore("(") ?: return null, + methodParams = testMetadata["method"]?.getMethodParams() ?: "()", + metadata = testMetadata, + tags = testTags + ) + } + + private fun String.getMethodParams(): String { + val params = this.substringAfter("(").substringBefore(")") + return if (params.isEmpty()) "()" else "($params)" + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitClassNames.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitClassNames.kt new file mode 100644 index 00000000..983d3ce4 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitClassNames.kt @@ -0,0 +1,43 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +const val PostDiscoveryFilter = "org.junit.platform.launcher.PostDiscoveryFilter" +const val FilterResult = "org.junit.platform.engine.FilterResult" +const val TestDescriptor = "org.junit.platform.engine.TestDescriptor" +const val Segment = "org.junit.platform.engine.UniqueId.Segment" +const val LauncherDiscoveryRequest = "org.junit.platform.launcher.LauncherDiscoveryRequest" +const val ConfigurationParameters = "org.junit.platform.engine.ConfigurationParameters" +const val TestTag = "org.junit.platform.engine.TestTag" + +fun getMetadata(descriptor: String) = """ + java.util.Map testMetadata = new java.util.HashMap(); + for (int i = 0; i < $descriptor.getUniqueId().getSegments().size(); i++) { + java.lang.String key = (($Segment)$descriptor.getUniqueId().getSegments().get(i)).getType(); + java.lang.String value = (($Segment)$descriptor.getUniqueId().getSegments().get(i)).getValue(); + testMetadata.put(key, value); + } + """.trimIndent() + +fun getTags(descriptor: String) = """ + java.util.List testTags = new java.util.ArrayList(); + java.util.Set tags = $descriptor.getTags(); + java.util.Iterator iterator = tags.iterator(); + while (iterator.hasNext()) { + $TestTag tag = ($TestTag) iterator.next(); + testTags.add(tag.getName()); + } + """.trimIndent() \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt new file mode 100644 index 00000000..aee43dee --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -0,0 +1,201 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.execution.TestMethodInfo +import com.epam.drill.agent.test.prioritization.RecommendedTests +import javassist.* +import mu.KotlinLogging +import java.security.ProtectionDomain + +actual object JUnitPlatformPrioritizingTransformer : TransformerObject, AbstractJUnitTransformer() { + + override val logger = KotlinLogging.logger {} + private val DrillJUnit5Filter = "${this.javaClass.`package`.name}.gen.DrillJUnit5Filter" + private val LauncherDiscoveryRequestAdapter = "${this.javaClass.`package`.name}.gen.LauncherDiscoveryRequestAdapter" + + override fun enabled(): Boolean = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/platform/launcher/core/DefaultLauncher" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + createRecommendedTestsFilterClass(pool, classLoader, protectionDomain) + createLauncherDiscoveryRequestAdapterClass(pool, classLoader, protectionDomain) + instrumentDiscoverMethod(ctClass) + instrumentExecuteMethod(ctClass) + } + + private fun instrumentDiscoverMethod(ctClass: CtClass) { + ctClass.getMethod( + "discover", + "(Lorg/junit/platform/launcher/LauncherDiscoveryRequest;)Lorg/junit/platform/launcher/TestPlan;" + ).insertBefore( + """ + $1 = new $LauncherDiscoveryRequestAdapter($1, new $DrillJUnit5Filter()); + """.trimIndent() + ) + } + + private fun instrumentExecuteMethod(ctClass: CtClass) { + ctClass.getMethod( + "execute", + "(Lorg/junit/platform/launcher/LauncherDiscoveryRequest;[Lorg/junit/platform/launcher/TestExecutionListener;)V") + .insertBefore( + """ + $1 = new $LauncherDiscoveryRequestAdapter($1, new $DrillJUnit5Filter()); + """.trimIndent() + ) + } + + private fun createRecommendedTestsFilterClass( + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ): CtClass { + val cc: CtClass = pool.makeClass(DrillJUnit5Filter) + cc.interfaces = arrayOf(pool.get(PostDiscoveryFilter)) + cc.addMethod( + CtMethod.make( + """ + public $FilterResult apply(java.lang.Object object) { + $TestDescriptor descriptor = ($TestDescriptor)object; + if (descriptor.isContainer()) + return $FilterResult.included(""); + + ${getMetadata("descriptor")} + ${getTags("descriptor")} + + ${TestMethodInfo::class.java.name} methodInfo = ${this::class.java.name}.INSTANCE.${this::convertToMethodInfo.name}(testMetadata, testTags, descriptor.getDisplayName()); + boolean shouldSkip = methodInfo != null && ${RecommendedTests::class.java.name}.INSTANCE.${RecommendedTests::shouldSkipByTestMethod.name}(methodInfo); + if (shouldSkip) { + return $FilterResult.excluded("skipped by Drill4J"); + } else { + return $FilterResult.included("recommended by Drill4J"); + } + } + """.trimIndent(), + cc + ) + ) + cc.toClass(classLoader, protectionDomain) + return cc + } + + private fun createLauncherDiscoveryRequestAdapterClass( + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ): CtClass { + val cc: CtClass = pool.makeClass(LauncherDiscoveryRequestAdapter) + cc.interfaces = arrayOf(pool.get(LauncherDiscoveryRequest)) + cc.addField(CtField.make("$LauncherDiscoveryRequest delegate = null;", cc)) + cc.addField(CtField.make("$PostDiscoveryFilter additionalFilter = null;", cc)) + cc.addConstructor( + CtNewConstructor.make( + """ + public LauncherDiscoveryRequestAdapter($LauncherDiscoveryRequest delegate, $PostDiscoveryFilter additionalFilter) { + this.delegate = delegate; + this.additionalFilter = additionalFilter; + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public java.util.List getEngineFilters() { + return delegate.getEngineFilters(); + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public java.util.List getPostDiscoveryFilters() { + java.util.ArrayList modifiedList = new java.util.ArrayList(delegate.getPostDiscoveryFilters()); + modifiedList.add(additionalFilter); + return modifiedList; + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public java.util.List getSelectorsByType(java.lang.Class selectorType) { + return delegate.getSelectorsByType(selectorType); + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public java.util.List getFiltersByType(java.lang.Class filterType) { + return delegate.getFiltersByType(filterType); + } + """.trimIndent(), + cc + ) + ) + cc.addMethod( + CtMethod.make( + """ + public $ConfigurationParameters getConfigurationParameters() { + return delegate.getConfigurationParameters(); + } + """.trimIndent(), + cc + ) + ) + cc.toClass(classLoader, protectionDomain) + return cc + } + + @Suppress("MemberVisibilityCanBePrivate") + fun convertToMethodInfo(testMetadata: Map, + testTags: List, + displayName: String?): TestMethodInfo? { + val testPath = testMetadata["class"] ?: testMetadata["feature"] ?: testMetadata["suite"] + val testName = testMetadata["method"]?.substringBefore("(") ?: displayName + if (testPath == null || testName == null) { + logger.error { "Failed to convert test metadata to TestDetails: $testMetadata" } + return null + } + return TestMethodInfo( + engine = testMetadata["engine"] ?: "junit", + className = testPath, + method = testName, + tags = testTags, + metadata = testMetadata + ) + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/ChromeDevTool.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/ChromeDevTool.kt new file mode 100644 index 00000000..953c6528 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/ChromeDevTool.kt @@ -0,0 +1,354 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import com.epam.drill.agent.test.* +import com.epam.drill.agent.test.serialization.* +import com.epam.drill.agent.test.session.* +import com.epam.drill.agent.common.transport.AgentMessage +import com.epam.drill.agent.common.transport.ResponseStatus +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.instrument.TestSessionHeadersProcessor +import com.epam.drill.agent.test.devtools.DevToolsMessageSender +import com.epam.drill.agent.test.serialization.json +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlin.time.DurationUnit +import kotlin.time.measureTimedValue +import java.net.* +import java.util.* +import mu.KotlinLogging +import kotlin.reflect.KClass + +private const val DEBUGGER_ADDRESS = "debuggerAddress" +private const val DEV_TOOL_DEBUGGER_URL = "webSocketDebuggerUrl" +private val JAVA_TOGGLES = listOf("Network") +private val JS_TOGGLES = listOf("Debugger", "Profiler") + .takeIf { Configuration.parameters[ParameterDefinitions.WITH_JS_COVERAGE] } + ?: emptyList() +private val REPLACE_LOCALHOST = Configuration.parameters[ParameterDefinitions.DEVTOOLS_REPLACE_LOCALHOST] + +/** + * Works with local or Selenoid DevTools by websocket + */ +class ChromeDevTool( + private val capabilities: Map<*, *>?, + private val remoteHost: String? +) { + private val logger = KotlinLogging.logger {} + private val launchType = Configuration.parameters[ParameterDefinitions.LAUNCH_TYPE] + private var isClosed = false + + private lateinit var targetUrl: String + private lateinit var targetId: String + private var sessionId: SessionId = SessionId() + private var headersAdded: Boolean = false + + /** + * connect to remote Selenoid or local webDriver + */ + fun connect(browserSessionId: String?, currentUrl: String) = runCatching { + logger.debug { "starting connectToDevTools with cap='$capabilities' sessionId='$sessionId' remote='$remoteHost'..." } + retrieveDevToolAddress(capabilities ?: emptyMap(), browserSessionId, remoteHost).let { + trackTime("connect to devtools") { + connect(it, currentUrl) + } + } + /** + * Add this to thread local only if successfully connected + */ + }.onFailure { logger.warn(it) { "UI coverage will be lost. Reason: " } }.getOrNull() + + fun addHeaders(headers: Map<*, *>) { + @Suppress("UNCHECKED_CAST") + val casted = headers as Map + try { + logger.trace { "try to add headers: $headers" } + val success = setHeaders(casted) + logger.debug { "Chrome Tool activated: ${sessionId.sessionId.isNotBlank()}. Headers: $headers" } + if (!success) throw RuntimeException("Can't add headers: $headers") + } catch (ex: Exception) { + logger.debug { "exception $ex; try to resend" } + Thread.sleep(2000) + setHeaders(casted) + } + } + + fun switchSession(url: String) { + val targetId = retrieveTargetId(url) + logger.trace { "Reconnect to target: $targetId, sessionId: ${sessionId.sessionId}, url $url" } + targetId?.takeIf { it != this.targetId }?.let { attachToTarget(it) }?.let { + this.targetId = targetId + sessionId = it + enableToggles() + startCollectJsCoverage() + } + } + + fun isHeadersAdded(): Boolean = this.headersAdded + + private fun startCollectJsCoverage() = + Configuration.parameters[ParameterDefinitions.WITH_JS_COVERAGE].takeIf(true::equals)?.let { + disableCache() && startPreciseCoverage() && enableScriptParsed() + }?.also { success -> + if (!success) logger.warn { "JS coverage may be lost" } + } + + private fun startPreciseCoverage() = mapOf("detailed" to true, "callCount" to false).let { params -> + executeCommand( + "Profiler.startPreciseCoverage", + DevToolsRequest(targetUrl, sessionId.sessionId, params.toOutput()) + ).success + } + + private fun disableCache() = executeCommand( + "Network.setCacheDisabled", + DevToolsRequest(targetUrl, sessionId.sessionId, mapOf("cacheDisabled" to true).toOutput()) + ).success + + private fun enableScriptParsed() = DevToolsMessageSender.send( + "POST", + "/event/Debugger.scriptParsed", + DevToolsRequest(targetUrl, sessionId.sessionId) + ).success + + fun takePreciseCoverage(): String = executeCommand( + "Profiler.takePreciseCoverage", + DevToolsRequest(targetUrl, sessionId.sessionId) + ).takeIf(ResponseStatus::success)?.content ?: "" + + fun scriptParsed(): String = DevToolsMessageSender.send( + "POST", + "/event/Debugger.scriptParsed/get-data", + DevToolsRequest(targetUrl, sessionId.sessionId) + ).takeIf(ResponseStatus::success)?.content ?: "" + + fun close() { + if (!isClosed) { + disableToggles() + stopCollectJsCoverage() + DevToolsMessageSender.send( + "DELETE", + "/connection", + DevToolsRequest(targetUrl) + ) + } + isClosed = true + } + + private fun stopCollectJsCoverage() = + Configuration.parameters[ParameterDefinitions.WITH_JS_COVERAGE].takeIf(true::equals)?.let { + DevToolsMessageSender.send( + "DELETE", + "/event/Debugger.scriptParsed", + DevToolsRequest(targetUrl, sessionId.sessionId) + ) + } + + // todo is it necessary to disable toggles when browser exit? + private fun disableToggles() = (JAVA_TOGGLES + JS_TOGGLES).map { + executeCommand( + "$it.disable", + DevToolsRequest(targetUrl, sessionId.sessionId) + ).success + }.all { it } + + private fun enableToggles() = (JAVA_TOGGLES + JS_TOGGLES).map { + executeCommand( + "$it.enable", + DevToolsRequest(targetUrl, sessionId.sessionId) + ).success + }.all { it }.also { + if (!it) logger.warn { "Toggles wasn't enable" } else logger.info { "Toggles enabled" } + } + + private fun retrieveDevToolAddress( + capabilities: Map<*, *>, + sessionId: String?, + remoteHost: String? + ): String = when (launchType) { + + // selenoid provides no access to /json/version, but allows to connect to debugger directly + // see https://aerokube.com/selenoid/latest/#_accessing_browser_developer_tools + "selenoid" -> { + if (sessionId.isNullOrBlank()) + throw RuntimeException("Can't connect to debugger directly, because 'sessionId' is null") + if (remoteHost.isNullOrBlank()) + throw RuntimeException("Can't connect to debugger directly, because 'remoteHost' is null") + "ws://$remoteHost/devtools/$sessionId" + } + + else -> capabilities.run { + val debuggerURL = get(DEBUGGER_ADDRESS)?.toString() + + if (debuggerURL.isNullOrBlank()) { + error("Can't get debugger address by field name $DEBUGGER_ADDRESS from capabilities: $capabilities}") + } + + return DevToolsMessageSender.send("http://$debuggerURL", "GET", "/json/version", "") + .onError { error -> + error("Can't get debugger address from http://$debuggerURL/json/version: $error") + } + .onSuccess { content -> + logger.trace { "/json/version: $content" } + + }.content?.let { content -> + val chromeInfo = Json.parseToJsonElement(content) as JsonObject + chromeInfo[DEV_TOOL_DEBUGGER_URL]?.jsonPrimitive?.contentOrNull + } + ?: error("Can't get debugger address from '$DEV_TOOL_DEBUGGER_URL' field") + } + } + + + private fun connect(devToolAddress: String, currentUrl: String) { + if (REPLACE_LOCALHOST.isNotBlank()) { + targetUrl = devToolAddress.replace("localhost", REPLACE_LOCALHOST) + } else { + targetUrl = devToolAddress + } + val success: Boolean = connectToDevTools().takeIf { it }?.also { + val targetId = retrieveTargetId(currentUrl) + logger.info { "Retrieved target for url $currentUrl: $targetId" } + targetId?.let { attachToTarget(it) }?.also { + this.targetId = targetId + sessionId = it + logger.debug { "DevTools session created: $sessionId" } + enableToggles() + startCollectJsCoverage() + } + } ?: false + if (success) { + DevToolStorage.set(this) + } else throw RuntimeException("Can't connect to $targetUrl") + } + + private fun connectToDevTools(): Boolean { + logger.debug { "DevTools URL: $targetUrl" } + val response = DevToolsMessageSender.send( + "POST", + "/connection", + DevToolsRequest(targetUrl) + ) + return response.success + } + + fun startIntercept(): Boolean { + val headers = TestSessionHeadersProcessor.retrieveHeaders() + if (headers.isEmpty()) return false + logger.debug { "Start intercepting. Headers: $headers, sessionId: $sessionId" } + val response = DevToolsMessageSender.send( + "POST", + "/intercept", + DevToolInterceptRequest(targetUrl, params = mapOf("headers" to headers)) + ) + return response.success + } + + + fun stopIntercept(): Boolean { + logger.debug { "Stop intercepting: $targetUrl, sessionId $sessionId" } + val response = DevToolsMessageSender.send( + "DELETE", + "/intercept", + DevToolInterceptRequest(targetUrl) + ) + setHeaders(mapOf()) + return response.success + } + + private fun setHeaders( + params: Map + ): Boolean = executeCommand( + "Network.setExtraHTTPHeaders", + DevToolsHeaderRequest(targetUrl, sessionId.sessionId, mapOf("headers" to params)) + ).success + + @Deprecated(message = "Useless") + private fun autoAttach(): Boolean { + val params = mapOf("autoAttach" to true, "waitForDebuggerOnStart" to false).toOutput() + return executeCommand( + "Target.setAutoAttach", + DevToolsRequest(targetUrl, sessionId.sessionId, params = params) + ).success + } + + private fun attachToTarget(targetId: String): SessionId? { + val params = mapOf("targetId" to targetId, "flatten" to true).toOutput() + val response = executeCommand( + "Target.attachToTarget", + DevToolsRequest(target = targetUrl, params = params), + SessionId::class + ) + return response.takeIf(ResponseStatus::success) + ?.let(ResponseStatus::content) + } + + private fun retrieveTargetId(currentUrl: String): String? = targets() + .find { it.url == currentUrl } + ?.targetId + ?.uppercase(Locale.getDefault()) + ?.takeIf { it.isNotBlank() } + + private fun targets(): List = executeCommand( + "Target.getTargets", + DevToolsRequest(target = targetUrl), + TargetInfos::class + ).takeIf(ResponseStatus::success) + ?.let(ResponseStatus::content) + ?.let(TargetInfos::targetInfos) + ?: emptyList() + + private fun executeCommand( + commandName: String, + request: DevToolsMessage, + httpMethod: String = "POST" + ): ResponseStatus = DevToolsMessageSender.send(httpMethod, "/command/$commandName", request) + + private fun executeCommand( + commandName: String, + request: DevToolsMessage, + clazz: KClass, + httpMethod: String = "POST" + ): ResponseStatus = DevToolsMessageSender.send(httpMethod, "/command/$commandName", request, clazz) + + private fun Map.toOutput(): Map = mapValues { (_, value) -> + val serializer = value::class.serializer().cast() + json.encodeToJsonElement(serializer, value) + } + + @Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") + private inline fun KSerializer.cast(): KSerializer = this as KSerializer + + private inline fun trackTime(tag: String = "", debug: Boolean = false, block: () -> T) = + measureTimedValue { block() }.apply { + val logger = KotlinLogging.logger {} + val message = "[$tag] took: $duration" + when { + duration.toDouble(DurationUnit.SECONDS) > 1 -> { + logger.warn { message } + } + + duration.toDouble(DurationUnit.SECONDS) > 30 -> { + logger.error { message } + } + + else -> if (debug) logger.debug { message } else logger.trace { message } + } + }.value + +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/DevToolStorage.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/DevToolStorage.kt new file mode 100644 index 00000000..4c5e7a54 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/DevToolStorage.kt @@ -0,0 +1,32 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import mu.KotlinLogging + +object DevToolStorage { + private val logger = KotlinLogging.logger {} + private val storage: InheritableThreadLocal = InheritableThreadLocal() + + fun set(devtool: ChromeDevTool) { + storage.set(devtool) + logger.debug { "DevTool inited for: Thread id=${Thread.currentThread().id}, DevToolWS address=$devtool" } + } + + fun get(): ChromeDevTool? = storage.get() + + fun clear() = storage.remove() +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/Model.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/Model.kt new file mode 100644 index 00000000..21560fbc --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/Model.kt @@ -0,0 +1,61 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import com.epam.drill.agent.common.transport.AgentMessage + +@Serializable +data class TargetInfos(val targetInfos: List): AgentMessage() + +@Serializable +data class SessionId(val sessionId: String = ""): AgentMessage() + +@Serializable +data class Target( + val targetId: String, + val type: String, + val title: String, + val url: String, + val attached: Boolean, + val browserContextId: String, +) + +@Serializable +sealed class DevToolsMessage : AgentMessage() { + abstract val target: String +} + +@Serializable +data class DevToolsRequest( + override val target: String, + val sessionId: String = "", + val params: Map = emptyMap() +) : DevToolsMessage() + +@Serializable +data class DevToolInterceptRequest( + override val target: String, + val params: Map> = emptyMap() +) : DevToolsMessage() + +@Serializable +data class DevToolsHeaderRequest( + override val target: String, + val sessionId: String, + val params: Map> = emptyMap(), +) : DevToolsMessage() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt new file mode 100644 index 00000000..56195b92 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -0,0 +1,278 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.* +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SELENIUM_ENABLED +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject +import javassist.* +import java.io.* +import mu.KotlinLogging +import java.security.ProtectionDomain + +@Suppress("PrivatePropertyName") +actual object SeleniumTransformer : TransformerObject, AbstractTestTransformerObject() { + + private const val Command = "org.openqa.selenium.remote.Command" + private const val ImmutableMap = "com.google.common.collect.ImmutableMap" + private const val ImmutableList = "com.google.common.collect.ImmutableList" + private const val Cookie = "org.openqa.selenium.Cookie" + private const val DesiredCapabilities = "org.openqa.selenium.remote.DesiredCapabilities" + private const val Proxy = "org.openqa.selenium.Proxy" + private const val initPages = "\"about:blank\", \"data:,\"" + private const val EXTENSION_NAME = "header-transmitter.xpi" + private val FirefoxDriver = "org.openqa.selenium.firefox.FirefoxDriver" + + private val extensionFile: String + + internal const val addDrillCookiesMethod = "addDrillCookies" + private const val isFirefoxBrowser = "isFirefoxBrowser" + + override val logger = KotlinLogging.logger {} + + init { + val extension = this::class.java.getResource("/$EXTENSION_NAME") + File(System.getProperty("java.io.tmpdir")).resolve(EXTENSION_NAME).apply { + extensionFile = absolutePath + writeBytes(extension.readBytes()) + } + } + + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_SELENIUM_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/openqa/selenium/remote/RemoteWebDriver" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain? + ) { + logger.debug { "starting instrument ${ctClass.name}..." } + + var remoteWebDriverConstructorInstrumented = false; + + fun tryCatch(fn: () -> Any) { + try { + fn(); + remoteWebDriverConstructorInstrumented = true; + } catch (e: Exception) { + logger.debug { "failed to instrument: $e" } + } + } + + ctClass.addField(CtField.make("java.lang.String drillRemoteAddress;", ctClass)) + + tryCatch { + ctClass + .getConstructor("(Lorg/openqa/selenium/remote/CommandExecutor;Lorg/openqa/selenium/Capabilities;)V") + .insertBefore( + """ + try { + if ($1 instanceof org.openqa.selenium.remote.HttpCommandExecutor) { + java.lang.System.out.println("Constructor called - (Lorg/openqa/selenium/remote/CommandExecutor;Lorg/openqa/selenium/Capabilities;)V"); + org.openqa.selenium.remote.HttpCommandExecutor drillHttpCommandExecutor = (org.openqa.selenium.remote.HttpCommandExecutor) $1; + drillRemoteAddress = drillHttpCommandExecutor.getAddressOfRemoteServer().getAuthority(); + } + } catch (Exception e) { + java.lang.System.out.println( + "Drill4J: failed to get remote address - Constructor: RemoteWebDriver(CommandExecutor executor, Capabilities desiredCapabilities) - Error: " + e.toString() + ); + } + """.trimIndent() + ) + } + + tryCatch { + ctClass + .getConstructor("(Ljava/net/URL;Lorg/openqa/selenium/Capabilities;)V") + .insertBefore( + """ + try { + java.lang.System.out.println("Constructor called - (Ljava/net/URL;Lorg/openqa/selenium/Capabilities;)V"); + + drillRemoteAddress = $1.getAuthority(); + } catch (Exception e) { + java.lang.System.out.println( + "Drill4J: failed to get remote address - Constructor: RemoteWebDriver(URL remoteAddress, Capabilities desiredCapabilities) - Error: " + e.toString() + ); + } + """.trimIndent() + ) + } + + tryCatch { + ctClass + .getConstructor("(Ljava/net/URL;Lorg/openqa/selenium/Capabilities;Lorg/openqa/selenium/Capabilities;)V") + .insertBefore( + """ + try { + java.lang.System.out.println("Constructor called - (Ljava/net/URL;Lorg/openqa/selenium/Capabilities;Lorg/openqa/selenium/Capabilities;)V"); + drillRemoteAddress = $1.getAuthority(); + } catch (Exception e) { + java.lang.System.out.println( + "Drill4J: failed to get remote address - Constructor: RemoteWebDriver(URL remoteAddress, Capabilities desiredCapabilities, Capabilities requiredCapabilities) - Error: " + e.toString() + ); + } + """.trimIndent() + ) + } + + tryCatch { + ctClass + .getConstructor("(Lorg/openqa/selenium/Capabilities;)V") + .insertBefore( + """ + java.lang.System.out.println("Constructor called - (Lorg/openqa/selenium/Capabilities;)V"); + """.trimIndent() + ) + } + + if (!remoteWebDriverConstructorInstrumented) { + logger.warn { "No RemoteWebDriver constructors were instrumented. Possibly unsupported Selenium version" } + } else { + logger.debug { "RemoteWebDriver constructors instrumented" } + } + + ctClass.addMethod( + CtMethod.make( + """ + public boolean $isFirefoxBrowser(org.openqa.selenium.Capabilities capabilities){ + return capabilities.getBrowserName().equalsIgnoreCase("firefox"); + } + """.trimIndent(), + ctClass + ) + ) + + val startSession = ctClass.getDeclaredMethod("startSession") + + /** + * Browser proxy is needed only for Firefox browser + */ + startSession.insertBefore( + """ + if (${this::class.java.name}.INSTANCE.${this::proxyUrl.name}() != null && $isFirefoxBrowser($1)) { + $DesiredCapabilities dCap = new $DesiredCapabilities(); + $Proxy dProxy = new $Proxy(); + dProxy.setHttpProxy(${this::class.java.name}.INSTANCE.${this::proxyUrl.name}()); + dProxy.setSslProxy(${this::class.java.name}.INSTANCE.${this::proxyUrl.name}()); + dCap.setCapability("proxy", dProxy); + $1 = $1.merge(dCap); + } + ${WebDriverThreadStorage::class.java.name}.INSTANCE.${WebDriverThreadStorage::set.name}(this); + """ + ) + startSession.insertAfter( + """ + if (${this::class.java.name}.INSTANCE.${this::devToolsProxyAddress.name}() != null){ + ${ChromeDevTool::class.java.name} drillDevTools = new ${ChromeDevTool::class.java.name}( + ((java.util.Map)this.capabilities.getCapability("goog:chromeOptions")), + drillRemoteAddress + ); + drillDevTools.${ChromeDevTool::connect.name}(sessionId.toString(), getCurrentUrl()); + } + try { + if (this instanceof $FirefoxDriver) { + java.util.HashMap hashMapq = new java.util.HashMap(); + hashMapq.put("path", "${extensionFile.replace("\\", "\\\\")}"); + hashMapq.put("temporary", Boolean.TRUE); + this.execute("installExtension", hashMapq).getValue(); + } + } catch (Exception e){} + """ + ) + ctClass.addMethod( + CtMethod.make( + """ + public void $addDrillCookiesMethod() { + if ($isFirefoxBrowser(getCapabilities()) && $ARE_DRILL_HEADERS_PRESENT) { + try { + executor.execute(new $Command(sessionId, "addCookie", $ImmutableMap.of("cookie", new $Cookie($SESSION_ID_CALC_LINE)))); + executor.execute(new $Command(sessionId, "addCookie", $ImmutableMap.of("cookie", new $Cookie($TEST_NAME_CALC_LINE)))); + } catch(Exception e) { e.printStackTrace();} + } + } + """.trimIndent(), + ctClass + ) + ) + ctClass.addMethod( + CtMethod.make( + """ + public void addDrillHeaders() { + if ($IS_DEV_TOOL_NOT_NULL && $ARE_DRILL_HEADERS_PRESENT && !$IS_HEADER_ADDED) { + try { + java.util.HashMap hashMap = new java.util.HashMap(); + hashMap.put($SESSION_ID_CALC_LINE); + hashMap.put($TEST_NAME_CALC_LINE); + ${getChromeDevTool()}.${ChromeDevTool::addHeaders.name}(hashMap); + } catch(Exception e) { e.printStackTrace();} + } + } + """.trimIndent(), + ctClass + ) + ) + ctClass.getDeclaredMethod("get").insertBefore( + """ + boolean isInitPage = $ImmutableList.of($initPages).contains(getCurrentUrl()); + if (isInitPage) { execute("get", $ImmutableMap.of("url", $1)); } + addDrillHeaders(); + $addDrillCookiesMethod(); + """.trimIndent() + ) + /** + * todo enable js instrumentation on tab open @Roman_Davliatshin + */ + ctClass.getMethod( + "execute", + "(Ljava/lang/String;Ljava/util/Map;)Lorg/openqa/selenium/remote/Response;" + ).insertAfter( + """ + if ($1.equals(org.openqa.selenium.remote.DriverCommand.SWITCH_TO_WINDOW)){ + java.lang.String currentUrl = getCurrentUrl(); + if ($IS_DEV_TOOL_NOT_NULL){ + ${getChromeDevTool()}.${ChromeDevTool::switchSession.name}(currentUrl); + } else { + execute("get", $ImmutableMap.of("url",currentUrl)); + $addDrillCookiesMethod(); + } + } + """.trimIndent() + ) + ctClass.getDeclaredMethod("quit").insertBefore( + """ + if ($IS_DEV_TOOL_NOT_NULL){ + ${getChromeDevTool()}.${ChromeDevTool::close.name}(); + ${DevToolStorage::class.java.name}.INSTANCE.${DevToolStorage::clear.name}(); + } + ${WebDriverThreadStorage::class.java.name}.INSTANCE.${WebDriverThreadStorage::clear.name}(); + """.trimIndent() + ) + } + + fun proxyUrl() = Configuration.parameters[ParameterDefinitions.PROXY_ADDRESS] + + fun devToolsProxyAddress() = Configuration.parameters[ParameterDefinitions.DEVTOOLS_PROXY_ADDRESS] + + private fun getChromeDevTool() = "${DevToolStorage::class.java.name}.INSTANCE.${DevToolStorage::get.name}()" +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/WebDriverThreadStorage.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/WebDriverThreadStorage.kt new file mode 100644 index 00000000..a2d5319b --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/WebDriverThreadStorage.kt @@ -0,0 +1,32 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +object WebDriverThreadStorage { + private val webDriver = InheritableThreadLocal() + + fun set(obj: Any) = webDriver.set(obj) + + fun addCookies() { + runCatching { + webDriver.get()?.let { + it.javaClass.getMethod(SeleniumTransformer.addDrillCookiesMethod).invoke(it) + } + }.getOrNull() + } + + fun clear() = webDriver.remove() +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNG67Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNG67Transformer.kt new file mode 100644 index 00000000..b0eddae6 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNG67Transformer.kt @@ -0,0 +1,202 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.test.execution.TestController +import javassist.* +import java.lang.reflect.* +import java.security.* +import mu.KotlinLogging + +abstract class AbstractTestNG67Transformer() : AbstractTestNGTransformer() { + companion object { + const val engineSegment = "testng" + const val TestNGMethod = "org.testng.internal.TestNGMethod" + const val ITestResult = "org.testng.ITestResult" + + private const val DrillTestNGTestListner = "DrillTestNGTestListener" + private const val ITestContext = "org.testng.ITestContext" + } + + override val logger = KotlinLogging.logger {} + + abstract val versionRegex: Regex + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/testng/TestRunner" + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + createTestListener(pool, classLoader, protectionDomain) + ctClass.constructors.forEach { it.insertAfter("addTestListener(new $DrillTestNGTestListner());") } + ctClass.supportIgnoredTestsTracking() + } + + private fun createTestListener( + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + val testListener = pool.makeClass(DrillTestNGTestListner) + testListener.interfaces = arrayOf(pool.get("org.testng.ITestListener")) + testListener.addMethod( + CtMethod.make(getParamsMethod(), testListener) + ) + testListener.addMethod( + CtMethod.make(getTestClassNameMethod(), testListener) + ) + testListener.addMethod( + CtMethod.make(getTestNameMethod(), testListener) + ) + testListener.addMethod( + CtMethod.make(getTestGroups(), testListener) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onTestStart($ITestResult result) { + if (result.getThrowable() == null) { + ${TestController::class.java.name}.INSTANCE.${TestController::testStarted.name}("$engineSegment", getTestClassName(result), getTestName(result), getParamsString(result), getTestGroups(result)); + } else { + ${this::class.java.name}.INSTANCE.${this::debug.name}("The start of the test " + result.getName() + " is ignored by the drill"); + } + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onTestSuccess($ITestResult result) { + ${TestController::class.java.name}.INSTANCE.${TestController::testFinished.name}("$engineSegment", getTestClassName(result), getTestName(result), "PASSED", getParamsString(result), getTestGroups(result)); + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onTestFailure($ITestResult result) { + ${TestController::class.java.name}.INSTANCE.${TestController::testFinished.name}("$engineSegment", getTestClassName(result), getTestName(result), "FAILED", getParamsString(result), getTestGroups(result)); + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onTestSkipped($ITestResult result) { + ${TestController::class.java.name}.INSTANCE.${TestController::testIgnored.name}("$engineSegment", getTestClassName(result), getTestName(result), getParamsString(result), getTestGroups(result)); + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onTestFailedButWithinSuccessPercentage($ITestResult result) { + return; + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onStart($ITestContext result) { + return; + } + """.trimIndent(), + testListener + ) + ) + testListener.addMethod( + CtMethod.make( + """ + public void onFinish($ITestContext result) { + return; + } + """.trimIndent(), + testListener + ) + ) + testListener.toClass(classLoader, protectionDomain) + } + + protected open fun getParamsMethod(): String = """ + private String getParamsString($ITestResult result) { + Object[] parameters = result.getParameters(); + String paramString = ${this::class.java.name}.INSTANCE.${this::paramTypes.name}(parameters); + return paramString; + } + """.trimIndent() + + protected open fun getTestClassNameMethod(): String = """ + private String getTestClassName($ITestResult result) { + return result.getInstanceName(); + } + """.trimIndent() + + protected open fun getTestNameMethod(): String = """ + private String getTestName($ITestResult result) { + return result.getName(); + } + """.trimIndent() + + protected open fun getTestGroups(): String = """ + private java.util.List getTestGroups($ITestResult result) { + String[] groups = result.getMethod().getGroups(); + return java.util.Arrays.asList(groups); + } + """.trimIndent() + + + private fun CtClass.supportIgnoredTestsTracking() = getDeclaredMethod("run").insertBefore( + """ + java.util.Iterator disabledTests = getExcludedMethods().iterator(); + while(disabledTests.hasNext()) { + java.lang.Object baseMethod = disabledTests.next(); + if (baseMethod instanceof $TestNGMethod) { + $TestNGMethod test = ($TestNGMethod) baseMethod; + ${TestController::class.java.name}.INSTANCE.${TestController::testIgnored.name}("$engineSegment", test.getTestClass().getName(), test.getMethodName()); + } + } + """.trimIndent() + ) + + fun paramTypes(objects: Array?): String = objects?.joinToString(",", "(", ")") { obj -> + when (obj) { + null -> obj.toString() + is Field -> obj.type.simpleName + else -> obj.javaClass.simpleName.substringBeforeLast("\$") + } + } ?: "" + + fun debug(message: String) { + logger.debug { message } + } + +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt new file mode 100644 index 00000000..85edecf0 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt @@ -0,0 +1,80 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.prioritization.RecommendedTests +import javassist.ClassPool +import javassist.CtClass +import java.security.ProtectionDomain + +abstract class AbstractTestNGPrioritizingTransformer() : AbstractTestNGTransformer() { + private val engineSegment = "testng" + abstract val versionRegex: Regex + abstract fun getMethodParametersExpression(): String + + override fun enabled(): Boolean = super.enabled() && agentConfiguration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return interfaces.any { it == "org/testng/IMethodSelector" } + } + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + if ("${ctClass.url}".contains(versionRegex)) { + instrumentIfSupport(ctClass, pool, classLoader, protectionDomain) + } + } + + private fun instrumentIfSupport( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ): ByteArray? { + instrumentIncludeMethod(ctClass) + return ctClass.toBytecode() + } + + private fun instrumentIncludeMethod(ctClass: CtClass) { + ctClass.getMethod( + "includeMethod", + "(Lorg/testng/IMethodSelectorContext;Lorg/testng/ITestNGMethod;Z)Z" + ).insertAfter( + """ + if (${'$'}_ == true && $3 == true) { + java.lang.String className = $2.getTestClass().getName(); + java.lang.String methodName = $2.getMethodName(); + java.lang.String methodParameters = ${this::class.java.name}.INSTANCE.${this::paramTypes.name}($2.${getMethodParametersExpression()}); + boolean shouldSkip = ${RecommendedTests::class.java.name}.INSTANCE.${RecommendedTests::shouldSkip.name}("$engineSegment", className, methodName, methodParameters); + if (shouldSkip) { + return false; + } + } + """.trimIndent() + ) + } + + @Suppress("MemberVisibilityCanBePrivate") + fun paramTypes(objects: Array?>?): String = objects?.joinToString(",", "(", ")") { obj -> + obj?.name ?: "" + } ?: "" + +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt new file mode 100644 index 00000000..5e8ba129 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt @@ -0,0 +1,23 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_TESTNG_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +abstract class AbstractTestNGTransformer(): AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_TESTNG_ENABLED] +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt new file mode 100644 index 00000000..b028106e --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject +import mu.KotlinLogging + +actual object TestNG6PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() { + override val logger = KotlinLogging.logger {} + override val versionRegex: Regex = "testng-6\\.[0-9]+(\\.[0-9]+)*".toRegex() + + override fun getMethodParametersExpression(): String { + return "getConstructorOrMethod().getParameterTypes()" + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt new file mode 100644 index 00000000..b96b433f --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -0,0 +1,42 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject +import javassist.* +import java.security.* + +actual object TestNG6Transformer : TransformerObject, AbstractTestNG67Transformer() { + override val versionRegex: Regex = "testng-6\\.[0-9]+(\\.[0-9]+)*".toRegex() + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + if ("${ctClass.url}".contains(versionRegex)) { + super.instrument(ctClass, pool, classLoader, protectionDomain) + } + } + + + override fun getTestClassNameMethod(): String = """ + private String getTestClassName($ITestResult result) { + return result.getTestClass().getName(); + } + """.trimIndent() +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt new file mode 100644 index 00000000..c0c9221b --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject +import mu.KotlinLogging + +actual object TestNG7PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() { + override val logger = KotlinLogging.logger {} + override val versionRegex: Regex = "testng-7\\.[0-9]+(\\.[0-9]+)*".toRegex() + + override fun getMethodParametersExpression(): String { + return "getParameterTypes()" + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt new file mode 100644 index 00000000..2018db17 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -0,0 +1,36 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject +import javassist.* +import java.security.* + +actual object TestNG7Transformer : TransformerObject, AbstractTestNG67Transformer() { + + override val versionRegex: Regex = "testng-7\\.[0-9]+(\\.[0-9]+)*".toRegex() + + override fun instrument( + ctClass: CtClass, + pool: ClassPool, + classLoader: ClassLoader?, + protectionDomain: ProtectionDomain?, + ) { + if ("${ctClass.url}".contains(versionRegex)) { + super.instrument(ctClass, pool, classLoader, protectionDomain) + } + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTests.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTests.kt new file mode 100644 index 00000000..b2b75bcb --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTests.kt @@ -0,0 +1,59 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.prioritization + +import com.epam.drill.agent.test.execution.TestMethodInfo +import mu.KotlinLogging + +object RecommendedTests { + private val logger = KotlinLogging.logger {} + private val recommendedTestsReceiver: RecommendedTestsReceiver = RecommendedTestsReceiverImpl() + private val testsToSkip: Set by lazy { initTestsToSkip() } + + private fun initTestsToSkip() = recommendedTestsReceiver.getTestsToSkip() + .toSet() + .also { + logger.info { "${it.size} tests will be skipped by Drill4J" } + } + + + fun shouldSkip( + engine: String, + testClass: String, + testMethod: String, + methodParameters: String = "()" + ): Boolean { + val test = TestMethodInfo( + engine = engine, + className = testClass, + method = testMethod, + methodParams = methodParameters, + ) + return shouldSkipByTestMethod(test) + } + + fun shouldSkipByTestMethod(test: TestMethodInfo): Boolean { + return testsToSkip.contains(test).also { + if (it) { + logger.debug { "Test `${test.method}` will be skipped by Drill4J" } + recommendedTestsReceiver.sendSkippedTest(test) + } else { + logger.debug { "Test `${test.method}` will not be skipped by Drill4J" } + } + } + } + +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt new file mode 100644 index 00000000..45de6b1a --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt @@ -0,0 +1,125 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.prioritization + +import com.epam.drill.agent.common.transport.AgentMessageDestination +import com.epam.drill.agent.common.transport.AgentMessageReceiver +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.DefaultParameterDefinitions +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.execution.TestController +import com.epam.drill.agent.test.execution.TestExecutionRecorder +import com.epam.drill.agent.test.execution.TestMethodInfo +import com.epam.drill.agent.test.sending.* +import com.epam.drill.agent.test.transport.TestAgentMessageReceiver +import kotlinx.serialization.Serializable +import mu.KotlinLogging + +interface RecommendedTestsReceiver { + fun getTestsToSkip(): List + fun sendSkippedTest(test: TestMethodInfo) +} + +class RecommendedTestsReceiverImpl( + private val agentMessageReceiver: AgentMessageReceiver = TestAgentMessageReceiver, + private val testExecutionRecorder: TestExecutionRecorder = TestController +) : RecommendedTestsReceiver { + private val logger = KotlinLogging.logger {} + + override fun getTestsToSkip(): List { + if (!Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED]) + return emptyList() + val groupId = Configuration.parameters[DefaultParameterDefinitions.GROUP_ID] + val testTaskId = Configuration.parameters[ParameterDefinitions.TEST_TASK_ID] + val targetAppId = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_APP_ID] + val targetBuildVersion = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_BUILD_VERSION] + .takeIf { it.isNotEmpty() } + val targetCommitSha = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_COMMIT_SHA] + .takeIf { it.isNotEmpty() } + val baselineCommitSha = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_BASELINE_COMMIT_SHA] + .takeIf { it.isNotEmpty() } + val baselineBuildVersion = + Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_BASELINE_BUILD_VERSION] + .takeIf { it.isNotEmpty() } + val coveragePeriodDays = + Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_COVERAGE_PERIOD_DAYS].toInt() + .takeIf { it > 0 } + val useMaterializedViews = + Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_USE_MATERIALIZED_VIEWS] + .takeIf { it.isNotEmpty() } + ?.lowercase() + ?.toBooleanStrict() + + val parameters: String = buildString { + append("?groupId=$groupId") + append("&appId=$targetAppId") + append("&testTaskId=$testTaskId") + append("&testsToSkip=true") + targetBuildVersion?.let { append("&targetBuildVersion=$it") } + targetCommitSha?.let { append("&targetCommitSha=$it") } + baselineCommitSha?.let { append("&baselineCommitSha=$it") } + baselineBuildVersion?.let { append("&baselineBuildVersion=$it") } + coveragePeriodDays?.let { append("&coveragePeriodDays=$it") } + useMaterializedViews?.let { append("&useMaterializedViews=$it") } + } + logger.debug { "Retrieving information about recommended tests, testTaskId: $testTaskId" } + return runCatching { + agentMessageReceiver.receive( + AgentMessageDestination( + "GET", + "/recommended-tests$parameters", + ), + RecommendedTestsApiResponse::class + ).data.recommendedTests.map { it.toTestMethodInfo() } + }.onFailure { + logger.warn { "Unable to retrieve information about recommended tests. Error message: $it" } + }.getOrElse { + emptyList() + } + } + + override fun sendSkippedTest(test: TestMethodInfo) { + testExecutionRecorder.recordTestIgnoring(test, isSmartSkip = true) + } +} + +@Serializable +class RecommendedTestsApiResponse( + val data: RecommendedTestsResponse +) + +@Serializable +class RecommendedTestsResponse( + val recommendedTests: List +) + +@Serializable +class TestDefinitionResponse( + val testDefinitionId: String, + val testRunner: String, + val testPath: String, + val testName: String, + val tags: List, + val metadata: Map, +) + +private fun TestDefinitionResponse.toTestMethodInfo() = TestMethodInfo( + engine = testRunner, + className = testPath, + method = testName, + metadata = metadata, + tags = tags, +) \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/AddTestsPayload.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/AddTestsPayload.kt new file mode 100644 index 00000000..a67a6a89 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/AddTestsPayload.kt @@ -0,0 +1,26 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.sending + +import com.epam.drill.agent.common.transport.AgentMessage +import kotlinx.serialization.Serializable + +@Serializable +data class AddTestsPayload( + val groupId: String, + val sessionId: String, + val tests: List = emptyList(), +): AgentMessage() \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestDefinitionPayload.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestDefinitionPayload.kt new file mode 100644 index 00000000..00e68fa4 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestDefinitionPayload.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.sending + +import kotlinx.serialization.Serializable + +@Serializable +class TestDefinitionPayload( + val runner: String = "", + val path: String = "", + val testName: String = "", + val testParams: List = emptyList(), + val metadata: Map = emptyMap(), + val tags: List = emptyList(), +) \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestInfoSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestInfoSender.kt new file mode 100644 index 00000000..b3db15bc --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestInfoSender.kt @@ -0,0 +1,75 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.sending + +import com.epam.drill.agent.common.transport.AgentMessageDestination +import com.epam.drill.agent.common.transport.AgentMessageSender +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.DefaultParameterDefinitions +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.session.SessionController +import mu.KotlinLogging +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit + +interface TestInfoSender { + fun startSendingTests() + fun stopSendingTests() +} + +class IntervalTestInfoSender( + private val messageSender: AgentMessageSender, + private val intervalMs: Long = 1000, + private val collectTests: () -> List = { emptyList() } +) : TestInfoSender { + private val logger = KotlinLogging.logger {} + private val scheduledThreadPool = Executors.newSingleThreadScheduledExecutor() + + override fun startSendingTests() { + scheduledThreadPool.scheduleAtFixedRate( + { sendTests(collectTests()) }, + 0, + intervalMs, + TimeUnit.MILLISECONDS + ) + logger.debug { "Test sending job is started." } + } + + override fun stopSendingTests() { + scheduledThreadPool.shutdown() + if (!scheduledThreadPool.awaitTermination(1, TimeUnit.SECONDS)) { + logger.error("Failed to send some tests prior to shutdown") + scheduledThreadPool.shutdownNow(); + } + sendTests(collectTests()) + messageSender.shutdown() + logger.info { "Test sending job is stopped." } + } + + private fun sendTests(tests: List) { + if (tests.isEmpty()) return + logger.debug { "Sending ${tests.size} tests..." } + messageSender.send( + destination = AgentMessageDestination("POST", "tests-metadata"), + message = AddTestsPayload( + groupId = Configuration.parameters[DefaultParameterDefinitions.GROUP_ID], + sessionId = SessionController.getSessionId(), + tests = tests + ), + serializer = AddTestsPayload.serializer() + ) + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestLaunchPayload.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestLaunchPayload.kt new file mode 100644 index 00000000..ee2196ee --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/sending/TestLaunchPayload.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.sending + +import com.epam.drill.agent.test.execution.TestResult +import kotlinx.serialization.Serializable + +@Serializable +data class TestLaunchPayload( + val testLaunchId: String, + val testDefinitionId: String, + val result: TestResult, + val duration: Int?, + val details: TestDefinitionPayload, +) \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/Json.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/Json.kt new file mode 100644 index 00000000..bfdc44f8 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/Json.kt @@ -0,0 +1,23 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.serialization + +import kotlinx.serialization.json.* + +val json = Json { + encodeDefaults = true + ignoreUnknownKeys = true +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/PropertyDecoder.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/PropertyDecoder.kt new file mode 100644 index 00000000..2005423d --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/serialization/PropertyDecoder.kt @@ -0,0 +1,60 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.serialization + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.encoding.* +import kotlinx.serialization.internal.* + +class PropertyDecoder(val map: Map) : NamedValueDecoder() { + private var currentIndex = 0 + + override fun decodeCollectionSize(descriptor: SerialDescriptor): Int { + return decodeTaggedInt(nested("size")) + } + + override fun decodeTaggedValue(tag: String): Any { + return map.getValue(tag) + } + + override fun decodeTaggedBoolean(tag: String): Boolean { + return map.getValue(tag) as Boolean + } + + override fun decodeTaggedLong(tag: String): Long { + return map.getValue(tag) as Long + } + + override fun decodeTaggedEnum(tag: String, enumDescriptor: SerialDescriptor): Int { + return (map.getValue(tag) as Enum<*>).ordinal + } + + @Suppress("UNCHECKED_CAST") + override fun decodeSerializableValue(deserializer: DeserializationStrategy, previousValue: T?): T { + return map[this.currentTagOrNull] as? T ?: super.decodeSerializableValue(deserializer, previousValue) + } + + override fun decodeElementIndex(descriptor: SerialDescriptor): Int { + val tag = nested("size") + val size = if (map.containsKey(tag)) decodeTaggedInt(tag) else descriptor.elementsCount + while (currentIndex < size) { + val name = descriptor.getTag(currentIndex++) + if (map.keys.any { it.startsWith(name) }) return currentIndex - 1 + } + return CompositeDecoder.DECODE_DONE + } +} diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt new file mode 100644 index 00000000..0fc214c7 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt @@ -0,0 +1,118 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.session + +import com.benasher44.uuid.* +import com.epam.drill.agent.common.request.DrillInitialContext +import com.epam.drill.agent.common.request.DrillRequest +import com.epam.drill.agent.request.DrillRequestHolder +import com.epam.drill.agent.test.SESSION_ID_HEADER +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.DefaultParameterDefinitions +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.test.sending.IntervalTestInfoSender +import com.epam.drill.agent.test.sending.TestInfoSender +import com.epam.drill.agent.test.execution.TestController +import com.epam.drill.agent.test.execution.TestExecutionInfo +import com.epam.drill.agent.test.sending.TestDefinitionPayload +import com.epam.drill.agent.test.sending.TestLaunchPayload +import com.epam.drill.agent.test.transport.TestAgentMessageSender +import mu.KotlinLogging +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.util.zip.CRC32 + +actual object SessionController { + private val logger = KotlinLogging.logger {} + private val sessionSender: SessionSender = SessionSenderImpl( + messageSender = TestAgentMessageSender + ) + private val testInfoSender: TestInfoSender = IntervalTestInfoSender( + messageSender = TestAgentMessageSender, + collectTests = { TestController.getFinishedTests().toTestLaunchPayloads() } + ) + private lateinit var sessionId: String + + init { + if (isTestLaunchMetadataSendingEnabled()) + Runtime.getRuntime().addShutdownHook(Thread { testInfoSender.stopSendingTests() }) + } + + actual fun startSession() { + if (!isTestAgentEnabled()) { + logger.info { "Test agent is disabled. Test session will not be started." } + return + } + val customSessionId = Configuration.parameters[ParameterDefinitions.SESSION_ID] + sessionId = customSessionId ?: uuid4().toString() + DrillInitialContext.add(SESSION_ID_HEADER, sessionId) + DrillRequestHolder.store(DrillRequest(sessionId)) + logger.info { "Test session started: $sessionId" } + val builds = + takeIf { Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_APP_ID].isNotEmpty() }?.let { + SingleSessionBuildPayload( + appId = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_APP_ID], + buildVersion = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_BUILD_VERSION], + commitSha = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_COMMIT_SHA] + ) + }?.let { listOf(it) } ?: emptyList() + sessionSender.sendSession( + SessionPayload( + id = sessionId, + groupId = Configuration.parameters[DefaultParameterDefinitions.GROUP_ID], + testTaskId = Configuration.parameters[ParameterDefinitions.TEST_TASK_ID], + startedAt = System.currentTimeMillis().toIsoTimeFormat(), + builds = builds + ) + ) + if (isTestLaunchMetadataSendingEnabled()) + testInfoSender.startSendingTests() + } + + fun getSessionId(): String = sessionId + + private fun isTestAgentEnabled(): Boolean = Configuration.parameters[ParameterDefinitions.TEST_AGENT_ENABLED] + private fun isTestLaunchMetadataSendingEnabled(): Boolean = isTestAgentEnabled() && Configuration.parameters[ParameterDefinitions.TEST_LAUNCH_METADATA_SENDING_ENABLED] +} + +private fun List.toTestLaunchPayloads(): List = map { info -> + val testDefinitionPayload = TestDefinitionPayload( + runner = info.testMethod.engine, + path = info.testMethod.className, + testName = info.testMethod.method, + testParams = info.testMethod.methodParams.removeSurrounding("(", ")").split(",").filter { it.isNotEmpty() }, + metadata = info.testMethod.metadata, + tags = info.testMethod.tags + ) + TestLaunchPayload( + testLaunchId = info.testLaunchId, + testDefinitionId = hash(info.testMethod.signature), + result = info.result, + duration = info.finishedAt?.minus(info.startedAt ?: 0)?.toInt(), + details = testDefinitionPayload + ) +} + +private fun hash(signature: String): String = CRC32().let { + it.update(signature.toByteArray()) + java.lang.Long.toHexString(it.value) +} + +private fun Long.toIsoTimeFormat(): String = Instant.ofEpochMilli(this) + .let { ZonedDateTime.ofInstant(it, ZoneId.systemDefault()) } + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionPayload.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionPayload.kt new file mode 100644 index 00000000..8f142f84 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionPayload.kt @@ -0,0 +1,36 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.session + +import com.epam.drill.agent.common.transport.AgentMessage +import kotlinx.serialization.Serializable + +@Serializable +class SingleSessionBuildPayload( + val appId: String, + val instanceId: String? = null, + val buildVersion: String? = null, + val commitSha: String? = null +) + +@Serializable +class SessionPayload( + val id: String, + val groupId: String, + val testTaskId: String, + val startedAt: String, + val builds: List = emptyList() +): AgentMessage() \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionSender.kt new file mode 100644 index 00000000..f9948371 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionSender.kt @@ -0,0 +1,37 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.session + +import com.epam.drill.agent.common.transport.AgentMessage +import com.epam.drill.agent.common.transport.AgentMessageDestination +import com.epam.drill.agent.common.transport.AgentMessageSender + +interface SessionSender { + fun sendSession(payload: SessionPayload) +} + +class SessionSenderImpl( + private val messageSender: AgentMessageSender +) : SessionSender { + + override fun sendSession(payload: SessionPayload) { + messageSender.send( + AgentMessageDestination("PUT", "sessions"), + payload, + SessionPayload.serializer() + ) + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageReceiver.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageReceiver.kt new file mode 100644 index 00000000..388d23d0 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageReceiver.kt @@ -0,0 +1,32 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.transport + +import com.epam.drill.agent.common.transport.AgentMessageReceiver +import com.epam.drill.agent.transport.JsonAgentMessageDeserializer +import com.epam.drill.agent.transport.SimpleAgentMessageReceiver +import com.epam.drill.agent.transport.HttpAgentMessageDestinationMapper + +object TestAgentMessageReceiver : AgentMessageReceiver by messageReceiver() + +fun messageReceiver(): AgentMessageReceiver { + return SimpleAgentMessageReceiver( + agentTransport(), + JsonAgentMessageDeserializer(), + HttpAgentMessageDestinationMapper("metrics") + ) +} + diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageSender.kt new file mode 100644 index 00000000..67bfb79d --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/transport/TestAgentMessageSender.kt @@ -0,0 +1,69 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.transport + +import java.io.File +import io.aesy.datasize.ByteUnit +import io.aesy.datasize.DataSize +import mu.KotlinLogging +import com.epam.drill.agent.configuration.DefaultParameterDefinitions +import com.epam.drill.agent.transport.* +import com.epam.drill.agent.transport.http.HttpAgentMessageTransport +import com.epam.drill.agent.common.transport.AgentMessageSender +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions + +private val logger = KotlinLogging.logger {} +private const val QUEUE_DEFAULT_SIZE: Long = 512L * 1024 * 1024 + +object TestAgentMessageSender : AgentMessageSender by messageSender() + +fun agentTransport(): AgentMessageTransport = HttpAgentMessageTransport( + Configuration.parameters[ParameterDefinitions.API_URL], + Configuration.parameters[ParameterDefinitions.API_KEY] ?: "", + Configuration.parameters[ParameterDefinitions.SSL_TRUSTSTORE] + ?.let { resolvePath(it) } ?: "", + Configuration.parameters[ParameterDefinitions.SSL_TRUSTSTORE_PASSWORD] ?: "", + gzipCompression = false +) + +fun messageSender(): AgentMessageSender { + val transport = agentTransport() + val serializer = JsonAgentMessageSerializer() + val mapper = HttpAgentMessageDestinationMapper("data-ingest") + val queue = InMemoryAgentMessageQueue( + capacity = Configuration.parameters[ParameterDefinitions.MESSAGE_QUEUE_LIMIT].let(::parseBytes) + ) + return QueuedAgentMessageSender(transport, serializer, mapper, queue, + maxRetries = Configuration.parameters[ParameterDefinitions.MESSAGE_MAX_RETRIES] + ) +} + +private fun resolvePath(path: String) = File(path).run { + val installationDir = File(Configuration.parameters[DefaultParameterDefinitions.INSTALLATION_DIR] ?: "") + val resolved = this.takeIf(File::exists) + ?: this.takeUnless(File::isAbsolute)?.let(installationDir::resolve) + logger.trace { "resolvePath: Resolved $path to ${resolved?.absolutePath}" } + resolved?.absolutePath ?: path +} + +private fun parseBytes(value: String): Long = value.run { + val logError: (Throwable) -> Unit = { logger.warn(it) { "parseBytes: Exception while parsing value: $this" } } + this.runCatching(DataSize::parse) + .onFailure(logError) + .getOrDefault(DataSize.of(QUEUE_DEFAULT_SIZE, ByteUnit.BYTE)) + .toUnit(ByteUnit.BYTE).value.toLong() +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/HttpAgentMessageDestinationMapper.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/HttpAgentMessageDestinationMapper.kt index d1b06e30..f8e7522c 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/HttpAgentMessageDestinationMapper.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/HttpAgentMessageDestinationMapper.kt @@ -17,12 +17,10 @@ package com.epam.drill.agent.transport import com.epam.drill.agent.common.transport.AgentMessageDestination -class HttpAgentMessageDestinationMapper : AgentMessageDestinationMapper { - - private val dataIngestionPath = "data-ingest" +class HttpAgentMessageDestinationMapper(val path: String = "data-ingest") : AgentMessageDestinationMapper { override fun map(destination: AgentMessageDestination) = destination.copy( - target = if (destination.target.isEmpty()) dataIngestionPath else "${dataIngestionPath}/${destination.target}" + target = if (destination.target.isEmpty()) path else "${path}/${destination.target}" ) } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt index 02b37c5e..6b028fa7 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt @@ -64,6 +64,20 @@ import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber4Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber5Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber6Transformer +import com.epam.drill.agent.test.instrument.jmeter.JMeterTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4PrioritizingTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4Transformer +import com.epam.drill.agent.test.instrument.junit.JUnit5Transformer +import com.epam.drill.agent.test.instrument.junit.JUnitPlatformPrioritizingTransformer +import com.epam.drill.agent.test.instrument.selenium.SeleniumTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6Transformer +import com.epam.drill.agent.test.instrument.testng.TestNG7PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG7Transformer +import com.epam.drill.agent.test.session.SessionController object Agent { @@ -109,6 +123,19 @@ object Agent { UndertowWsServerTransformer, UndertowWsMessagesTransformer, CompatibilityTestsTransformer, + JUnit4Transformer, + JUnit5Transformer, + TestNG6Transformer, + TestNG7Transformer, + Cucumber4Transformer, + Cucumber5Transformer, + Cucumber6Transformer, + SeleniumTransformer, + JMeterTransformer, + JUnit4PrioritizingTransformer, + JUnitPlatformPrioritizingTransformer, + TestNG6PrioritizingTransformer, + TestNG7PrioritizingTransformer, ) @OptIn(ExperimentalNativeApi::class, ExperimentalForeignApi::class) @@ -142,6 +169,8 @@ object Agent { Configuration.initializeJvm() loadJvmModule("com.epam.drill.agent.test2code.Test2Code") JvmModuleMessageSender.sendAgentMetadata() + + SessionController.startSession() } fun agentOnVmDeath() { diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt new file mode 100644 index 00000000..6461ead5 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_AGENT_ENABLED +import com.epam.drill.agent.instrument.AbstractTransformerObject + +abstract class AbstractTestTransformerObject: AbstractTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[TEST_AGENT_ENABLED] +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt new file mode 100644 index 00000000..2bf426c8 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/AbstractCucumberTransformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_CUCUMBER_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +abstract class AbstractCucumberTransformer(): AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_CUCUMBER_ENABLED] +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt new file mode 100644 index 00000000..7cbbebaa --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +actual object Cucumber4Transformer: TransformerObject, AbstractCucumberTransformer() { + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == /*4.x.x*/"cucumber/runner/TestStep" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt new file mode 100644 index 00000000..d1015838 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +actual object Cucumber5Transformer: TransformerObject, AbstractCucumberTransformer() { + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "io/cucumber/core/runner/TestStep" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt new file mode 100644 index 00000000..cb1cfa6d --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.cucumber + +import com.epam.drill.agent.instrument.TransformerObject + +actual object Cucumber6Transformer: TransformerObject, AbstractCucumberTransformer() { + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "io/cucumber/core/runner/TestStep" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt new file mode 100644 index 00000000..c5e05183 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -0,0 +1,29 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.jmeter + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JMETER_ENABLED +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +actual object JMeterTransformer: TransformerObject, AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_JMETER_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt new file mode 100644 index 00000000..29cf2035 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/AbstractJUnitTransformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JUNIT_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +abstract class AbstractJUnitTransformer(): AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_JUNIT_ENABLED] +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt new file mode 100644 index 00000000..6d7dc12a --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.instrument.TransformerObject + +actual object JUnit4PrioritizingTransformer: TransformerObject, AbstractJUnitTransformer() { + override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/runners/JUnit4" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt new file mode 100644 index 00000000..ddc714c5 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +actual object JUnit4Transformer: TransformerObject, AbstractJUnitTransformer() { + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/runner/notification/RunNotifier" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt new file mode 100644 index 00000000..d22bebea --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -0,0 +1,24 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.instrument.TransformerObject + +actual object JUnit5Transformer: TransformerObject, AbstractJUnitTransformer() { + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/platform/engine/support/hierarchical/NodeTestTaskContext" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt new file mode 100644 index 00000000..5856def1 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.junit + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.instrument.TransformerObject + +actual object JUnitPlatformPrioritizingTransformer: TransformerObject, AbstractJUnitTransformer() { + override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/junit/platform/launcher/core/DefaultLauncher" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt new file mode 100644 index 00000000..b884c074 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -0,0 +1,29 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.selenium + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SELENIUM_ENABLED +import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +actual object SeleniumTransformer: TransformerObject, AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_SELENIUM_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/openqa/selenium/remote/RemoteWebDriver" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt new file mode 100644 index 00000000..908681f4 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt @@ -0,0 +1,27 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.configuration.ParameterDefinitions + +abstract class AbstractTestNGPrioritizingTransformer(): AbstractTestNGTransformer() { + override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return interfaces.any { it == "org/testng/IMethodSelector" } + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt new file mode 100644 index 00000000..cd448e7d --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt @@ -0,0 +1,28 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.configuration.Configuration +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_TESTNG_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject + +abstract class AbstractTestNGTransformer(): AbstractTestTransformerObject() { + override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_TESTNG_ENABLED] + + override fun permit(className: String, superName: String?, interfaces: Array): Boolean { + return className == "org/testng/TestRunner" + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt new file mode 100644 index 00000000..6fbb7713 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +actual object TestNG6PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt new file mode 100644 index 00000000..2d41ad5f --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +actual object TestNG6Transformer: TransformerObject, AbstractTestNGTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt new file mode 100644 index 00000000..9e651b7a --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +actual object TestNG7PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt new file mode 100644 index 00000000..70d59f56 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.instrument.testng + +import com.epam.drill.agent.instrument.TransformerObject + +actual object TestNG7Transformer: TransformerObject, AbstractTestNGTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt new file mode 100644 index 00000000..852b934e --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt @@ -0,0 +1,26 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.test.session + +import com.epam.drill.agent.jvmapi.callObjectVoidMethod +import com.epam.drill.agent.jvmapi.callObjectVoidMethodWithString + +actual object SessionController { + + actual fun startSession(): Unit = + callObjectVoidMethod(SessionController::class, SessionController::startSession) + +} From d1738b779553cd4a73706ca0c693f79eff6e6497 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 30 Dec 2025 13:53:58 +0100 Subject: [PATCH 02/14] fix: clear context before removing because of context in inherited threads EPMDJ-11181 --- .../agent/test2code/coverage/ProbesProvider.kt | 14 +++++++++----- .../test2code/coverage/ThreadCoverageRecorder.kt | 14 ++++++++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt index 29122602..8342b0fc 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt @@ -28,11 +28,15 @@ const val TEST_CONTEXT_NONE = "TEST_CONTEXT_NONE" const val SESSION_CONTEXT_AMBIENT = "GLOBAL" data class ContextKey( - private val _sessionId: SessionId? = null, // TODO there must be a better way to avoid nullability and assign defaults - private val _testId: TestId? = null + var sessionId: SessionId, + var testId: TestId ) { - val sessionId: SessionId = _sessionId ?: SESSION_CONTEXT_NONE - val testId: TestId = _testId ?: TEST_CONTEXT_NONE + fun clear() { + sessionId = SESSION_CONTEXT_NONE + testId = TEST_CONTEXT_NONE + } + fun isSessionEmpty() = sessionId == SESSION_CONTEXT_NONE + fun isSessionGlobal() = sessionId == SESSION_CONTEXT_AMBIENT } -internal val CONTEXT_AMBIENT = ContextKey(SESSION_CONTEXT_AMBIENT) \ No newline at end of file +internal val CONTEXT_AMBIENT = ContextKey(SESSION_CONTEXT_AMBIENT, TEST_CONTEXT_NONE) \ No newline at end of file diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ThreadCoverageRecorder.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ThreadCoverageRecorder.kt index 85e982b7..28be648c 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ThreadCoverageRecorder.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ThreadCoverageRecorder.kt @@ -28,8 +28,8 @@ class ThreadCoverageRecorder( private val execData: ThreadLocal = TransmittableThreadLocal() override fun startRecording(sessionId: String?, testId: String?) { - stopRecording(context.get()?.sessionId, context.get()?.testId) - val ctx = ContextKey(sessionId, testId) + stopRecording(context.get()?.sessionId ?: SESSION_CONTEXT_NONE, context.get()?.testId ?: TEST_CONTEXT_NONE) + val ctx = ContextKey(sessionId ?: SESSION_CONTEXT_NONE, testId ?: TEST_CONTEXT_NONE) context.set(ctx) execData.set(execDataPool.getOrPut( ctx, @@ -39,9 +39,11 @@ class ThreadCoverageRecorder( } override fun stopRecording(sessionId: String?, testId: String?) { - if (execData.get() == null) return - execDataPool.release(ContextKey(sessionId, testId), execData.get() ?: ExecData()) - execData.remove() + execData.get()?.let { data -> + execDataPool.release(ContextKey(sessionId ?: SESSION_CONTEXT_NONE, testId ?: TEST_CONTEXT_NONE), data) + execData.remove() + } + context.get()?.clear() context.remove() logger.trace { "Test recording stopped (sessionId = $sessionId, testId = $testId, threadId = ${Thread.currentThread().id})." } } @@ -58,7 +60,7 @@ class ThreadCoverageRecorder( } override fun getContext(): ContextCoverage? { - return context.get()?.let { ctx -> execData.get()?.let { ContextCoverage(ctx, it) } } + return context.get()?.takeIf { !it.isSessionEmpty() }?.let { ctx -> execData.get()?.let { ContextCoverage(ctx, it) } } } } From ee1843c4352298849f4b7eba8655ccf998d44b30 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 30 Dec 2025 16:14:15 +0100 Subject: [PATCH 03/14] fix: fix NPE error in SeleniumTransformer EPMDJ-11181 --- .../configuration/ParameterDefinitions.kt | 2 +- .../instrument/selenium/SeleniumTransformer.kt | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 8879b1f7..63293d7e 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -51,7 +51,7 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val PROXY_ADDRESS = AgentParameterDefinition.forString(name = "browserProxyAddress", defaultValue = "").register() val DEVTOOLS_PROXY_ADDRESS = AgentParameterDefinition.forString( name = "devToolsProxyAddress", - defaultValue = "http://localhost:9222",//TODO + defaultValue = "http://localhost:9222", parser = { it.trim().takeIf(String::isBlank) ?: it.takeIf(URL_SCHEME_REGEX::matches) ?: "http://$it"} ).register() val DEVTOOLS_REPLACE_LOCALHOST = AgentParameterDefinition.forString(name = "devtoolsAddressReplaceLocalhost", defaultValue = "").register() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt index 56195b92..94552044 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -22,6 +22,7 @@ import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTR import com.epam.drill.agent.instrument.TransformerObject import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject import javassist.* +import mu.KLogger import java.io.* import mu.KotlinLogging import java.security.ProtectionDomain @@ -39,18 +40,21 @@ actual object SeleniumTransformer : TransformerObject, AbstractTestTransformerOb private const val EXTENSION_NAME = "header-transmitter.xpi" private val FirefoxDriver = "org.openqa.selenium.firefox.FirefoxDriver" - private val extensionFile: String + private var extensionFile: String? = null internal const val addDrillCookiesMethod = "addDrillCookies" private const val isFirefoxBrowser = "isFirefoxBrowser" - - override val logger = KotlinLogging.logger {} + override val logger: KLogger = KotlinLogging.logger {} init { val extension = this::class.java.getResource("/$EXTENSION_NAME") - File(System.getProperty("java.io.tmpdir")).resolve(EXTENSION_NAME).apply { - extensionFile = absolutePath - writeBytes(extension.readBytes()) + if (extension != null) { + File(System.getProperty("java.io.tmpdir")).resolve(EXTENSION_NAME).apply { + extensionFile = absolutePath + writeBytes(extension.readBytes()) + } + } else { + logger.warn { "Failed to load extension file: $EXTENSION_NAME" } } } @@ -193,7 +197,7 @@ actual object SeleniumTransformer : TransformerObject, AbstractTestTransformerOb try { if (this instanceof $FirefoxDriver) { java.util.HashMap hashMapq = new java.util.HashMap(); - hashMapq.put("path", "${extensionFile.replace("\\", "\\\\")}"); + hashMapq.put("path", "${extensionFile?.replace("\\", "\\\\")}"); hashMapq.put("temporary", Boolean.TRUE); this.execute("installExtension", hashMapq).getValue(); } From e0834d870bff632ecadbab37a31b25879b05446b Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 27 Jan 2026 13:55:05 +0100 Subject: [PATCH 04/14] build: update sharedLibsRef to point to feature/united-java-agent --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9be62a1f..45634916 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 -sharedLibsRef = main +sharedLibsRef = feature/united-java-agent sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false From cc34a406ee6bf0c054881e3042601377c8fab23c Mon Sep 17 00:00:00 2001 From: iryabov Date: Thu, 19 Feb 2026 15:09:04 +0100 Subject: [PATCH 05/14] feat: change ASM library dependency --- java-agent/build.gradle.kts | 1 + java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/java-agent/build.gradle.kts b/java-agent/build.gradle.kts index 79f47be4..099441dd 100644 --- a/java-agent/build.gradle.kts +++ b/java-agent/build.gradle.kts @@ -115,6 +115,7 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-cli:${kotlinxCliVersion}") + implementation("org.ow2.asm:asm:9.8") implementation(project(":common")) implementation(project(":agent-transport")) implementation(project(":agent-instrumentation")) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt index 597cef82..2c4e0ef2 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt @@ -54,7 +54,7 @@ import com.epam.drill.agent.module.JvmModuleLoader import com.epam.drill.agent.test2code.Test2Code import com.epam.drill.agent.test2code.configuration.Test2CodeParameterDefinitions import com.epam.drill.agent.transport.JvmModuleMessageSender -import jdk.internal.org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassReader import mu.KotlinLogging import java.lang.instrument.ClassFileTransformer import java.lang.instrument.Instrumentation From dc8d1d890c818dd4ec1fdcbe98406366fa217785 Mon Sep 17 00:00:00 2001 From: iryabov Date: Fri, 20 Feb 2026 11:15:07 +0100 Subject: [PATCH 06/14] feat: implement checkAndTransform method for class transformation --- gradle.properties | 1 + java-agent/build.gradle.kts | 4 ++-- .../instrument/ApplicationClassTransformer.kt | 10 ++++++++++ .../epam/drill/agent/jvmti/ClassFileLoadHook.kt | 17 ++++------------- settings.gradle.kts | 2 -- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/gradle.properties b/gradle.properties index 9be62a1f..a779e0e0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,7 @@ microutilsLoggingVersion = 2.1.23 apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 +asmVersion = 9.8 sharedLibsRef = main sharedLibsLocalPath = lib-jvm-shared diff --git a/java-agent/build.gradle.kts b/java-agent/build.gradle.kts index 099441dd..94775e71 100644 --- a/java-agent/build.gradle.kts +++ b/java-agent/build.gradle.kts @@ -37,6 +37,7 @@ val nativeAgentHookEnabled: String by parent!!.extra val macosLd64: String by parent!!.extra val bytebuddyVersion: String by parent!!.extra val kotlinxCliVersion: String by parent!!.extra +val asmVersion: String by parent!!.extra repositories { mavenCentral() @@ -115,7 +116,7 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:${kotlinxSerializationVersion}") implementation("org.jetbrains.kotlinx:kotlinx-cli:${kotlinxCliVersion}") - implementation("org.ow2.asm:asm:9.8") + implementation("org.ow2.asm:asm:${asmVersion}") implementation(project(":common")) implementation(project(":agent-transport")) implementation(project(":agent-instrumentation")) @@ -130,7 +131,6 @@ kotlin { implementation("com.benasher44:uuid:$uuidVersion") implementation("io.ktor:ktor-utils:$ktorVersion") implementation(project(":jvmapi")) - implementation(project(":knasm")) implementation(project(":konform")) implementation(project(":agent-instrumentation")) if (nativeAgentHookEnabled == "true") diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index dfae73bf..03f6652c 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -45,4 +45,14 @@ actual object ApplicationClassTransformer : TransformerObject, AbstractTransform .fold(classFileBuffer) { bytes, plugin -> plugin.instrument(className, bytes) ?: bytes } + + override fun checkAndTransform( + className: String, + classFileBuffer: ByteArray, + loader: Any?, + protectionDomain: Any? + ): ByteArray { + if (!permit(className, null, emptyArray())) return classFileBuffer + return transform(className, classFileBuffer, loader, protectionDomain) + } } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt index 3db54803..116b5ae9 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt @@ -24,7 +24,6 @@ import com.epam.drill.agent.jvmapi.gen.jobject import io.ktor.utils.io.bits.* import kotlinx.cinterop.* import mu.KotlinLogging -import org.objectweb.asm.ClassReader import kotlin.concurrent.AtomicInt import kotlinx.cinterop.ExperimentalForeignApi @@ -54,26 +53,18 @@ object ClassFileLoadHook { .takeIf { it.any() } ?: return - val (oldClassBytes, reader) = runCatching { + val oldClassBytes = runCatching { val classBytes = ByteArray(classDataLen).apply { Memory.of(kClassData, classDataLen).loadByteArray(0, this) } - classBytes to ClassReader(classBytes) + classBytes }.onFailure { logger.error(it) { "Can't read class: $kClassName" } }.getOrNull() ?: return - val permittedTransformers = precheckedTransformers.filter { - it.permit( - kClassName, - reader.superName, - reader.interfaces - ) - } - - val newClassBytes = permittedTransformers.fold(oldClassBytes) { bytes, transformer -> + val newClassBytes = precheckedTransformers.fold(oldClassBytes) { bytes, transformer -> runCatching { - transformer.transform(kClassName, bytes, loader, protectionDomain) + transformer.checkAndTransform(kClassName, bytes, loader, protectionDomain) }.onFailure { logger.warn(it) { "Can't transform class: $kClassName with ${transformer::class.simpleName}" } }.getOrNull() diff --git a/settings.gradle.kts b/settings.gradle.kts index 1bee3210..da3085cc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,14 +39,12 @@ includeSharedLib("agent-config") includeSharedLib("agent-transport") includeSharedLib("agent-instrumentation") includeSharedLib("jvmapi") -includeSharedLib("knasm") includeSharedLib("konform") includeSharedLib("transmittable-thread-local") // FYI: Interceptor not patched for macOS ARM64 architecture. //includeSharedLib("interceptor-hook") //includeSharedLib("interceptor-http") includeSharedLib("interceptor-stub") -includeSharedLib("dsm-annotations") includeSharedLib("test2code-common") include("test2code-jacoco") include("test2code") From 60d0945ee1205561bd447363f24e43f80b3ee93d Mon Sep 17 00:00:00 2001 From: iryabov Date: Mon, 23 Feb 2026 13:34:48 +0100 Subject: [PATCH 07/14] refactor: add CompositeTransformer to combine all Java transformers into one --- .../instrument/ApplicationClassTransformer.kt | 2 +- .../agent/instrument/CompositeTransformer.kt | 18 ++++ .../agent/instrument/TransformerRegistrar.kt | 20 +++++ .../clients/ApacheHttpClientTransformer.kt | 4 +- .../clients/JavaHttpClientTransformer.kt | 4 +- .../clients/OkHttp3ClientTransformer.kt | 4 +- .../clients/SpringWebClientTransformer.kt | 4 +- .../jetty/Jetty10WsMessagesTransformer.kt | 4 +- .../jetty/Jetty11WsMessagesTransformer.kt | 4 +- .../jetty/Jetty9WsMessagesTransformer.kt | 4 +- .../jetty/JettyHttpServerTransformer.kt | 4 +- .../jetty/JettyWsClientTransformer.kt | 4 +- .../jetty/JettyWsServerTransformer.kt | 4 +- .../netty/NettyHttpServerTransformer.kt | 4 +- .../netty/NettyWsClientTransformer.kt | 4 +- .../netty/NettyWsMessagesTransformer.kt | 4 +- .../netty/NettyWsServerTransformer.kt | 4 +- .../instrument/servers/CadenceTransformer.kt | 4 +- .../servers/CompatibilityTestsTransformer.kt | 4 +- .../instrument/servers/KafkaTransformer.kt | 4 +- .../instrument/servers/ReactorTransformer.kt | 4 +- .../servers/SSLEngineTransformer.kt | 4 +- .../instrument/servers/TTLTransformer.kt | 4 +- .../tomcat/TomcatHttpServerTransformer.kt | 4 +- .../tomcat/TomcatWsClientTransformer.kt | 4 +- .../tomcat/TomcatWsMessagesTransformer.kt | 4 +- .../tomcat/TomcatWsServerTransformer.kt | 4 +- .../undertow/UndertowHttpServerTransformer.kt | 4 +- .../undertow/UndertowWsClientTransformer.kt | 4 +- .../undertow/UndertowWsMessagesTransformer.kt | 4 +- .../undertow/UndertowWsServerTransformer.kt | 4 +- .../kotlin/com/epam/drill/agent/Agent.kt | 65 ++------------ .../instrument/ApplicationClassTransformer.kt | 4 +- .../agent/instrument/CompositeTransformer.kt | 63 +++++++++++++ .../agent/instrument/TransformerRegistrar.kt | 88 +++++++++++++++++++ .../clients/ApacheHttpClientTransformer.kt | 4 +- .../clients/JavaHttpClientTransformer.kt | 4 +- .../clients/OkHttp3ClientTransformer.kt | 4 +- .../clients/SpringWebClientTransformer.kt | 2 +- .../jetty/Jetty10WsMessagesTransformer.kt | 2 +- .../jetty/Jetty11WsMessagesTransformer.kt | 2 +- .../jetty/Jetty9WsMessagesTransformer.kt | 2 +- .../jetty/JettyHttpServerTransformer.kt | 2 +- .../jetty/JettyWsClientTransformer.kt | 2 +- .../jetty/JettyWsServerTransformer.kt | 2 +- .../netty/NettyHttpServerTransformer.kt | 4 +- .../netty/NettyWsClientTransformer.kt | 4 +- .../netty/NettyWsMessagesTransformer.kt | 4 +- .../netty/NettyWsServerTransformer.kt | 4 +- .../reactor/transformers/FluxTransformer.kt | 4 +- .../reactor/transformers/MonoTransformer.kt | 4 +- .../transformers/ParallelFluxTransformer.kt | 4 +- .../transformers/SchedulersTransformer.kt | 4 +- .../instrument/servers/CadenceTransformer.kt | 4 +- .../servers/CompatibilityTestsTransformer.kt | 2 +- .../instrument/servers/KafkaTransformer.kt | 4 +- .../instrument/servers/ReactorTransformer.kt | 4 +- .../servers/SSLEngineTransformer.kt | 4 +- .../instrument/servers/TTLTransformer.kt | 4 +- .../tomcat/TomcatHttpServerTransformer.kt | 4 +- .../tomcat/TomcatWsClientTransformer.kt | 4 +- .../tomcat/TomcatWsMessagesTransformer.kt | 4 +- .../tomcat/TomcatWsServerTransformer.kt | 4 +- .../undertow/UndertowHttpServerTransformer.kt | 2 +- .../undertow/UndertowWsClientTransformer.kt | 2 +- .../undertow/UndertowWsMessagesTransformer.kt | 2 +- .../undertow/UndertowWsServerTransformer.kt | 2 +- .../kotlin/com/epam/drill/agent/Agent.kt | 61 ------------- .../instrument/AbstractTransformerObject.kt | 10 ++- .../instrument/ApplicationClassTransformer.kt | 24 ++--- .../agent/instrument/CompositeTransformer.kt | 27 ++++++ .../agent/instrument/TransformerRegistrar.kt | 88 +++++++++++++++++++ .../clients/ApacheHttpClientTransformer.kt | 4 +- .../clients/JavaHttpClientTransformer.kt | 4 +- .../clients/OkHttp3ClientTransformer.kt | 4 +- .../clients/SpringWebClientTransformer.kt | 6 +- .../jetty/Jetty10WsMessagesTransformer.kt | 9 +- .../jetty/Jetty11WsMessagesTransformer.kt | 5 +- .../jetty/Jetty9WsMessagesTransformer.kt | 9 +- .../jetty/JettyHttpServerTransformer.kt | 12 ++- .../jetty/JettyWsClientTransformer.kt | 5 +- .../jetty/JettyWsServerTransformer.kt | 5 +- .../netty/NettyHttpServerTransformer.kt | 11 ++- .../netty/NettyWsClientTransformer.kt | 5 +- .../netty/NettyWsMessagesTransformer.kt | 5 +- .../netty/NettyWsServerTransformer.kt | 5 +- .../instrument/servers/CadenceTransformer.kt | 12 +-- .../servers/CompatibilityTestsTransformer.kt | 7 +- .../instrument/servers/KafkaTransformer.kt | 6 +- .../instrument/servers/ReactorTransformer.kt | 5 +- .../servers/SSLEngineTransformer.kt | 11 +-- .../instrument/servers/TTLTransformer.kt | 19 +--- .../tomcat/TomcatHttpServerTransformer.kt | 12 +-- .../tomcat/TomcatWsClientTransformer.kt | 5 +- .../tomcat/TomcatWsMessagesTransformer.kt | 5 +- .../tomcat/TomcatWsServerTransformer.kt | 5 +- .../undertow/UndertowHttpServerTransformer.kt | 13 +-- .../undertow/UndertowWsClientTransformer.kt | 5 +- .../undertow/UndertowWsMessagesTransformer.kt | 5 +- .../undertow/UndertowWsServerTransformer.kt | 5 +- .../drill/agent/jvmti/ClassFileLoadHook.kt | 43 ++------- 101 files changed, 530 insertions(+), 403 deletions(-) create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt create mode 100644 java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt create mode 100644 java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt create mode 100644 java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index 6287331d..43abdbb5 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -15,4 +15,4 @@ */ package com.epam.drill.agent.instrument -expect object ApplicationClassTransformer: TransformerObject \ No newline at end of file +expect object ApplicationClassTransformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt new file mode 100644 index 00000000..a2461b2d --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt @@ -0,0 +1,18 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +expect object CompositeTransformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt new file mode 100644 index 00000000..f6c5386a --- /dev/null +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt @@ -0,0 +1,20 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +expect object TransformerRegistrar { + val enabledTransformers: List +} \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt index 142051c1..8894a73a 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.clients -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object ApacheHttpClientTransformer : TransformerObject +expect object ApacheHttpClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt index 0965fd14..a9dc4f72 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.clients -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JavaHttpClientTransformer : TransformerObject +expect object JavaHttpClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt index ded1d282..a97c65e0 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.clients -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object OkHttp3ClientTransformer : TransformerObject +expect object OkHttp3ClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt index 19abc448..1f8c4a8e 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.clients -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object SpringWebClientTransformer : TransformerObject \ No newline at end of file +expect object SpringWebClientTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt index 8cf258e4..a6cf17c4 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Jetty10WsMessagesTransformer : TransformerObject +expect object Jetty10WsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt index 6a24cbcd..aaadb0f8 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Jetty11WsMessagesTransformer : TransformerObject +expect object Jetty11WsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt index 46288850..8aac8b42 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Jetty9WsMessagesTransformer : TransformerObject +expect object Jetty9WsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt index 5b2d8d43..3ab39e8b 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JettyHttpServerTransformer : TransformerObject +expect object JettyHttpServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt index 8f988ad4..a52da7d3 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JettyWsClientTransformer : TransformerObject +expect object JettyWsClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt index 9ae0d7c3..b25b1274 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JettyWsServerTransformer : TransformerObject +expect object JettyWsServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt index e8d6279c..1bdb624c 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.netty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object NettyHttpServerTransformer : TransformerObject +expect object NettyHttpServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt index c07e7bee..5871380d 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.netty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object NettyWsClientTransformer : TransformerObject +expect object NettyWsClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt index 5b2233ce..b0339058 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.netty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object NettyWsMessagesTransformer : TransformerObject +expect object NettyWsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt index 2e1f79eb..72437f59 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.netty -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object NettyWsServerTransformer : TransformerObject +expect object NettyWsServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt index 677e9bf0..d9239948 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object CadenceTransformer : TransformerObject +expect object CadenceTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt index 0404fecb..89a03d9c 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object CompatibilityTestsTransformer : TransformerObject \ No newline at end of file +expect object CompatibilityTestsTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt index 158a89d4..2a203b5e 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object KafkaTransformer : TransformerObject +expect object KafkaTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt index ad978792..098d3d76 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object ReactorTransformer: TransformerObject \ No newline at end of file +expect object ReactorTransformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt index 83e3130a..2d211e6c 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object SSLEngineTransformer : TransformerObject +expect object SSLEngineTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt index a2ea9d42..af5d96a6 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.servers -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TTLTransformer : TransformerObject +expect object TTLTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt index cb970ac2..4b61437c 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.tomcat -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TomcatHttpServerTransformer : TransformerObject +expect object TomcatHttpServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt index b3cfa1ab..23caee70 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.tomcat -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TomcatWsClientTransformer : TransformerObject +expect object TomcatWsClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt index b92a7c68..89ba98f5 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.tomcat -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TomcatWsMessagesTransformer : TransformerObject +expect object TomcatWsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt index cf2a7fc6..2be31a98 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.tomcat -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TomcatWsServerTransformer : TransformerObject +expect object TomcatWsServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt index 06cd6be6..82fcf924 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.undertow -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object UndertowHttpServerTransformer : TransformerObject +expect object UndertowHttpServerTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt index a9e5cf80..2ee71b92 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.undertow -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object UndertowWsClientTransformer : TransformerObject +expect object UndertowWsClientTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt index 5bd574b1..fc6a424e 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.undertow -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object UndertowWsMessagesTransformer : TransformerObject +expect object UndertowWsMessagesTransformer : Transformer diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt index 8c530768..83519a44 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.instrument.undertow -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object UndertowWsServerTransformer : TransformerObject +expect object UndertowWsServerTransformer : Transformer diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt index 2c4e0ef2..f7e47af1 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt @@ -21,6 +21,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.DefaultParameterDefinitions import com.epam.drill.agent.configuration.ParameterDefinitions import com.epam.drill.agent.instrument.ApplicationClassTransformer +import com.epam.drill.agent.instrument.CompositeTransformer import com.epam.drill.agent.instrument.TransformerRegistrar import com.epam.drill.agent.instrument.clients.ApacheHttpClientTransformer import com.epam.drill.agent.instrument.clients.JavaHttpClientTransformer @@ -73,37 +74,6 @@ private val logo = """ private const val DRILL_PACKAGE = "com/epam/drill/agent" private val logger = KotlinLogging.logger("com.epam.drill.agent.Agent") -private val transformers = setOf( - ApplicationClassTransformer, - TomcatHttpServerTransformer, - JettyHttpServerTransformer, - UndertowHttpServerTransformer, - NettyHttpServerTransformer, - JavaHttpClientTransformer, - ApacheHttpClientTransformer, - OkHttp3ClientTransformer, - SpringWebClientTransformer, - KafkaTransformer, - CadenceTransformer, - TTLTransformer, - ReactorTransformer, -// SSLEngineTransformer, TODO does not work in JVM due to too early initialization of HeadersRetriever - JettyWsClientTransformer, - JettyWsServerTransformer, - Jetty9WsMessagesTransformer, - Jetty10WsMessagesTransformer, - Jetty11WsMessagesTransformer, - NettyWsClientTransformer, - NettyWsServerTransformer, - NettyWsMessagesTransformer, - TomcatWsClientTransformer, - TomcatWsServerTransformer, - TomcatWsMessagesTransformer, - UndertowWsClientTransformer, - UndertowWsServerTransformer, - UndertowWsMessagesTransformer, - CompatibilityTestsTransformer, -) fun premain(agentArgs: String?, inst: Instrumentation) { try { @@ -112,7 +82,6 @@ fun premain(agentArgs: String?, inst: Instrumentation) { Configuration.initializeNative(agentArgs ?: "") updateJvmLoggingConfiguration() validateConfiguration() - TransformerRegistrar.initialize(transformers) inst.addTransformer(DrillClassFileTransformer, true) JvmModuleMessageSender.sendAgentMetadata() JvmModuleLoader.loadJvmModule(Test2Code::class.java.name).load() @@ -187,35 +156,19 @@ object DrillClassFileTransformer : ClassFileTransformer { ): ByteArray? { val kClassName = className ?: return null val kClassBytes = classfileBuffer ?: return null - val precheckedTransformers = TransformerRegistrar.enabledTransformers - .filterNot { kClassName.startsWith(DRILL_PACKAGE) } - .filter { it.precheck(kClassName, loader, protectionDomain) } - .takeIf { it.any() } - ?: return null - val (oldClassBytes, reader) = runCatching { - kClassBytes to ClassReader(kClassBytes) + if (kClassName.startsWith(DRILL_PACKAGE)) return null + if (!CompositeTransformer.precheck(kClassName, loader, protectionDomain)) return null + val oldClassBytes = runCatching { + kClassBytes }.onFailure { logger.error(it) { "Can't read class: $kClassName" } }.getOrNull() ?: return null - val permittedTransformers = precheckedTransformers.filter { - it.permit( - kClassName, - reader.superName, - reader.interfaces - ) - } - val newClassBytes = permittedTransformers.fold(oldClassBytes) { bytes, transformer -> - runCatching { - transformer.transform(kClassName, bytes, loader, protectionDomain) + val newClassBytes = runCatching { + CompositeTransformer.transform(kClassName, oldClassBytes, loader, protectionDomain) }.onFailure { - logger.warn(it) { "Can't transform class: $kClassName with ${transformer::class.simpleName}" } - }.getOrNull() - ?.takeIf { it !== bytes } - ?.also { - logger.debug { "$kClassName was transformed by ${transformer::class.simpleName}" } - } ?: bytes - } + logger.warn(it) { "Can't transform class: $kClassName" } + }.getOrNull() ?: return null return if (newClassBytes !== oldClassBytes) newClassBytes else null } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index 1fdd4de9..c6f55776 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -24,7 +24,7 @@ import mu.KLogger import mu.KotlinLogging actual object ApplicationClassTransformer : - TransformerObject, + Transformer, AbstractTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider { @@ -35,7 +35,7 @@ actual object ApplicationClassTransformer : className: String, superName: String?, interfaces: Array - ): Boolean = ClassSource(className, superName ?: "") + ): Boolean = ClassSource(className, superName) .prefixMatches(Configuration.agentMetadata.packagesPrefixes) override fun transform( diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt new file mode 100644 index 00000000..61239861 --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt @@ -0,0 +1,63 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +import mu.KotlinLogging +import org.objectweb.asm.ClassReader + +actual object CompositeTransformer : Transformer { + private val logger = KotlinLogging.logger {} + private val transformers = TransformerRegistrar + + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean { + return transformers.enabledTransformers.any { it.precheck(className, loader, protectionDomain) } + } + + override fun transform( + className: String, + classFileBuffer: ByteArray, + loader: Any?, + protectionDomain: Any? + ): ByteArray { + val reader = runCatching { ClassReader(classFileBuffer) } + .onFailure { logger.warn(it) { "Can't read class: $classFileBuffer" } } + .getOrNull() ?: return classFileBuffer + val enabledTransformers = runCatching { transformers.enabledTransformers }.onFailure { + logger.warn(it) { "Can't get enabled transformers for class: $className" } + }.getOrNull() ?: return classFileBuffer + return enabledTransformers.fold(classFileBuffer) { bytes, transformer -> + runCatching { + when { + transformer is TransformerObject && !transformer.permit( + className, + reader.superName, + reader.interfaces + ) -> bytes + + else -> transformer.transform(className, bytes, loader, protectionDomain) + } + }.onFailure { + logger.warn(it) { "Can't transform class: $className with ${transformer::class.simpleName}" } + }.getOrNull()?.takeIf { it !== bytes }?.also { + logger.debug { "$className was transformed by ${transformer::class.simpleName}" } + } ?: bytes + } + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt new file mode 100644 index 00000000..983cfe1f --- /dev/null +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt @@ -0,0 +1,88 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +import mu.KotlinLogging +import com.epam.drill.agent.instrument.clients.ApacheHttpClientTransformer +import com.epam.drill.agent.instrument.clients.JavaHttpClientTransformer +import com.epam.drill.agent.instrument.clients.OkHttp3ClientTransformer +import com.epam.drill.agent.instrument.clients.SpringWebClientTransformer +import com.epam.drill.agent.instrument.jetty.Jetty10WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.Jetty11WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.Jetty9WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.JettyHttpServerTransformer +import com.epam.drill.agent.instrument.jetty.JettyWsClientTransformer +import com.epam.drill.agent.instrument.jetty.JettyWsServerTransformer +import com.epam.drill.agent.instrument.netty.NettyHttpServerTransformer +import com.epam.drill.agent.instrument.netty.NettyWsClientTransformer +import com.epam.drill.agent.instrument.netty.NettyWsMessagesTransformer +import com.epam.drill.agent.instrument.netty.NettyWsServerTransformer +import com.epam.drill.agent.instrument.servers.CadenceTransformer +import com.epam.drill.agent.instrument.servers.CompatibilityTestsTransformer +import com.epam.drill.agent.instrument.servers.KafkaTransformer +import com.epam.drill.agent.instrument.servers.ReactorTransformer +import com.epam.drill.agent.instrument.servers.SSLEngineTransformer +import com.epam.drill.agent.instrument.servers.TTLTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatHttpServerTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsClientTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsMessagesTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsServerTransformer +import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer + +actual object TransformerRegistrar { + private val logger = KotlinLogging.logger {} + private val transformers: Set = setOf( + ApplicationClassTransformer, + TomcatHttpServerTransformer, + JettyHttpServerTransformer, + UndertowHttpServerTransformer, + NettyHttpServerTransformer, + JavaHttpClientTransformer, + ApacheHttpClientTransformer, + OkHttp3ClientTransformer, + SpringWebClientTransformer, + KafkaTransformer, + CadenceTransformer, + TTLTransformer, + ReactorTransformer, + SSLEngineTransformer, + JettyWsClientTransformer, + JettyWsServerTransformer, + Jetty9WsMessagesTransformer, + Jetty10WsMessagesTransformer, + Jetty11WsMessagesTransformer, + NettyWsClientTransformer, + NettyWsServerTransformer, + NettyWsMessagesTransformer, + TomcatWsClientTransformer, + TomcatWsServerTransformer, + TomcatWsMessagesTransformer, + UndertowWsClientTransformer, + UndertowWsServerTransformer, + UndertowWsMessagesTransformer, + CompatibilityTestsTransformer, + ) + actual val enabledTransformers: List by lazy { + transformers.filter { transformer -> + transformer.enabled() + }.also { + logger.info { "Enabled ${it.size} jvm transformers" } + } + } +} \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt index c6f18222..d575a7a5 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object ApacheHttpClientTransformer : - TransformerObject, + Transformer, ApacheHttpClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt index 3a4a845a..c083293f 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object JavaHttpClientTransformer : - TransformerObject, + Transformer, JavaHttpClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt index 8cbace7b..c1f9e395 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object OkHttp3ClientTransformer : - TransformerObject, + Transformer, OkHttp3ClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt index 918aba52..0eb89728 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object SpringWebClientTransformer: - TransformerObject, + Transformer, SpringWebClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt index 9dca362a..39772b47 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object Jetty10WsMessagesTransformer : - TransformerObject, + Transformer, Jetty10WsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt index 7caae792..e729e015 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object Jetty11WsMessagesTransformer : - TransformerObject, + Transformer, Jetty11WsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt index 0e754bc5..34a37dda 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object Jetty9WsMessagesTransformer : - TransformerObject, + Transformer, Jetty9WsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt index fac55cbd..9be8d886 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.instrument.* import com.epam.drill.agent.request.HeadersRetriever actual object JettyHttpServerTransformer : - TransformerObject, + Transformer, JettyHttpServerTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt index 2b2d3f0c..335a4119 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object JettyWsClientTransformer : - TransformerObject, + Transformer, JettyWsClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt index a5cdfb01..57e9abca 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.* actual object JettyWsServerTransformer : - TransformerObject, + Transformer, JettyWsServerTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt index 497e31fa..a06ffcb1 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt @@ -20,11 +20,11 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.HeadersRetriever actual object NettyHttpServerTransformer : - TransformerObject, + Transformer, NettyHttpServerTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt index dae6ab09..91056018 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object NettyWsClientTransformer : - TransformerObject, + Transformer, NettyWsClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt index 8dd3fbf0..c6602b8f 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt @@ -22,10 +22,10 @@ import com.epam.drill.agent.instrument.DefaultPayloadProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.PayloadProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object NettyWsMessagesTransformer : - TransformerObject, + Transformer, NettyWsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt index b9eacf3e..cd57e734 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object NettyWsServerTransformer : - TransformerObject, + Transformer, NettyWsServerTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/FluxTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/FluxTransformer.kt index afbc3828..d5fff6db 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/FluxTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/FluxTransformer.kt @@ -18,10 +18,10 @@ package com.epam.drill.agent.instrument.reactor.transformers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.DrillRequestHolder -object FluxTransformer: TransformerObject, +object FluxTransformer: Transformer, FluxTransformerObject(Configuration), com.epam.drill.agent.common.request.RequestHolder by DrillRequestHolder, ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/MonoTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/MonoTransformer.kt index 1952bf00..86e43a2d 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/MonoTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/MonoTransformer.kt @@ -18,10 +18,10 @@ package com.epam.drill.agent.instrument.reactor.transformers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.DrillRequestHolder -object MonoTransformer : TransformerObject, +object MonoTransformer : Transformer, MonoTransformerObject(Configuration), com.epam.drill.agent.common.request.RequestHolder by DrillRequestHolder, ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/ParallelFluxTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/ParallelFluxTransformer.kt index 41c1acdb..2a31ff26 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/ParallelFluxTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/ParallelFluxTransformer.kt @@ -18,10 +18,10 @@ package com.epam.drill.agent.instrument.reactor.transformers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.DrillRequestHolder -object ParallelFluxTransformer: TransformerObject, +object ParallelFluxTransformer: Transformer, ParallelFluxTransformerObject(Configuration), com.epam.drill.agent.common.request.RequestHolder by DrillRequestHolder, ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/SchedulersTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/SchedulersTransformer.kt index 5883ce3e..a723a696 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/SchedulersTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/reactor/transformers/SchedulersTransformer.kt @@ -16,12 +16,12 @@ package com.epam.drill.agent.instrument.reactor.transformers import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider import com.epam.drill.agent.request.DrillRequestHolder -object SchedulersTransformer: TransformerObject, +object SchedulersTransformer: Transformer, SchedulersTransformerObject(Configuration), com.epam.drill.agent.common.request.RequestHolder by DrillRequestHolder, ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt index f16af633..c161945f 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object CadenceTransformer : - TransformerObject, + Transformer, CadenceTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt index 3cb25ce0..ec576022 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt @@ -21,7 +21,7 @@ import com.epam.drill.agent.instrument.test.CompatibilityTestsTransformerObject import com.epam.drill.agent.request.DrillRequestHolder actual object CompatibilityTestsTransformer : - TransformerObject, + Transformer, com.epam.drill.agent.common.request.RequestHolder by DrillRequestHolder, CompatibilityTestsTransformerObject(Configuration), ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt index 82755906..f81c2b62 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object KafkaTransformer : - TransformerObject, + Transformer, KafkaTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt index bd3c70e2..76d8cdcf 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.instrument.reactor.transformers.FluxTransformer import com.epam.drill.agent.instrument.reactor.transformers.MonoTransformer import com.epam.drill.agent.instrument.reactor.transformers.ParallelFluxTransformer @@ -33,6 +33,6 @@ private val reactorTransformers = setOf( ) actual object ReactorTransformer : - TransformerObject, + Transformer, ReactorTransformerObject(reactorTransformers, Configuration), ClassPathProvider by RuntimeClassPathProvider \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt index bbf9cbdc..e78fca28 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt @@ -20,11 +20,11 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.HeadersRetriever actual object SSLEngineTransformer : - TransformerObject, + Transformer, SSLEngineTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt index 3c300607..7ba450e3 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt @@ -18,9 +18,9 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object TTLTransformer : - TransformerObject, + Transformer, TTLTransformerObject(Configuration), ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt index 8c3a60b2..7167babc 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt @@ -20,11 +20,11 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.request.HeadersRetriever actual object TomcatHttpServerTransformer : - TransformerObject, + Transformer, TomcatHttpServerTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt index 9442959a..c7fc5caa 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object TomcatWsClientTransformer : - TransformerObject, + Transformer, TomcatWsClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt index b27fb0ff..b6f92ea4 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt @@ -22,10 +22,10 @@ import com.epam.drill.agent.instrument.DefaultPayloadProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.PayloadProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object TomcatWsMessagesTransformer : - TransformerObject, + Transformer, TomcatWsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt index 484145c7..de681d77 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt @@ -20,10 +20,10 @@ import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.DefaultHeadersProcessor import com.epam.drill.agent.instrument.HeadersProcessor import com.epam.drill.agent.instrument.RuntimeClassPathProvider -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer actual object TomcatWsServerTransformer : - TransformerObject, + Transformer, TomcatWsServerTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt index 1793c479..2efcab3b 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.instrument.* import com.epam.drill.agent.request.HeadersRetriever actual object UndertowHttpServerTransformer : - TransformerObject, + Transformer, UndertowHttpServerTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt index 86b1d18a..cc63a310 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.instrument.* import com.epam.drill.agent.request.HeadersRetriever actual object UndertowWsClientTransformer : - TransformerObject, + Transformer, UndertowWsClientTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt index a4890c89..69074164 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.instrument.* import com.epam.drill.agent.request.HeadersRetriever actual object UndertowWsMessagesTransformer : - TransformerObject, + Transformer, UndertowWsMessagesTransformerObject(Configuration), HeadersProcessor by DefaultHeadersProcessor, PayloadProcessor by DefaultPayloadProcessor, diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt index 721c144e..91581ac3 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt @@ -20,7 +20,7 @@ import com.epam.drill.agent.instrument.* import com.epam.drill.agent.request.HeadersRetriever actual object UndertowWsServerTransformer : - TransformerObject, + Transformer, UndertowWsServerTransformerObject(HeadersRetriever, Configuration), HeadersProcessor by DefaultHeadersProcessor, ClassPathProvider by RuntimeClassPathProvider diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt index 02b37c5e..99159932 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt @@ -35,35 +35,6 @@ import com.epam.drill.agent.transport.JvmModuleMessageSender import com.epam.drill.agent.jvmapi.gen.* import kotlinx.cinterop.ExperimentalForeignApi import kotlin.experimental.ExperimentalNativeApi -import com.epam.drill.agent.instrument.TransformerRegistrar -import com.epam.drill.agent.instrument.clients.ApacheHttpClientTransformer -import com.epam.drill.agent.instrument.clients.JavaHttpClientTransformer -import com.epam.drill.agent.instrument.clients.OkHttp3ClientTransformer -import com.epam.drill.agent.instrument.clients.SpringWebClientTransformer -import com.epam.drill.agent.instrument.jetty.Jetty10WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.Jetty11WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.Jetty9WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.JettyHttpServerTransformer -import com.epam.drill.agent.instrument.jetty.JettyWsClientTransformer -import com.epam.drill.agent.instrument.jetty.JettyWsServerTransformer -import com.epam.drill.agent.instrument.netty.NettyHttpServerTransformer -import com.epam.drill.agent.instrument.netty.NettyWsClientTransformer -import com.epam.drill.agent.instrument.netty.NettyWsMessagesTransformer -import com.epam.drill.agent.instrument.netty.NettyWsServerTransformer -import com.epam.drill.agent.instrument.servers.CadenceTransformer -import com.epam.drill.agent.instrument.servers.CompatibilityTestsTransformer -import com.epam.drill.agent.instrument.servers.KafkaTransformer -import com.epam.drill.agent.instrument.servers.ReactorTransformer -import com.epam.drill.agent.instrument.servers.SSLEngineTransformer -import com.epam.drill.agent.instrument.servers.TTLTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatHttpServerTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsClientTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsMessagesTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsServerTransformer -import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer object Agent { @@ -79,37 +50,6 @@ object Agent { """.trimIndent() private val logger = KotlinLogging.logger("com.epam.drill.agent.Agent") - private val transformers = setOf( - ApplicationClassTransformer, - TomcatHttpServerTransformer, - JettyHttpServerTransformer, - UndertowHttpServerTransformer, - NettyHttpServerTransformer, - JavaHttpClientTransformer, - ApacheHttpClientTransformer, - OkHttp3ClientTransformer, - SpringWebClientTransformer, - KafkaTransformer, - CadenceTransformer, - TTLTransformer, - ReactorTransformer, - SSLEngineTransformer, - JettyWsClientTransformer, - JettyWsServerTransformer, - Jetty9WsMessagesTransformer, - Jetty10WsMessagesTransformer, - Jetty11WsMessagesTransformer, - NettyWsClientTransformer, - NettyWsServerTransformer, - NettyWsMessagesTransformer, - TomcatWsClientTransformer, - TomcatWsServerTransformer, - TomcatWsMessagesTransformer, - UndertowWsClientTransformer, - UndertowWsServerTransformer, - UndertowWsMessagesTransformer, - CompatibilityTestsTransformer, - ) @OptIn(ExperimentalNativeApi::class, ExperimentalForeignApi::class) fun agentOnLoad(options: String): Int { @@ -117,7 +57,6 @@ object Agent { AgentLoggingConfiguration.defaultNativeLoggingConfiguration() Configuration.initializeNative(options) AgentLoggingConfiguration.updateNativeLoggingConfiguration() - TransformerRegistrar.initialize(transformers) addCapabilities() setEventCallbacks() setUnhandledExceptionHook({ error: Throwable -> logger.error(error) { "Unhandled event: $error" }}.freeze()) diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt index db0b6e27..f91d4c04 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt @@ -18,6 +18,14 @@ package com.epam.drill.agent.instrument import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_ENABLED -abstract class AbstractTransformerObject: JvmTransformerObject() { +abstract class AbstractTransformerObject: Transformer { override fun enabled() = Configuration.parameters[INSTRUMENTATION_ENABLED] + override fun transform( + className: String, + classFileBuffer: ByteArray, + loader: Any?, + protectionDomain: Any? + ): ByteArray { + throw UnsupportedOperationException("Use transform in CompositeTransformer instead") + } } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index 03f6652c..907afc96 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -20,20 +20,16 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.module.InstrumentationAgentModule import com.epam.drill.agent.module.JvmModuleStorage -actual object ApplicationClassTransformer : TransformerObject, AbstractTransformerObject() { +actual object ApplicationClassTransformer : Transformer, AbstractTransformerObject() { override fun precheck( className: String, loader: Any?, protectionDomain: Any? - ): Boolean = loader != null && protectionDomain != null && '$' !in className - - override fun permit( - className: String, - superName: String?, - interfaces: Array - ): Boolean = ClassSource(className, superName ?: "") - .prefixMatches(Configuration.agentMetadata.packagesPrefixes) + ): Boolean = loader != null + && protectionDomain != null + && '$' !in className + && ClassSource(className, "").prefixMatches(Configuration.agentMetadata.packagesPrefixes) override fun transform( className: String, @@ -45,14 +41,4 @@ actual object ApplicationClassTransformer : TransformerObject, AbstractTransform .fold(classFileBuffer) { bytes, plugin -> plugin.instrument(className, bytes) ?: bytes } - - override fun checkAndTransform( - className: String, - classFileBuffer: ByteArray, - loader: Any?, - protectionDomain: Any? - ): ByteArray { - if (!permit(className, null, emptyArray())) return classFileBuffer - return transform(className, classFileBuffer, loader, protectionDomain) - } } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt new file mode 100644 index 00000000..35edf999 --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt @@ -0,0 +1,27 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +actual object CompositeTransformer: Transformer, JvmTransformer() { + private val transformers = TransformerRegistrar + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean { + return transformers.enabledTransformers.any { it.precheck(className, loader, protectionDomain) } + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt new file mode 100644 index 00000000..e38cd65e --- /dev/null +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt @@ -0,0 +1,88 @@ +/** + * Copyright 2020 - 2022 EPAM Systems + * + * 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. + */ +package com.epam.drill.agent.instrument + +import com.epam.drill.agent.instrument.clients.ApacheHttpClientTransformer +import com.epam.drill.agent.instrument.clients.JavaHttpClientTransformer +import com.epam.drill.agent.instrument.clients.OkHttp3ClientTransformer +import com.epam.drill.agent.instrument.clients.SpringWebClientTransformer +import com.epam.drill.agent.instrument.jetty.Jetty10WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.Jetty11WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.Jetty9WsMessagesTransformer +import com.epam.drill.agent.instrument.jetty.JettyHttpServerTransformer +import com.epam.drill.agent.instrument.jetty.JettyWsClientTransformer +import com.epam.drill.agent.instrument.jetty.JettyWsServerTransformer +import com.epam.drill.agent.instrument.netty.NettyHttpServerTransformer +import com.epam.drill.agent.instrument.netty.NettyWsClientTransformer +import com.epam.drill.agent.instrument.netty.NettyWsMessagesTransformer +import com.epam.drill.agent.instrument.netty.NettyWsServerTransformer +import com.epam.drill.agent.instrument.servers.CadenceTransformer +import com.epam.drill.agent.instrument.servers.CompatibilityTestsTransformer +import com.epam.drill.agent.instrument.servers.KafkaTransformer +import com.epam.drill.agent.instrument.servers.ReactorTransformer +import com.epam.drill.agent.instrument.servers.SSLEngineTransformer +import com.epam.drill.agent.instrument.servers.TTLTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatHttpServerTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsClientTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsMessagesTransformer +import com.epam.drill.agent.instrument.tomcat.TomcatWsServerTransformer +import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer +import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer +import mu.KotlinLogging + +actual object TransformerRegistrar { + private val logger = KotlinLogging.logger("TransformerRegistrar") + private val transformers = setOf( + ApplicationClassTransformer, + TomcatHttpServerTransformer, + JettyHttpServerTransformer, + UndertowHttpServerTransformer, + NettyHttpServerTransformer, + JavaHttpClientTransformer, + ApacheHttpClientTransformer, + OkHttp3ClientTransformer, + SpringWebClientTransformer, + KafkaTransformer, + CadenceTransformer, + TTLTransformer, + ReactorTransformer, + SSLEngineTransformer, + JettyWsClientTransformer, + JettyWsServerTransformer, + Jetty9WsMessagesTransformer, + Jetty10WsMessagesTransformer, + Jetty11WsMessagesTransformer, + NettyWsClientTransformer, + NettyWsServerTransformer, + NettyWsMessagesTransformer, + TomcatWsClientTransformer, + TomcatWsServerTransformer, + TomcatWsMessagesTransformer, + UndertowWsClientTransformer, + UndertowWsServerTransformer, + UndertowWsMessagesTransformer, + CompatibilityTestsTransformer, + ) + actual val enabledTransformers: List by lazy { + transformers.filter { transformer -> + transformer.enabled() + }.also { + logger.info { "Enabled ${it.size} native transformers" } + } + } +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt index c10008c0..808f0fca 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/ApacheHttpClientTransformer.kt @@ -18,8 +18,8 @@ package com.epam.drill.agent.instrument.clients import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_APACHE_HTTP_CLIENT_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object ApacheHttpClientTransformer : TransformerObject, AbstractTransformerObject() { +actual object ApacheHttpClientTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_APACHE_HTTP_CLIENT_ENABLED] } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt index 5fa1f25c..1fdc84b9 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/JavaHttpClientTransformer.kt @@ -18,9 +18,9 @@ package com.epam.drill.agent.instrument.clients import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JAVA_HTTP_CLIENT_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JavaHttpClientTransformer : TransformerObject, AbstractTransformerObject() { +actual object JavaHttpClientTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_JAVA_HTTP_CLIENT_ENABLED] override fun precheck( className: String, diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt index 4ecd338c..ef77c155 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/OkHttp3ClientTransformer.kt @@ -18,8 +18,8 @@ package com.epam.drill.agent.instrument.clients import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_OK_HTTP_CLIENT_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object OkHttp3ClientTransformer : TransformerObject, AbstractTransformerObject() { +actual object OkHttp3ClientTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_OK_HTTP_CLIENT_ENABLED] } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt index 4e1edb86..193b4674 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/clients/SpringWebClientTransformer.kt @@ -17,11 +17,9 @@ package com.epam.drill.agent.instrument.clients import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_APACHE_HTTP_CLIENT_ENABLED import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SPRING_WEB_CLIENT_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object SpringWebClientTransformer : TransformerObject, AbstractTransformerObject() { +actual object SpringWebClientTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_SPRING_WEB_CLIENT_ENABLED] } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt index 5cb074a9..4ecddba3 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty10WsMessagesTransformer.kt @@ -15,12 +15,7 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_APACHE_HTTP_CLIENT_ENABLED -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_WS_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Jetty10WsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() \ No newline at end of file +actual object Jetty10WsMessagesTransformer : Transformer, AbstractWsTransformerObject() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt index 471b9b83..17ee6516 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty11WsMessagesTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.jetty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Jetty11WsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() +actual object Jetty11WsMessagesTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt index cb9c1253..35be1b12 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/Jetty9WsMessagesTransformer.kt @@ -15,12 +15,7 @@ */ package com.epam.drill.agent.instrument.jetty -import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_APACHE_HTTP_CLIENT_ENABLED -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_WS_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Jetty9WsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() +actual object Jetty9WsMessagesTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt index b9d8c319..30e81e3e 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyHttpServerTransformer.kt @@ -17,9 +17,13 @@ package com.epam.drill.agent.instrument.jetty import com.epam.drill.agent.instrument.AbstractHttpTransformerObject import com.epam.drill.agent.instrument.JETTY_SERVER_HANDLER -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JettyHttpServerTransformer : TransformerObject, AbstractHttpTransformerObject() { - override fun permit(className: String, superName: String?, interfaces: Array) = - JETTY_SERVER_HANDLER == className +actual object JettyHttpServerTransformer : Transformer, AbstractHttpTransformerObject() { + + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = JETTY_SERVER_HANDLER == className } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt index 1166e255..1e23c041 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsClientTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.jetty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JettyWsClientTransformer : TransformerObject, AbstractWsTransformerObject() +actual object JettyWsClientTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt index 8159e9d9..c7231a7f 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/jetty/JettyWsServerTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.jetty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JettyWsServerTransformer : TransformerObject, AbstractWsTransformerObject() +actual object JettyWsServerTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt index 9dff80d8..42fbba19 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyHttpServerTransformer.kt @@ -16,15 +16,14 @@ package com.epam.drill.agent.instrument.netty import com.epam.drill.agent.instrument.AbstractHttpTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject import com.epam.drill.agent.instrument.NETTY_CHANNEL_HANDLER_CONTEXT -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object NettyHttpServerTransformer : TransformerObject, AbstractHttpTransformerObject() { +actual object NettyHttpServerTransformer : Transformer, AbstractHttpTransformerObject() { - override fun permit( + override fun precheck( className: String, - superName: String?, - interfaces: Array + loader: Any?, + protectionDomain: Any? ): Boolean = '$' !in className && className.startsWith(NETTY_CHANNEL_HANDLER_CONTEXT) } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt index aee92da0..3df441c9 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsClientTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.netty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object NettyWsClientTransformer : TransformerObject, AbstractWsTransformerObject() +actual object NettyWsClientTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt index 90e32c00..2340f9c5 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsMessagesTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.netty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object NettyWsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() +actual object NettyWsMessagesTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt index 0a21b76c..5c52ddbe 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/netty/NettyWsServerTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.netty import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object NettyWsServerTransformer : TransformerObject, AbstractWsTransformerObject() +actual object NettyWsServerTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt index eb57d01e..e91da1e1 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CadenceTransformer.kt @@ -17,15 +17,17 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.instrument.CADENCE_CONSUMER import com.epam.drill.agent.instrument.CADENCE_PRODUCER import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_CADENCE_ENABLED -actual object CadenceTransformer : TransformerObject, AbstractTransformerObject() { +actual object CadenceTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_CADENCE_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array) = - CADENCE_PRODUCER == className || CADENCE_CONSUMER == className + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = CADENCE_PRODUCER == className || CADENCE_CONSUMER == className } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt index bd1c5784..2778a65e 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/CompatibilityTestsTransformer.kt @@ -16,13 +16,10 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.configuration.ParameterDefinitions import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_COMPATIBILITY_TESTS_ENABLED -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_WS_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object CompatibilityTestsTransformer : TransformerObject, AbstractTransformerObject() { +actual object CompatibilityTestsTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_COMPATIBILITY_TESTS_ENABLED] } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt index e44e2793..09d53a8a 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/KafkaTransformer.kt @@ -20,10 +20,8 @@ import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_KAFKA_ENABLED import com.epam.drill.agent.instrument.KAFKA_CONSUMER_SPRING import com.epam.drill.agent.instrument.KAFKA_PRODUCER_INTERFACE -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object KafkaTransformer : TransformerObject, AbstractTransformerObject() { +actual object KafkaTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_KAFKA_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array) = - KAFKA_CONSUMER_SPRING == className || interfaces.contains(KAFKA_PRODUCER_INTERFACE) } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt index 4fbebdab..3e3adbea 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/ReactorTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.instrument.AbstractReactTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object ReactorTransformer: TransformerObject, AbstractReactTransformerObject() \ No newline at end of file +actual object ReactorTransformer: Transformer, AbstractReactTransformerObject() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt index 265ea35a..90c0f577 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/SSLEngineTransformer.kt @@ -18,17 +18,10 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SSL_ENABLED -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_WS_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject import com.epam.drill.agent.instrument.SSL_ENGINE_CLASS_NAME -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object SSLEngineTransformer : TransformerObject, AbstractTransformerObject() { +actual object SSLEngineTransformer : Transformer, AbstractTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_SSL_ENABLED] - override fun permit( - className: String, - superName: String?, - interfaces: Array - ): Boolean = superName == SSL_ENGINE_CLASS_NAME } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt index 84891034..e7de17df 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/servers/TTLTransformer.kt @@ -18,11 +18,9 @@ package com.epam.drill.agent.instrument.servers import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_TTL_ENABLED -import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_WS_ENABLED -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TTLTransformer : TransformerObject, AbstractTransformerObject() { +actual object TTLTransformer : Transformer, AbstractTransformerObject() { val directTtlClasses = listOf( "java/util/concurrent/ScheduledThreadPoolExecutor", "java/util/concurrent/ThreadPoolExecutor", @@ -39,15 +37,6 @@ actual object TTLTransformer : TransformerObject, AbstractTransformerObject() { className: String, loader: Any?, protectionDomain: Any? - ): Boolean = loader != null && protectionDomain != null || className in directTtlClasses - - override fun permit( - className: String, - superName: String?, - interfaces: Array - ): Boolean = className in directTtlClasses - || (className != timerTaskClass - && (runnableInterface in interfaces.filterNotNull() - || superName == poolExecutor)) - && !className.startsWith(jdkInternal) + ): Boolean = loader != null && protectionDomain != null && !className.startsWith("jdk/internal") + || className in directTtlClasses } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt index ae8b2069..f0e1a077 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatHttpServerTransformer.kt @@ -16,11 +16,13 @@ package com.epam.drill.agent.instrument.tomcat import com.epam.drill.agent.instrument.AbstractHttpTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject import com.epam.drill.agent.instrument.TOMCAT_HTTP_FILTER -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TomcatHttpServerTransformer : TransformerObject, AbstractHttpTransformerObject() { - override fun permit(className: String, superName: String?, interfaces: Array) = - TOMCAT_HTTP_FILTER == className +actual object TomcatHttpServerTransformer : Transformer, AbstractHttpTransformerObject() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = TOMCAT_HTTP_FILTER == className } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt index f5d8c039..d1971f81 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsClientTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.tomcat import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TomcatWsClientTransformer : TransformerObject, AbstractWsTransformerObject() +actual object TomcatWsClientTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt index 8a863048..5cb007af 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsMessagesTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.tomcat import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TomcatWsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() +actual object TomcatWsMessagesTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt index 31095dc3..92c076b6 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/tomcat/TomcatWsServerTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.tomcat import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TomcatWsServerTransformer : TransformerObject, AbstractWsTransformerObject() +actual object TomcatWsServerTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt index 3d006b81..76e8d4bf 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowHttpServerTransformer.kt @@ -16,11 +16,14 @@ package com.epam.drill.agent.instrument.undertow import com.epam.drill.agent.instrument.AbstractHttpTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.instrument.UNDERTOW_SERVER_CONNECTORS -actual object UndertowHttpServerTransformer : TransformerObject, AbstractHttpTransformerObject() { - override fun permit(className: String, superName: String?, interfaces: Array) = - UNDERTOW_SERVER_CONNECTORS == className +actual object UndertowHttpServerTransformer : Transformer, AbstractHttpTransformerObject() { + + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = UNDERTOW_SERVER_CONNECTORS == className } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt index f7dec9a2..f697c31e 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsClientTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.undertow import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object UndertowWsClientTransformer : TransformerObject, AbstractWsTransformerObject() +actual object UndertowWsClientTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt index 67f99e63..7e300fe9 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsMessagesTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.undertow import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object UndertowWsMessagesTransformer : TransformerObject, AbstractWsTransformerObject() +actual object UndertowWsMessagesTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt index f8923a52..cbd7ebd2 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/undertow/UndertowWsServerTransformer.kt @@ -16,7 +16,6 @@ package com.epam.drill.agent.instrument.undertow import com.epam.drill.agent.instrument.AbstractWsTransformerObject -import com.epam.drill.agent.instrument.JvmTransformerObject -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object UndertowWsServerTransformer : TransformerObject, AbstractWsTransformerObject() +actual object UndertowWsServerTransformer : Transformer, AbstractWsTransformerObject() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt index 116b5ae9..248af6f8 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/jvmti/ClassFileLoadHook.kt @@ -15,8 +15,7 @@ */ package com.epam.drill.agent.jvmti -import com.epam.drill.agent.instrument.servers.* -import com.epam.drill.agent.instrument.TransformerRegistrar +import com.epam.drill.agent.instrument.CompositeTransformer import com.epam.drill.agent.jvmapi.gen.Allocate import com.epam.drill.agent.jvmapi.gen.jint import com.epam.drill.agent.jvmapi.gen.jintVar @@ -47,11 +46,8 @@ object ClassFileLoadHook { initRuntimeIfNeeded() val kClassName = clsName?.toKString() ?: return val kClassData = classData ?: return - val precheckedTransformers = TransformerRegistrar.enabledTransformers - .filterNot { kClassName.startsWith(DRILL_PACKAGE) } - .filter { it.precheck(kClassName, loader, protectionDomain) } - .takeIf { it.any() } - ?: return + if (kClassName.startsWith(DRILL_PACKAGE)) return + if (!CompositeTransformer.precheck(kClassName, loader, protectionDomain)) return val oldClassBytes = runCatching { val classBytes = ByteArray(classDataLen).apply { @@ -62,19 +58,13 @@ object ClassFileLoadHook { logger.error(it) { "Can't read class: $kClassName" } }.getOrNull() ?: return - val newClassBytes = precheckedTransformers.fold(oldClassBytes) { bytes, transformer -> - runCatching { - transformer.checkAndTransform(kClassName, bytes, loader, protectionDomain) - }.onFailure { - logger.warn(it) { "Can't transform class: $kClassName with ${transformer::class.simpleName}" } - }.getOrNull() - ?.takeIf { it !== bytes } - ?.also { - logger.debug { "$kClassName was transformed by ${transformer::class.simpleName}" } - } ?: bytes - } + val newClassBytes = runCatching { + CompositeTransformer.transform(kClassName, oldClassBytes, loader, protectionDomain) + }.onFailure { + logger.warn(it) { "Can't transform class: $kClassName" } + }.getOrNull() ?: return - if (newClassBytes !== oldClassBytes) { + if (!newClassBytes.contentEquals(oldClassBytes)) { totalTransformClass.addAndGet(1).takeIf { it % 100 == 0 }?.let { logger.debug { "At least $it classes were transformed" } } @@ -97,19 +87,4 @@ object ClassFileLoadHook { newClassDataLen!!.pointed.value = instrumentedSize } - @OptIn(ExperimentalForeignApi::class) - private fun isBootstrapClassLoading(loader: jobject?, protectionDomain: jobject?) = - loader == null || protectionDomain == null - - @OptIn(ExperimentalForeignApi::class) - private fun isTTLCandidate( - kClassName: String, - superName: String, - interfaces: Collection, - ) = kClassName in TTLTransformer.directTtlClasses - || (kClassName != TTLTransformer.timerTaskClass - && (TTLTransformer.runnableInterface in interfaces - || superName == TTLTransformer.poolExecutor)) - && !kClassName.startsWith(TTLTransformer.jdkInternal) - } From 52be016de2c2a124ec8c5a68bda4325e31fc11dc Mon Sep 17 00:00:00 2001 From: iryabov Date: Mon, 23 Feb 2026 14:09:07 +0100 Subject: [PATCH 08/14] build: update sharedLibsRef to feature/java25-support --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a779e0e0..960cc522 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 asmVersion = 9.8 -sharedLibsRef = main +sharedLibsRef = feature/java25-support sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false From 7a9b0c3ceff4a72b0cb392702637a6e9f8c0e612 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 24 Feb 2026 09:18:17 +0100 Subject: [PATCH 09/14] refactor: update transform methods to return nullable ByteArray --- .../agent/instrument/ApplicationClassTransformer.kt | 2 +- .../drill/agent/instrument/CompositeTransformer.kt | 10 ++++++---- .../agent/instrument/AbstractTransformerObject.kt | 2 +- .../agent/instrument/ApplicationClassTransformer.kt | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index c6f55776..3d90e1bf 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -43,7 +43,7 @@ actual object ApplicationClassTransformer : classFileBuffer: ByteArray, loader: Any?, protectionDomain: Any? - ): ByteArray = JvmModuleStorage.values() + ): ByteArray? = JvmModuleStorage.values() .filterIsInstance() .fold(classFileBuffer) { bytes, plugin -> plugin.instrument(className, bytes) ?: bytes diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt index 61239861..00deb8d8 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt @@ -35,16 +35,18 @@ actual object CompositeTransformer : Transformer { classFileBuffer: ByteArray, loader: Any?, protectionDomain: Any? - ): ByteArray { + ): ByteArray? { val reader = runCatching { ClassReader(classFileBuffer) } .onFailure { logger.warn(it) { "Can't read class: $classFileBuffer" } } - .getOrNull() ?: return classFileBuffer + .getOrNull() ?: return null val enabledTransformers = runCatching { transformers.enabledTransformers }.onFailure { logger.warn(it) { "Can't get enabled transformers for class: $className" } - }.getOrNull() ?: return classFileBuffer + }.getOrNull() ?: return null return enabledTransformers.fold(classFileBuffer) { bytes, transformer -> runCatching { when { + !transformer.precheck(className, loader, protectionDomain) -> bytes + transformer is TransformerObject && !transformer.permit( className, reader.superName, @@ -58,6 +60,6 @@ actual object CompositeTransformer : Transformer { }.getOrNull()?.takeIf { it !== bytes }?.also { logger.debug { "$className was transformed by ${transformer::class.simpleName}" } } ?: bytes - } + }.takeIf { it !== classFileBuffer } } } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt index f91d4c04..42786082 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/AbstractTransformerObject.kt @@ -25,7 +25,7 @@ abstract class AbstractTransformerObject: Transformer { classFileBuffer: ByteArray, loader: Any?, protectionDomain: Any? - ): ByteArray { + ): ByteArray? { throw UnsupportedOperationException("Use transform in CompositeTransformer instead") } } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index 907afc96..961f5103 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -36,7 +36,7 @@ actual object ApplicationClassTransformer : Transformer, AbstractTransformerObje classFileBuffer: ByteArray, loader: Any?, protectionDomain: Any? - ): ByteArray = JvmModuleStorage.values() + ): ByteArray? = JvmModuleStorage.values() .filterIsInstance() .fold(classFileBuffer) { bytes, plugin -> plugin.instrument(className, bytes) ?: bytes From 9749fa80d17225045f44b0687f08aae95c0769d8 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 24 Feb 2026 11:23:01 +0100 Subject: [PATCH 10/14] refactor: replace hardcoded compiler-generated name check with constant --- .../epam/drill/agent/instrument/ApplicationClassTransformer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt index 961f5103..bf936bc4 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/ApplicationClassTransformer.kt @@ -28,7 +28,7 @@ actual object ApplicationClassTransformer : Transformer, AbstractTransformerObje protectionDomain: Any? ): Boolean = loader != null && protectionDomain != null - && '$' !in className + && COMPILER_GENERATED_NAMES_PREFIX !in className && ClassSource(className, "").prefixMatches(Configuration.agentMetadata.packagesPrefixes) override fun transform( From d533ce348371bc24b7d22f387dd62fcde241d7f6 Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 24 Feb 2026 13:54:33 +0100 Subject: [PATCH 11/14] refactor: replace TransformerObject with Transformer in test transformers --- .../cucumber/Cucumber4Transformer.kt | 4 +-- .../cucumber/Cucumber5Transformer.kt | 4 +-- .../cucumber/Cucumber6Transformer.kt | 4 +-- .../instrument/jmeter/JMeterTransformer.kt | 4 +-- .../junit/JUnit4PrioritizingTransformer.kt | 4 +-- .../instrument/junit/JUnit4Transformer.kt | 4 +-- .../instrument/junit/JUnit5Transformer.kt | 4 +-- .../JUnitPlatformPrioritizingTransformer.kt | 4 +-- .../selenium/SeleniumTransformer.kt | 4 +-- .../testng/TestNG6PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG6Transformer.kt | 4 +-- .../testng/TestNG7PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG7Transformer.kt | 4 +-- .../kotlin/com/epam/drill/agent/Agent.kt | 31 +------------------ .../agent/instrument/TransformerRegistrar.kt | 27 ++++++++++++++++ .../cucumber/Cucumber4Transformer.kt | 4 +-- .../cucumber/Cucumber5Transformer.kt | 4 +-- .../cucumber/Cucumber6Transformer.kt | 4 +-- .../instrument/jmeter/JMeterTransformer.kt | 4 +-- .../junit/JUnit4PrioritizingTransformer.kt | 4 +-- .../instrument/junit/JUnit4Transformer.kt | 4 +-- .../instrument/junit/JUnit5Transformer.kt | 4 +-- .../JUnitPlatformPrioritizingTransformer.kt | 4 +-- .../selenium/SeleniumTransformer.kt | 4 +-- .../testng/TestNG6PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG6Transformer.kt | 4 +-- .../testng/TestNG7PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG7Transformer.kt | 4 +-- .../kotlin/com/epam/drill/agent/Agent.kt | 3 +- .../agent/instrument/TransformerRegistrar.kt | 27 ++++++++++++++++ .../cucumber/Cucumber4Transformer.kt | 12 ++++--- .../cucumber/Cucumber5Transformer.kt | 12 ++++--- .../cucumber/Cucumber6Transformer.kt | 12 ++++--- .../instrument/jmeter/JMeterTransformer.kt | 12 ++++--- .../junit/JUnit4PrioritizingTransformer.kt | 12 ++++--- .../instrument/junit/JUnit4Transformer.kt | 12 ++++--- .../instrument/junit/JUnit5Transformer.kt | 12 ++++--- .../JUnitPlatformPrioritizingTransformer.kt | 12 ++++--- .../selenium/SeleniumTransformer.kt | 12 ++++--- .../AbstractTestNGPrioritizingTransformer.kt | 9 +++--- .../testng/AbstractTestNGTransformer.kt | 9 ++++-- .../testng/TestNG6PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG6Transformer.kt | 10 ++++-- .../testng/TestNG7PrioritizingTransformer.kt | 4 +-- .../instrument/testng/TestNG7Transformer.kt | 10 ++++-- 45 files changed, 201 insertions(+), 145 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt index 5ffa4f42..f8127c72 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Cucumber4Transformer : TransformerObject \ No newline at end of file +expect object Cucumber4Transformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt index 00327b71..43493a06 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Cucumber5Transformer : TransformerObject \ No newline at end of file +expect object Cucumber5Transformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt index 275e6dff..f30fe8d5 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object Cucumber6Transformer : TransformerObject \ No newline at end of file +expect object Cucumber6Transformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt index 50d7aeec..08d715e0 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.jmeter -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JMeterTransformer : TransformerObject \ No newline at end of file +expect object JMeterTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt index fa485db6..b1dd5d1c 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JUnit4PrioritizingTransformer : TransformerObject \ No newline at end of file +expect object JUnit4PrioritizingTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt index 3f2e3940..c6ed84f4 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JUnit4Transformer : TransformerObject \ No newline at end of file +expect object JUnit4Transformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt index 07b99ef2..eda5b6c2 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JUnit5Transformer : TransformerObject \ No newline at end of file +expect object JUnit5Transformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt index e1d6aa68..bffba82f 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object JUnitPlatformPrioritizingTransformer : TransformerObject \ No newline at end of file +expect object JUnitPlatformPrioritizingTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt index 9eb4dcf1..5b0b184a 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.selenium -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object SeleniumTransformer : TransformerObject \ No newline at end of file +expect object SeleniumTransformer : Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt index 5112b468..dc3503ca 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TestNG6PrioritizingTransformer: TransformerObject \ No newline at end of file +expect object TestNG6PrioritizingTransformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt index 109223d7..27837eb5 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TestNG6Transformer: TransformerObject \ No newline at end of file +expect object TestNG6Transformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt index 074a58b2..8414131d 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TestNG7PrioritizingTransformer: TransformerObject \ No newline at end of file +expect object TestNG7PrioritizingTransformer: Transformer \ No newline at end of file diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt index c18b6af1..0df511af 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -expect object TestNG7Transformer: TransformerObject \ No newline at end of file +expect object TestNG7Transformer: Transformer \ No newline at end of file diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt index 0d3fcc30..7d716275 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/Agent.kt @@ -20,42 +20,13 @@ import com.epam.drill.agent.configuration.AgentParametersValidator import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.DefaultParameterDefinitions import com.epam.drill.agent.configuration.ParameterDefinitions -import com.epam.drill.agent.instrument.ApplicationClassTransformer import com.epam.drill.agent.instrument.CompositeTransformer -import com.epam.drill.agent.instrument.TransformerRegistrar -import com.epam.drill.agent.instrument.clients.ApacheHttpClientTransformer -import com.epam.drill.agent.instrument.clients.JavaHttpClientTransformer -import com.epam.drill.agent.instrument.clients.OkHttp3ClientTransformer -import com.epam.drill.agent.instrument.clients.SpringWebClientTransformer -import com.epam.drill.agent.instrument.jetty.Jetty10WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.Jetty11WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.Jetty9WsMessagesTransformer -import com.epam.drill.agent.instrument.jetty.JettyHttpServerTransformer -import com.epam.drill.agent.instrument.jetty.JettyWsClientTransformer -import com.epam.drill.agent.instrument.jetty.JettyWsServerTransformer -import com.epam.drill.agent.instrument.netty.NettyHttpServerTransformer -import com.epam.drill.agent.instrument.netty.NettyWsClientTransformer -import com.epam.drill.agent.instrument.netty.NettyWsMessagesTransformer -import com.epam.drill.agent.instrument.netty.NettyWsServerTransformer -import com.epam.drill.agent.instrument.servers.CadenceTransformer -import com.epam.drill.agent.instrument.servers.CompatibilityTestsTransformer -import com.epam.drill.agent.instrument.servers.KafkaTransformer -import com.epam.drill.agent.instrument.servers.ReactorTransformer -import com.epam.drill.agent.instrument.servers.TTLTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatHttpServerTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsClientTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsMessagesTransformer -import com.epam.drill.agent.instrument.tomcat.TomcatWsServerTransformer -import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer -import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer import com.epam.drill.agent.logging.LoggingConfiguration import com.epam.drill.agent.module.JvmModuleLoader +import com.epam.drill.agent.test.session.SessionController import com.epam.drill.agent.test2code.Test2Code import com.epam.drill.agent.test2code.configuration.Test2CodeParameterDefinitions import com.epam.drill.agent.transport.JvmModuleMessageSender -import org.objectweb.asm.ClassReader import mu.KotlinLogging import java.lang.instrument.ClassFileTransformer import java.lang.instrument.Instrumentation diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt index 983cfe1f..2925f53b 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt @@ -44,6 +44,19 @@ import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber4Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber5Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber6Transformer +import com.epam.drill.agent.test.instrument.jmeter.JMeterTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4PrioritizingTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4Transformer +import com.epam.drill.agent.test.instrument.junit.JUnit5Transformer +import com.epam.drill.agent.test.instrument.junit.JUnitPlatformPrioritizingTransformer +import com.epam.drill.agent.test.instrument.selenium.SeleniumTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6Transformer +import com.epam.drill.agent.test.instrument.testng.TestNG7PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG7Transformer actual object TransformerRegistrar { private val logger = KotlinLogging.logger {} @@ -77,6 +90,20 @@ actual object TransformerRegistrar { UndertowWsServerTransformer, UndertowWsMessagesTransformer, CompatibilityTestsTransformer, + //Test instrumentation + Cucumber4Transformer, + Cucumber5Transformer, + Cucumber6Transformer, + JMeterTransformer, + JUnit4PrioritizingTransformer, + JUnit4Transformer, + JUnit5Transformer, + JUnitPlatformPrioritizingTransformer, + SeleniumTransformer, + TestNG6PrioritizingTransformer, + TestNG6Transformer, + TestNG7PrioritizingTransformer, + TestNG7Transformer ) actual val enabledTransformers: List by lazy { transformers.filter { transformer -> diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt index eaac09c4..e4f0181f 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -15,10 +15,10 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import javassist.* -actual object Cucumber4Transformer : TransformerObject, AbstractCucumberTransformer() { +actual object Cucumber4Transformer : Transformer, AbstractCucumberTransformer() { override val testPackage = "cucumber.api.event" override val Status = "cucumber.api.Result.Type" override val EventBus = "cucumber.runner.EventBus" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt index 4b4c1ccc..d906f039 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -15,12 +15,12 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import java.security.ProtectionDomain import javassist.ClassPool import javassist.CtClass -actual object Cucumber5Transformer : TransformerObject, AbstractCucumber56Transformer() { +actual object Cucumber5Transformer : Transformer, AbstractCucumber56Transformer() { override val versionPattern: Regex = "5\\.[0-9]+\\.[0-9]+".toRegex() override val Event: String = "io.cucumber.plugin.event.Event" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt index 2e592bae..2a58f327 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -15,12 +15,12 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import java.security.ProtectionDomain import javassist.ClassPool import javassist.CtClass -actual object Cucumber6Transformer : TransformerObject, AbstractCucumber56Transformer() { +actual object Cucumber6Transformer : Transformer, AbstractCucumber56Transformer() { override val versionPattern: Regex = "6\\.[0-9]+\\.[0-9]+".toRegex() override val Event: String = "java.lang.Object" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt index b561d3a3..909143f4 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -16,13 +16,13 @@ package com.epam.drill.agent.test.instrument.jmeter import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JMETER_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject import javassist.* import mu.KotlinLogging import java.security.* -actual object JMeterTransformer : TransformerObject, AbstractTestTransformerObject() { +actual object JMeterTransformer : Transformer, AbstractTestTransformerObject() { override val logger = KotlinLogging.logger {} override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_JMETER_ENABLED] diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt index f052f802..ac222357 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -16,7 +16,7 @@ package com.epam.drill.agent.test.instrument.junit import com.epam.drill.agent.configuration.ParameterDefinitions -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.prioritization.RecommendedTests import javassist.* import mu.KotlinLogging @@ -25,7 +25,7 @@ import java.security.ProtectionDomain private const val Filter = "org.junit.runner.manipulation.Filter" private const val Description = "org.junit.runner.Description" -actual object JUnit4PrioritizingTransformer : TransformerObject, AbstractJUnitTransformer() { +actual object JUnit4PrioritizingTransformer : Transformer, AbstractJUnitTransformer() { override val logger = KotlinLogging.logger {} private val engineSegment = "junit" private val DrillJUnit4Filter = "${this.javaClass.`package`.name}.gen.DrillJUnit4Filter" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt index b352ac6c..d017ccca 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -15,7 +15,7 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.execution.TestController import com.epam.drill.agent.test.execution.TestResult import javassist.ClassPool @@ -27,7 +27,7 @@ import mu.KotlinLogging import java.security.ProtectionDomain actual object JUnit4Transformer: - TransformerObject, + Transformer, AbstractJUnitTransformer() { override val logger = KotlinLogging.logger {} const val engineSegment = "junit" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt index b1f83fce..b71dce79 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -15,14 +15,14 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.execution.TestController import com.epam.drill.agent.test.execution.TestMethodInfo import javassist.* import mu.KotlinLogging import java.security.* -actual object JUnit5Transformer: TransformerObject, AbstractJUnitTransformer() { +actual object JUnit5Transformer: Transformer, AbstractJUnitTransformer() { override val logger = KotlinLogging.logger {} override fun permit(className: String, superName: String?, interfaces: Array): Boolean { diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt index aee43dee..14bf5717 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -17,14 +17,14 @@ package com.epam.drill.agent.test.instrument.junit import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.ParameterDefinitions -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.execution.TestMethodInfo import com.epam.drill.agent.test.prioritization.RecommendedTests import javassist.* import mu.KotlinLogging import java.security.ProtectionDomain -actual object JUnitPlatformPrioritizingTransformer : TransformerObject, AbstractJUnitTransformer() { +actual object JUnitPlatformPrioritizingTransformer : Transformer, AbstractJUnitTransformer() { override val logger = KotlinLogging.logger {} private val DrillJUnit5Filter = "${this.javaClass.`package`.name}.gen.DrillJUnit5Filter" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt index 94552044..200b4cf0 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -19,7 +19,7 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.ParameterDefinitions import com.epam.drill.agent.test.* import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SELENIUM_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject import javassist.* import mu.KLogger @@ -28,7 +28,7 @@ import mu.KotlinLogging import java.security.ProtectionDomain @Suppress("PrivatePropertyName") -actual object SeleniumTransformer : TransformerObject, AbstractTestTransformerObject() { +actual object SeleniumTransformer : Transformer, AbstractTestTransformerObject() { private const val Command = "org.openqa.selenium.remote.Command" private const val ImmutableMap = "com.google.common.collect.ImmutableMap" diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt index b028106e..c4c9caac 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -15,10 +15,10 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import mu.KotlinLogging -actual object TestNG6PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() { +actual object TestNG6PrioritizingTransformer: Transformer, AbstractTestNGPrioritizingTransformer() { override val logger = KotlinLogging.logger {} override val versionRegex: Regex = "testng-6\\.[0-9]+(\\.[0-9]+)*".toRegex() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt index b96b433f..33e4b743 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -15,11 +15,11 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import javassist.* import java.security.* -actual object TestNG6Transformer : TransformerObject, AbstractTestNG67Transformer() { +actual object TestNG6Transformer : Transformer, AbstractTestNG67Transformer() { override val versionRegex: Regex = "testng-6\\.[0-9]+(\\.[0-9]+)*".toRegex() override fun instrument( diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt index c0c9221b..fa2e3e59 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -15,10 +15,10 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import mu.KotlinLogging -actual object TestNG7PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() { +actual object TestNG7PrioritizingTransformer: Transformer, AbstractTestNGPrioritizingTransformer() { override val logger = KotlinLogging.logger {} override val versionRegex: Regex = "testng-7\\.[0-9]+(\\.[0-9]+)*".toRegex() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt index 2018db17..9b99b9f3 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -15,11 +15,11 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import javassist.* import java.security.* -actual object TestNG7Transformer : TransformerObject, AbstractTestNG67Transformer() { +actual object TestNG7Transformer : Transformer, AbstractTestNG67Transformer() { override val versionRegex: Regex = "testng-7\\.[0-9]+(\\.[0-9]+)*".toRegex() diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt index 67a2f933..b1a559bf 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/Agent.kt @@ -26,13 +26,13 @@ import mu.KotlinLogging import com.epam.drill.agent.configuration.AgentLoggingConfiguration import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.DefaultParameterDefinitions.INSTALLATION_DIR -import com.epam.drill.agent.instrument.ApplicationClassTransformer import com.epam.drill.agent.jvmti.classFileLoadHook import com.epam.drill.agent.jvmti.vmDeathEvent import com.epam.drill.agent.jvmti.vmInitEvent import com.epam.drill.agent.module.JvmModuleLoader import com.epam.drill.agent.transport.JvmModuleMessageSender import com.epam.drill.agent.jvmapi.gen.* +import com.epam.drill.agent.test.session.SessionController import kotlinx.cinterop.ExperimentalForeignApi import kotlin.experimental.ExperimentalNativeApi @@ -81,7 +81,6 @@ object Agent { Configuration.initializeJvm() loadJvmModule("com.epam.drill.agent.test2code.Test2Code") JvmModuleMessageSender.sendAgentMetadata() - SessionController.startSession() } diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt index e38cd65e..207ff796 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/instrument/TransformerRegistrar.kt @@ -43,6 +43,19 @@ import com.epam.drill.agent.instrument.undertow.UndertowHttpServerTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsClientTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsMessagesTransformer import com.epam.drill.agent.instrument.undertow.UndertowWsServerTransformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber4Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber5Transformer +import com.epam.drill.agent.test.instrument.cucumber.Cucumber6Transformer +import com.epam.drill.agent.test.instrument.jmeter.JMeterTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4PrioritizingTransformer +import com.epam.drill.agent.test.instrument.junit.JUnit4Transformer +import com.epam.drill.agent.test.instrument.junit.JUnit5Transformer +import com.epam.drill.agent.test.instrument.junit.JUnitPlatformPrioritizingTransformer +import com.epam.drill.agent.test.instrument.selenium.SeleniumTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG6Transformer +import com.epam.drill.agent.test.instrument.testng.TestNG7PrioritizingTransformer +import com.epam.drill.agent.test.instrument.testng.TestNG7Transformer import mu.KotlinLogging actual object TransformerRegistrar { @@ -77,6 +90,20 @@ actual object TransformerRegistrar { UndertowWsServerTransformer, UndertowWsMessagesTransformer, CompatibilityTestsTransformer, + //Test instrumentation + Cucumber4Transformer, + Cucumber5Transformer, + Cucumber6Transformer, + JMeterTransformer, + JUnit4PrioritizingTransformer, + JUnit4Transformer, + JUnit5Transformer, + JUnitPlatformPrioritizingTransformer, + SeleniumTransformer, + TestNG6PrioritizingTransformer, + TestNG6Transformer, + TestNG7PrioritizingTransformer, + TestNG7Transformer ) actual val enabledTransformers: List by lazy { transformers.filter { transformer -> diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt index 7cbbebaa..547030cf 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber4Transformer.kt @@ -15,10 +15,12 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Cucumber4Transformer: TransformerObject, AbstractCucumberTransformer() { - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == /*4.x.x*/"cucumber/runner/TestStep" - } +actual object Cucumber4Transformer: Transformer, AbstractCucumberTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == /*4.x.x*/"cucumber/runner/TestStep" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt index d1015838..65c069d2 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber5Transformer.kt @@ -15,10 +15,12 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Cucumber5Transformer: TransformerObject, AbstractCucumberTransformer() { - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "io/cucumber/core/runner/TestStep" - } +actual object Cucumber5Transformer: Transformer, AbstractCucumberTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "io/cucumber/core/runner/TestStep" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt index cb1cfa6d..a527f17c 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/cucumber/Cucumber6Transformer.kt @@ -15,10 +15,12 @@ */ package com.epam.drill.agent.test.instrument.cucumber -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object Cucumber6Transformer: TransformerObject, AbstractCucumberTransformer() { - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "io/cucumber/core/runner/TestStep" - } +actual object Cucumber6Transformer: Transformer, AbstractCucumberTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "io/cucumber/core/runner/TestStep" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt index c5e05183..42f3a387 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/jmeter/JMeterTransformer.kt @@ -17,13 +17,15 @@ package com.epam.drill.agent.test.instrument.jmeter import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_JMETER_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject -actual object JMeterTransformer: TransformerObject, AbstractTestTransformerObject() { +actual object JMeterTransformer: Transformer, AbstractTestTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_JMETER_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl" - } + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt index 6d7dc12a..71bc5cb8 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4PrioritizingTransformer.kt @@ -17,12 +17,14 @@ package com.epam.drill.agent.test.instrument.junit import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.ParameterDefinitions -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JUnit4PrioritizingTransformer: TransformerObject, AbstractJUnitTransformer() { +actual object JUnit4PrioritizingTransformer: Transformer, AbstractJUnitTransformer() { override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/junit/runners/JUnit4" - } + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/junit/runners/JUnit4" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt index ddc714c5..358e67b9 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit4Transformer.kt @@ -15,10 +15,12 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JUnit4Transformer: TransformerObject, AbstractJUnitTransformer() { - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/junit/runner/notification/RunNotifier" - } +actual object JUnit4Transformer: Transformer, AbstractJUnitTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/junit/runner/notification/RunNotifier" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt index d22bebea..0069a700 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnit5Transformer.kt @@ -15,10 +15,12 @@ */ package com.epam.drill.agent.test.instrument.junit -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JUnit5Transformer: TransformerObject, AbstractJUnitTransformer() { - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/junit/platform/engine/support/hierarchical/NodeTestTaskContext" - } +actual object JUnit5Transformer: Transformer, AbstractJUnitTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/junit/platform/engine/support/hierarchical/NodeTestTaskContext" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt index 5856def1..9ab372ab 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -17,12 +17,14 @@ package com.epam.drill.agent.test.instrument.junit import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.ParameterDefinitions -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object JUnitPlatformPrioritizingTransformer: TransformerObject, AbstractJUnitTransformer() { +actual object JUnitPlatformPrioritizingTransformer: Transformer, AbstractJUnitTransformer() { override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/junit/platform/launcher/core/DefaultLauncher" - } + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/junit/platform/launcher/core/DefaultLauncher" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt index b884c074..49872007 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -17,13 +17,15 @@ package com.epam.drill.agent.test.instrument.selenium import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_SELENIUM_ENABLED -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject -actual object SeleniumTransformer: TransformerObject, AbstractTestTransformerObject() { +actual object SeleniumTransformer: Transformer, AbstractTestTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_SELENIUM_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/openqa/selenium/remote/RemoteWebDriver" - } + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/openqa/selenium/remote/RemoteWebDriver" } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt index 908681f4..648a53c4 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGPrioritizingTransformer.kt @@ -17,11 +17,10 @@ package com.epam.drill.agent.test.instrument.testng import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.ParameterDefinitions +import com.epam.drill.agent.instrument.InstrumentationParameterDefinitions.INSTRUMENTATION_TESTNG_ENABLED +import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject abstract class AbstractTestNGPrioritizingTransformer(): AbstractTestNGTransformer() { - override fun enabled(): Boolean = super.enabled() && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] - - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return interfaces.any { it == "org/testng/IMethodSelector" } - } + override fun enabled(): Boolean = super.enabled() + && Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED] } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt index cd448e7d..5d7d46f0 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/AbstractTestNGTransformer.kt @@ -22,7 +22,10 @@ import com.epam.drill.agent.test.instrument.AbstractTestTransformerObject abstract class AbstractTestNGTransformer(): AbstractTestTransformerObject() { override fun enabled() = super.enabled() && Configuration.parameters[INSTRUMENTATION_TESTNG_ENABLED] - override fun permit(className: String, superName: String?, interfaces: Array): Boolean { - return className == "org/testng/TestRunner" - } + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className.startsWith("org/testng/") + } \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt index 6fbb7713..9d20b7ec 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6PrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TestNG6PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() \ No newline at end of file +actual object TestNG6PrioritizingTransformer: Transformer, AbstractTestNGPrioritizingTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt index 2d41ad5f..f512e0ac 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG6Transformer.kt @@ -15,6 +15,12 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TestNG6Transformer: TransformerObject, AbstractTestNGTransformer() \ No newline at end of file +actual object TestNG6Transformer: Transformer, AbstractTestNGTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/testng/TestRunner" +} \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt index 9e651b7a..b9c0eee0 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7PrioritizingTransformer.kt @@ -15,6 +15,6 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TestNG7PrioritizingTransformer: TransformerObject, AbstractTestNGPrioritizingTransformer() \ No newline at end of file +actual object TestNG7PrioritizingTransformer: Transformer, AbstractTestNGPrioritizingTransformer() \ No newline at end of file diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt index 70d59f56..77c5fc51 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/testng/TestNG7Transformer.kt @@ -15,6 +15,12 @@ */ package com.epam.drill.agent.test.instrument.testng -import com.epam.drill.agent.instrument.TransformerObject +import com.epam.drill.agent.instrument.Transformer -actual object TestNG7Transformer: TransformerObject, AbstractTestNGTransformer() \ No newline at end of file +actual object TestNG7Transformer: Transformer, AbstractTestNGTransformer() { + override fun precheck( + className: String, + loader: Any?, + protectionDomain: Any? + ): Boolean = className == "org/testng/TestRunner" +} \ No newline at end of file From 4f16f4f04633933632820517ecfcce4ab09b616a Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 24 Feb 2026 14:14:24 +0100 Subject: [PATCH 12/14] refactor: update test tracing parameters and logic in agent configuration --- .../agent/configuration/ParameterDefinitions.kt | 4 ++-- .../test/execution/ThreadTestExecutionRecorder.kt | 12 +++++++----- .../test/instrument/AbstractTestTransformerObject.kt | 4 ++-- .../drill/agent/test/session/SessionController.kt | 8 ++++---- .../test/instrument/AbstractTestTransformerObject.kt | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 63293d7e..630d90e1 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -45,8 +45,6 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { AgentParameterDefinition.forBoolean(name = "useProtobufSerializer", defaultValue = true).register() val USE_GZIP_COMPRESSION = AgentParameterDefinition.forBoolean(name = "useGzipCompression", defaultValue = true).register() - val TEST_AGENT_ENABLED = AgentParameterDefinition.forBoolean(name = "testAgentEnabled", defaultValue = false).register() - val WITH_JS_COVERAGE = AgentParameterDefinition.forBoolean(name = "withJsCoverage", defaultValue = false).register() val PROXY_ADDRESS = AgentParameterDefinition.forString(name = "browserProxyAddress", defaultValue = "").register() val DEVTOOLS_PROXY_ADDRESS = AgentParameterDefinition.forString( @@ -79,5 +77,7 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val RECOMMENDED_TESTS_USE_MATERIALIZED_VIEWS = AgentParameterDefinition.forString(name = "recommendedTestsUseMaterializedViews", defaultValue = "").register() val TEST_TRACING_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingEnabled", defaultValue = true).register() + val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingTestSessionEnabled", defaultValue = true).register() + val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingTestLaunchEnabled", defaultValue = true).register() val TEST_LAUNCH_METADATA_SENDING_ENABLED = AgentParameterDefinition.forBoolean(name = "testLaunchMetadataSendingEnabled", defaultValue = true).register() } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt index 5e7dd616..02d258cf 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt @@ -113,14 +113,16 @@ class ThreadTestExecutionRecorder( private fun generateTestLaunchId() = UUID.randomUUID().toString() private fun addDrillHeaders(testLaunchId: String) { - val drillRequest = if (Configuration.parameters[ParameterDefinitions.TEST_TRACING_ENABLED]) { - DrillRequest( + val drillRequest = when { + Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_SESSION_ENABLED] -> DrillRequest( + drillSessionId = SessionController.getSessionId() + ) + Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_TEST_LAUNCH_ENABLED] -> DrillRequest( drillSessionId = SessionController.getSessionId(), headers = mapOf(TEST_ID_HEADER to (testLaunchId)) ) - } else { - DrillRequest(drillSessionId = SessionController.getSessionId()) - } + else -> null + } ?: return requestHolder.store(drillRequest) } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt index 6a3ffbdb..34f0a52d 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt @@ -16,7 +16,7 @@ package com.epam.drill.agent.test.instrument import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_AGENT_ENABLED +import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_TRACING_ENABLED import com.epam.drill.agent.instrument.AbstractTransformerObject import com.epam.drill.agent.instrument.ClassPathProvider import com.epam.drill.agent.instrument.RuntimeClassPathProvider @@ -26,7 +26,7 @@ import java.security.ProtectionDomain abstract class AbstractTestTransformerObject : AbstractTransformerObject(Configuration), ClassPathProvider by RuntimeClassPathProvider { - override fun enabled() = super.enabled() && Configuration.parameters[TEST_AGENT_ENABLED] + override fun enabled() = super.enabled() && Configuration.parameters[TEST_TRACING_ENABLED] override fun transform(className: String, ctClass: CtClass) { throw NotImplementedError("AbstractTestTransformerObject.transform is not implemented") diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt index 0fc214c7..4b0af0c8 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt @@ -54,8 +54,8 @@ actual object SessionController { } actual fun startSession() { - if (!isTestAgentEnabled()) { - logger.info { "Test agent is disabled. Test session will not be started." } + if (!isTestTracingEnabled()) { + logger.info { "Test tracing is disabled. Test session will not be started." } return } val customSessionId = Configuration.parameters[ParameterDefinitions.SESSION_ID] @@ -86,8 +86,8 @@ actual object SessionController { fun getSessionId(): String = sessionId - private fun isTestAgentEnabled(): Boolean = Configuration.parameters[ParameterDefinitions.TEST_AGENT_ENABLED] - private fun isTestLaunchMetadataSendingEnabled(): Boolean = isTestAgentEnabled() && Configuration.parameters[ParameterDefinitions.TEST_LAUNCH_METADATA_SENDING_ENABLED] + private fun isTestTracingEnabled(): Boolean = Configuration.parameters[ParameterDefinitions.TEST_TRACING_ENABLED] + private fun isTestLaunchMetadataSendingEnabled(): Boolean = isTestTracingEnabled() && Configuration.parameters[ParameterDefinitions.TEST_LAUNCH_METADATA_SENDING_ENABLED] } private fun List.toTestLaunchPayloads(): List = map { info -> diff --git a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt index 6461ead5..7208268c 100644 --- a/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt +++ b/java-agent/src/nativeMain/kotlin/com/epam/drill/agent/test/instrument/AbstractTestTransformerObject.kt @@ -16,9 +16,9 @@ package com.epam.drill.agent.test.instrument import com.epam.drill.agent.configuration.Configuration -import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_AGENT_ENABLED +import com.epam.drill.agent.configuration.ParameterDefinitions.TEST_TRACING_ENABLED import com.epam.drill.agent.instrument.AbstractTransformerObject abstract class AbstractTestTransformerObject: AbstractTransformerObject() { - override fun enabled() = super.enabled() && Configuration.parameters[TEST_AGENT_ENABLED] + override fun enabled() = super.enabled() && Configuration.parameters[TEST_TRACING_ENABLED] } \ No newline at end of file From e0f8f1b063ac1f33dc02cb931d9a215c3d2cd7f4 Mon Sep 17 00:00:00 2001 From: iryabov Date: Wed, 25 Feb 2026 10:06:32 +0100 Subject: [PATCH 13/14] refactor: rename test tracing parameters for consistency and clarity --- .../drill/agent/configuration/ParameterDefinitions.kt | 4 ++-- .../test/prioritization/RecommendedTestsReceiver.kt | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 630d90e1..1f846233 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -77,7 +77,7 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val RECOMMENDED_TESTS_USE_MATERIALIZED_VIEWS = AgentParameterDefinition.forString(name = "recommendedTestsUseMaterializedViews", defaultValue = "").register() val TEST_TRACING_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingEnabled", defaultValue = true).register() - val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingTestSessionEnabled", defaultValue = true).register() - val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingTestLaunchEnabled", defaultValue = true).register() + val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestSessionEnabled", defaultValue = true).register() + val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestLaunchEnabled", defaultValue = true).register() val TEST_LAUNCH_METADATA_SENDING_ENABLED = AgentParameterDefinition.forBoolean(name = "testLaunchMetadataSendingEnabled", defaultValue = true).register() } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt index 45de6b1a..3d6e5acf 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt @@ -54,14 +54,6 @@ class RecommendedTestsReceiverImpl( val baselineBuildVersion = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_BASELINE_BUILD_VERSION] .takeIf { it.isNotEmpty() } - val coveragePeriodDays = - Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_COVERAGE_PERIOD_DAYS].toInt() - .takeIf { it > 0 } - val useMaterializedViews = - Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_USE_MATERIALIZED_VIEWS] - .takeIf { it.isNotEmpty() } - ?.lowercase() - ?.toBooleanStrict() val parameters: String = buildString { append("?groupId=$groupId") @@ -72,8 +64,6 @@ class RecommendedTestsReceiverImpl( targetCommitSha?.let { append("&targetCommitSha=$it") } baselineCommitSha?.let { append("&baselineCommitSha=$it") } baselineBuildVersion?.let { append("&baselineBuildVersion=$it") } - coveragePeriodDays?.let { append("&coveragePeriodDays=$it") } - useMaterializedViews?.let { append("&useMaterializedViews=$it") } } logger.debug { "Retrieving information about recommended tests, testTaskId: $testTaskId" } return runCatching { From a8da5cfa0290fd0da0905f1542298ecc1d3c3923 Mon Sep 17 00:00:00 2001 From: iryabov Date: Wed, 25 Feb 2026 14:34:29 +0100 Subject: [PATCH 14/14] fix: make SeleniumTransformer initialization as a lazy function to avoid initialization errors when selenium is not used refactor: rename sessionId parameter to testSessionId for clarity --- .../configuration/ParameterDefinitions.kt | 3 +-- .../agent/instrument/CompositeTransformer.kt | 2 +- .../execution/ThreadTestExecutionRecorder.kt | 12 +++++++----- .../selenium/SeleniumTransformer.kt | 16 +++++++--------- .../agent/test/session/SessionController.kt | 19 +++++++++---------- .../agent/transport/JvmModuleMessageSender.kt | 3 --- 6 files changed, 25 insertions(+), 30 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 1f846233..9f433ddd 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -53,7 +53,7 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { parser = { it.trim().takeIf(String::isBlank) ?: it.takeIf(URL_SCHEME_REGEX::matches) ?: "http://$it"} ).register() val DEVTOOLS_REPLACE_LOCALHOST = AgentParameterDefinition.forString(name = "devtoolsAddressReplaceLocalhost", defaultValue = "").register() - val SESSION_ID = NullableAgentParameterDefinition.forString(name = "sessionId").register() + val TEST_SESSION_ID = NullableAgentParameterDefinition.forString(name = "testSessionId").register() val LAUNCH_TYPE = AgentParameterDefinition.forString(name = "launchType", defaultValue = "").register() val FRAMEWORK_PLUGINS = AgentParameterDefinition.forType( name = "rawFrameworkPlugins", @@ -79,5 +79,4 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val TEST_TRACING_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingEnabled", defaultValue = true).register() val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestSessionEnabled", defaultValue = true).register() val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestLaunchEnabled", defaultValue = true).register() - val TEST_LAUNCH_METADATA_SENDING_ENABLED = AgentParameterDefinition.forBoolean(name = "testLaunchMetadataSendingEnabled", defaultValue = true).register() } diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt index 00deb8d8..7192757d 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/instrument/CompositeTransformer.kt @@ -40,7 +40,7 @@ actual object CompositeTransformer : Transformer { .onFailure { logger.warn(it) { "Can't read class: $classFileBuffer" } } .getOrNull() ?: return null val enabledTransformers = runCatching { transformers.enabledTransformers }.onFailure { - logger.warn(it) { "Can't get enabled transformers for class: $className" } + logger.warn { "Can't get enabled transformers for class: $className: " + it.message } }.getOrNull() ?: return null return enabledTransformers.fold(classFileBuffer) { bytes, transformer -> runCatching { diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt index 02d258cf..d09d59e5 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/execution/ThreadTestExecutionRecorder.kt @@ -63,7 +63,6 @@ class ThreadTestExecutionRecorder( } clearDrillHeaders() listeners.forEach { it.onTestFinished(testLaunchId, testMethod, testResult) } - println("Test: $testMethod FINISHED") logger.debug { "Test: $testMethod FINISHED. Result: $status" } } @@ -113,14 +112,17 @@ class ThreadTestExecutionRecorder( private fun generateTestLaunchId() = UUID.randomUUID().toString() private fun addDrillHeaders(testLaunchId: String) { + val isTestTracingPerTestLaunchEnabled = Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_TEST_LAUNCH_ENABLED] + val isTestTracingPerSessionEnabled = Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_SESSION_ENABLED] + val drillRequest = when { - Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_SESSION_ENABLED] -> DrillRequest( - drillSessionId = SessionController.getSessionId() - ) - Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_TEST_LAUNCH_ENABLED] -> DrillRequest( + isTestTracingPerTestLaunchEnabled -> DrillRequest( drillSessionId = SessionController.getSessionId(), headers = mapOf(TEST_ID_HEADER to (testLaunchId)) ) + isTestTracingPerSessionEnabled -> DrillRequest( + drillSessionId = SessionController.getSessionId() + ) else -> null } ?: return requestHolder.store(drillRequest) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt index 200b4cf0..4452abda 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/selenium/SeleniumTransformer.kt @@ -40,24 +40,22 @@ actual object SeleniumTransformer : Transformer, AbstractTestTransformerObject() private const val EXTENSION_NAME = "header-transmitter.xpi" private val FirefoxDriver = "org.openqa.selenium.firefox.FirefoxDriver" - private var extensionFile: String? = null - - internal const val addDrillCookiesMethod = "addDrillCookies" - private const val isFirefoxBrowser = "isFirefoxBrowser" - override val logger: KLogger = KotlinLogging.logger {} - - init { + private val extensionFile by lazy { val extension = this::class.java.getResource("/$EXTENSION_NAME") if (extension != null) { File(System.getProperty("java.io.tmpdir")).resolve(EXTENSION_NAME).apply { - extensionFile = absolutePath writeBytes(extension.readBytes()) - } + }.absolutePath } else { logger.warn { "Failed to load extension file: $EXTENSION_NAME" } + null } } + internal const val addDrillCookiesMethod = "addDrillCookies" + private const val isFirefoxBrowser = "isFirefoxBrowser" + override val logger: KLogger = KotlinLogging.logger {} + override fun enabled() = super.enabled() && agentConfiguration.parameters[INSTRUMENTATION_SELENIUM_ENABLED] override fun permit(className: String, superName: String?, interfaces: Array): Boolean { diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt index 4b0af0c8..59bca13d 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/session/SessionController.kt @@ -48,21 +48,22 @@ actual object SessionController { ) private lateinit var sessionId: String - init { - if (isTestLaunchMetadataSendingEnabled()) - Runtime.getRuntime().addShutdownHook(Thread { testInfoSender.stopSendingTests() }) - } actual fun startSession() { if (!isTestTracingEnabled()) { - logger.info { "Test tracing is disabled. Test session will not be started." } + logger.info { "Test tracing is disabled." } return } - val customSessionId = Configuration.parameters[ParameterDefinitions.SESSION_ID] + logger.info { "Test tracing is enabled." } + val customSessionId = Configuration.parameters[ParameterDefinitions.TEST_SESSION_ID] sessionId = customSessionId ?: uuid4().toString() DrillInitialContext.add(SESSION_ID_HEADER, sessionId) DrillRequestHolder.store(DrillRequest(sessionId)) - logger.info { "Test session started: $sessionId" } + logger.info { "Test session: $sessionId" } + + testInfoSender.startSendingTests() + Runtime.getRuntime().addShutdownHook(Thread { testInfoSender.stopSendingTests() }) + val builds = takeIf { Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_APP_ID].isNotEmpty() }?.let { SingleSessionBuildPayload( @@ -80,14 +81,12 @@ actual object SessionController { builds = builds ) ) - if (isTestLaunchMetadataSendingEnabled()) - testInfoSender.startSendingTests() } fun getSessionId(): String = sessionId private fun isTestTracingEnabled(): Boolean = Configuration.parameters[ParameterDefinitions.TEST_TRACING_ENABLED] - private fun isTestLaunchMetadataSendingEnabled(): Boolean = isTestTracingEnabled() && Configuration.parameters[ParameterDefinitions.TEST_LAUNCH_METADATA_SENDING_ENABLED] + private fun isTestLaunchMetadataSendingEnabled(): Boolean = isTestTracingEnabled() && Configuration.parameters[ParameterDefinitions.TEST_TRACING_PER_TEST_LAUNCH_ENABLED] } private fun List.toTestLaunchPayloads(): List = map { info -> diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/JvmModuleMessageSender.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/JvmModuleMessageSender.kt index 8150a767..90c35b54 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/JvmModuleMessageSender.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/transport/JvmModuleMessageSender.kt @@ -15,7 +15,6 @@ */ package com.epam.drill.agent.transport -import com.epam.drill.agent.common.configuration.AgentMetadata import java.io.File import io.aesy.datasize.ByteUnit import io.aesy.datasize.DataSize @@ -24,12 +23,10 @@ import com.epam.drill.agent.configuration.Configuration import com.epam.drill.agent.configuration.DefaultParameterDefinitions import com.epam.drill.agent.configuration.ParameterDefinitions import com.epam.drill.agent.transport.http.HttpAgentMessageTransport -import com.epam.drill.agent.common.transport.AgentMessage import com.epam.drill.agent.common.transport.AgentMessageDestination import com.epam.drill.agent.common.transport.AgentMessageSender import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable actual object JvmModuleMessageSender : AgentMessageSender {