From 685cf2c27d7e9b88887eb10f172a8d7eeeb29802 Mon Sep 17 00:00:00 2001 From: Taejin Koo Date: Wed, 8 Dec 2021 18:25:50 +0900 Subject: [PATCH] [#8472] Support Kotlin Coroutines Plugin IT --- plugins-it/kotlin-coroutines-it/pom.xml | 59 +++++++ .../kotlinx/coroutines/CoroutinesIT.java | 145 ++++++++++++++++++ .../kotlinx/coroutines/CoroutinesLaunch.kt | 61 ++++++++ .../test/resources/pinpoint-coroutines.config | 2 + plugins-it/pom.xml | 1 + 5 files changed, 268 insertions(+) create mode 100644 plugins-it/kotlin-coroutines-it/pom.xml create mode 100644 plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesIT.java create mode 100644 plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesLaunch.kt create mode 100644 plugins-it/kotlin-coroutines-it/src/test/resources/pinpoint-coroutines.config diff --git a/plugins-it/kotlin-coroutines-it/pom.xml b/plugins-it/kotlin-coroutines-it/pom.xml new file mode 100644 index 000000000000..6026c5c31568 --- /dev/null +++ b/plugins-it/kotlin-coroutines-it/pom.xml @@ -0,0 +1,59 @@ + + + + com.navercorp.pinpoint + pinpoint-plugins-it + 2.4.0-SNAPSHOT + + 4.0.0 + + pinpoint-kotlin-coroutines-plugin-it + + jar + + + 1.8 + ${env.JAVA_8_HOME} + java18 + + + + + com.navercorp.pinpoint + pinpoint-kotlin-coroutines-plugin + ${project.version} + test + + + com.navercorp.pinpoint + pinpoint-plugin-it-utils + ${project.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + 1.5.2 + + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + + \ No newline at end of file diff --git a/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesIT.java b/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesIT.java new file mode 100644 index 000000000000..91e6b3619225 --- /dev/null +++ b/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesIT.java @@ -0,0 +1,145 @@ +/* + * Copyright 2021 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.kotlinx.coroutines; + +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; +import com.navercorp.pinpoint.pluginit.utils.AgentPath; +import com.navercorp.pinpoint.test.plugin.Dependency; +import com.navercorp.pinpoint.test.plugin.ImportPlugin; +import com.navercorp.pinpoint.test.plugin.JvmVersion; +import com.navercorp.pinpoint.test.plugin.PinpointAgent; +import com.navercorp.pinpoint.test.plugin.PinpointConfig; +import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Taejin Koo + */ +@RunWith(PinpointPluginTestSuite.class) +@PinpointAgent(AgentPath.PATH) +@PinpointConfig("pinpoint-coroutines.config") +@ImportPlugin({"com.navercorp.pinpoint:pinpoint-kotlin-coroutines-plugin"}) +@Dependency({ + "log4j:log4j:[1.2.17]", + "org.jetbrains.kotlinx:kotlinx-coroutines-core:[1.0.1,)" +}) +@JvmVersion(8) +public class CoroutinesIT { + + private static final String DISPATCH_METHOD = ".dispatch("; + private static final String RUN_METHOD = ".runSafely("; + private static final String ASYNC_INVOCATION = "Asynchronous Invocation"; + + @Test + public void executeOneLaunchBlockTest() { + int minimumExpectedCount = 7; + int launchBlockCount = 1; + int expectedExecutedRunSafelyCount = 2; + + // This test has 1 ~ 2 executed Async Invocation + // This test has 2 executed runSafely() + CoroutinesLaunch coroutinesLaunch = new CoroutinesLaunch(); + coroutinesLaunch.execute("pinpoint-test"); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + List executedMethod = verifier.getExecutedMethod(); + + AtomicInteger index = new AtomicInteger(); + + // dispatch runblocking + Assert.assertTrue(executedMethod.size() >= minimumExpectedCount); + assertFirstDispatch(executedMethod, index); + for (int i = 0; i < launchBlockCount; i++) { + // dispatch launch job + Assert.assertTrue(executedMethod.get(index.getAndIncrement()).contains(DISPATCH_METHOD)); + } + + final String[] executeActualMethods = Arrays.copyOfRange(executedMethod.toArray(new String[0]), index.get(), executedMethod.size()); + Assert.assertTrue(assertExecutedCount(executeActualMethods, RUN_METHOD, expectedExecutedRunSafelyCount)); + Assert.assertTrue(assertExecutedCount(executeActualMethods, ASYNC_INVOCATION, executeActualMethods.length - expectedExecutedRunSafelyCount)); + } + + @Test + public void executeTwoLaunchBlockTest() { + int minimumExpectedCount = 10; + int launchBlockCount = 2; + int expectedExecutedRunSafelyCount = 4; + + + // This test has 1 ~ 4 executed Async Invocation + // This test has 4 executed runSafely() + CoroutinesLaunch coroutinesLaunch = new CoroutinesLaunch(); + coroutinesLaunch.execute2("pinpoint-test"); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + List executedMethod = verifier.getExecutedMethod(); + + AtomicInteger index = new AtomicInteger(); + + // dispatch runblocking + Assert.assertTrue(executedMethod.size() >= minimumExpectedCount); + assertFirstDispatch(executedMethod, index); + for (int i = 0; i < launchBlockCount; i++) { + // dispatch launch job + Assert.assertTrue(executedMethod.get(index.getAndIncrement()).contains(DISPATCH_METHOD)); + } + + final String[] executeActualMethods = Arrays.copyOfRange(executedMethod.toArray(new String[0]), index.get(), executedMethod.size()); + Assert.assertTrue(assertExecutedCount(executeActualMethods, RUN_METHOD, expectedExecutedRunSafelyCount)); + Assert.assertTrue(assertExecutedCount(executeActualMethods, ASYNC_INVOCATION, executeActualMethods.length - expectedExecutedRunSafelyCount)); + } + + + private void assertFirstDispatch(List executedMethod, AtomicInteger index) { + Assert.assertTrue(executedMethod.get(index.getAndIncrement()).contains(DISPATCH_METHOD)); + Assert.assertTrue(executedMethod.get(index.getAndIncrement()).equals(ASYNC_INVOCATION)); + // run dispatchedContinuation + Assert.assertTrue(executedMethod.get(index.getAndIncrement()).contains(RUN_METHOD)); + } + + private boolean assertExecutedCount(String[] executeActualMethod, String expectedActualMethod, int expectedCount) { + long count = Arrays.stream(executeActualMethod).filter(e -> e.contains(expectedActualMethod)).count(); + return count == expectedCount; + } + + @Test + public void executeCurrentThreadTest() { + int expectedCount = 2; + + // This test has 0 executed Async Invocation + // This test has 0 executed runSafely() + CoroutinesLaunch coroutinesLaunch = new CoroutinesLaunch(); + coroutinesLaunch.executeParentDispatcher("pinpoint-test"); + + // executes 2 times dispatch + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + + List executedMethod = verifier.getExecutedMethod(); + Assert.assertEquals(expectedCount, executedMethod.size()); + Assert.assertTrue(executedMethod.get(0).contains(DISPATCH_METHOD)); + Assert.assertTrue(executedMethod.get(1).contains(DISPATCH_METHOD)); + } + +} diff --git a/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesLaunch.kt b/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesLaunch.kt new file mode 100644 index 000000000000..600cfdbd106a --- /dev/null +++ b/plugins-it/kotlin-coroutines-it/src/test/java/com/navercorp/pinpoint/plugin/kotlinx/coroutines/CoroutinesLaunch.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2021 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.kotlinx.coroutines + +import kotlinx.coroutines.* +import java.util.* + +/** + * @author Taejin Koo + */ +class CoroutinesLaunch { + + fun execute(coroutineName: String) { + runBlocking(CoroutineName(coroutineName) + Dispatchers.Default) { + execute0(coroutineName) + } + } + + // Concurrently executes both sections + suspend fun execute0(firstName: String, secondName: String = UUID.randomUUID().toString()) = + coroutineScope { // this: CoroutineScope + val job = async(CoroutineName(firstName)) { + delay(10L) + println("Hello World 1") + } + launch(CoroutineName(secondName)) { + delay(5L) + println("Hello World 2") + } + job.join() + println("Hello World") + } + + fun execute2(coroutineName: String) { + runBlocking(CoroutineName(coroutineName) + Dispatchers.Default) { + execute0(coroutineName, coroutineName) + } + } + + fun executeParentDispatcher(coroutineName: String) { + runBlocking(CoroutineName(coroutineName)) { + execute0(coroutineName) + } + } + + +} \ No newline at end of file diff --git a/plugins-it/kotlin-coroutines-it/src/test/resources/pinpoint-coroutines.config b/plugins-it/kotlin-coroutines-it/src/test/resources/pinpoint-coroutines.config new file mode 100644 index 000000000000..e4bac8e1b34b --- /dev/null +++ b/plugins-it/kotlin-coroutines-it/src/test/resources/pinpoint-coroutines.config @@ -0,0 +1,2 @@ +profiler.kotlin.coroutines.enable=true +profiler.kotlin.coroutines.name.include=pinpoint-test \ No newline at end of file diff --git a/plugins-it/pom.xml b/plugins-it/pom.xml index 30ddbe043e11..6c19dd063449 100644 --- a/plugins-it/pom.xml +++ b/plugins-it/pom.xml @@ -78,6 +78,7 @@ oracledb-it paho-mqtt-it kafka-it + kotlin-coroutines-it lambda-it