From 6c14981f68bb5c98494c48bdd95565633f8f4b06 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Tue, 7 May 2024 20:56:09 +0200 Subject: [PATCH] chore: fix coverage config --- build.gradle.kts | 22 ++++- gradle/libs.versions.toml | 1 - packages/jetbrains-plugin/build.gradle.kts | 10 +-- .../jbplugin/observability/LogMessage.kt | 10 +-- .../RuntimeInformationService.kt | 4 +- .../jbplugin/observability/TelemetryEvent.kt | 41 +++++++++- .../observability/TelemetryService.kt | 2 +- .../probe/PluginActivatedProbe.kt | 2 +- .../jbplugin/observability/LogMessageTest.kt | 2 +- .../RuntimeInformationServiceTest.kt | 82 +++++++++++++++++++ .../observability/TelemetryServiceTest.kt | 29 +++++++ 11 files changed, 179 insertions(+), 26 deletions(-) create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationServiceTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 9caa5a56..f8e6a9f6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension group = "com.mongodb" // This should be bumped when releasing a new version using the versionBump task: @@ -8,15 +9,16 @@ version="0.0.1" plugins { alias(libs.plugins.versions) + id("jacoco") } buildscript { repositories { maven("https://plugins.gradle.org/m2/") } + dependencies { classpath(libs.buildScript.plugin.kotlin) - classpath(libs.buildScript.plugin.ktlint) classpath(libs.buildScript.plugin.versions) classpath(libs.buildScript.plugin.spotless) } @@ -25,7 +27,6 @@ buildscript { subprojects { apply(plugin = "java") apply(plugin = "org.jetbrains.kotlin.jvm") - apply(plugin = "org.jlleitschuh.gradle.ktlint") apply(plugin = "com.github.ben-manes.versions") apply(plugin = "com.diffplug.spotless") apply(plugin = "jacoco") @@ -57,6 +58,23 @@ subprojects { withType { useJUnitPlatform() + + extensions.configure(JacocoTaskExtension::class) { + isJmx = true + includes = listOf("com.mongodb.*") + isIncludeNoLocationClasses = true + } + + jacoco { + toolVersion = "0.8.12" + isScanForTestClasses = true + } + + forkEvery = 0 + + jvmArgs(listOf( + "--add-opens=java.base/java.lang=ALL-UNNAMED" + )) } withType { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd6ae2e3..735b1ff9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -60,7 +60,6 @@ testing-jmh-annotationProcessor={ group="org.openjdk.jmh", name="jmh-generator-a testing-jmh-generatorByteCode={ group="org.openjdk.jmh", name="jmh-generator-bytecode", version.ref="jmh" } buildScript-plugin-kotlin={ group="org.jetbrains.kotlin", name="kotlin-gradle-plugin", version="1.9.23" } -buildScript-plugin-ktlint={ group="org.jlleitschuh.gradle", name="ktlint-gradle", version="12.1.0" } buildScript-plugin-versions={ group="com.github.ben-manes", name="gradle-versions-plugin", version.ref="versions-plugin" } buildScript-plugin-spotless={ group="com.diffplug.spotless", name="spotless-plugin-gradle", version="6.25.0" } buildScript-plugin-cyclonedx={ group="org.cyclonedx", name="cyclonedx-gradle-plugin", version.ref="cyclonedx-plugin" } \ No newline at end of file diff --git a/packages/jetbrains-plugin/build.gradle.kts b/packages/jetbrains-plugin/build.gradle.kts index 809995b3..444d36ee 100644 --- a/packages/jetbrains-plugin/build.gradle.kts +++ b/packages/jetbrains-plugin/build.gradle.kts @@ -45,8 +45,8 @@ dependencies { jmh(libs.testing.jmh.annotationProcessor) jmh(libs.testing.jmh.generatorByteCode) - testImplementation(libs.testing.intellij.ideImpl) - testImplementation(libs.testing.intellij.coreUi) + testCompileOnly(libs.testing.intellij.ideImpl) + testCompileOnly(libs.testing.intellij.coreUi) testImplementation(libs.testing.remoteRobot) testImplementation(libs.testing.remoteRobotDeps.remoteFixtures) @@ -103,12 +103,6 @@ tasks { publishPlugin { token.set(System.getenv("PUBLISH_TOKEN")) } - - test { - jvmArgs = listOf( - "--add-opens=java.base/java.lang=ALL-UNNAMED" - ) - } } changelog { diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/LogMessage.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/LogMessage.kt index 837d0430..0155c5ca 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/LogMessage.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/LogMessage.kt @@ -43,7 +43,7 @@ internal class LogMessageBuilder(private val gson: Gson, message: String) { * * @param project */ -@Service +@Service(Service.Level.PROJECT) internal class LogMessage(private val project: Project) { private val gson = GsonBuilder().generateNonExecutableJson().disableJdkUnsafe().create() @@ -60,12 +60,4 @@ internal class LogMessage(private val project: Project) { .put("buildVersion", runtimeInformation.buildVersion) .put("ide", runtimeInformation.applicationName) } - - private fun getOrDefault(default: T, supplier: () -> T): T { - return try { - supplier() - } catch (ex: Throwable) { - return default - } - } } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationService.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationService.kt index 2f330999..c8d7ed1d 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationService.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationService.kt @@ -60,9 +60,9 @@ class RuntimeInformationService { applicationName ) - private fun getOrDefault(default: T, supplier: () -> T): T { + private fun getOrDefault(default: T, supplier: () -> T?): T { return try { - supplier() + supplier() ?: default } catch (ex: Throwable) { return default } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryEvent.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryEvent.kt index 1a4eaf66..0c650747 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryEvent.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryEvent.kt @@ -12,7 +12,16 @@ package com.mongodb.jbplugin.observability * * @property publicName Name of the field in Segment. */ -internal enum class TelemetryProperty(val publicName: String) +internal enum class TelemetryProperty(val publicName: String) { + IS_ATLAS("is_atlas"), + IS_LOCALHOST("is_localhost"), + IS_ENTERPRISE("is_enterprise"), + IS_GENUINE("is_genuine"), + NON_GENUINE_SERVER_NAME("non_genuine_server_name"), + SERVER_OS_FAMILY("server_os_family"), + VERSION("version"), + ; +} /** * Represents an event that will be sent to Segment. Essentially, all @@ -32,4 +41,34 @@ internal sealed class TelemetryEvent( name = "plugin-activated", properties = emptyMap() ) + + /** + * @param isAtlas + * @param isLocalhost + * @param isEnterprise + * @param isGenuine + * @param nonGenuineServerName + * @param serverOsFamily + * @param version + */ + internal class NewConnection( + isAtlas: Boolean, + isLocalhost: Boolean, + isEnterprise: Boolean, + isGenuine: Boolean, + nonGenuineServerName: String?, + serverOsFamily: String?, + version: String? + ) : TelemetryEvent( + name = "new-connection", + properties = mapOf( + TelemetryProperty.IS_ATLAS to isAtlas, + TelemetryProperty.IS_LOCALHOST to isLocalhost, + TelemetryProperty.IS_ENTERPRISE to isEnterprise, + TelemetryProperty.IS_GENUINE to isGenuine, + TelemetryProperty.NON_GENUINE_SERVER_NAME to (nonGenuineServerName ?: ""), + TelemetryProperty.SERVER_OS_FAMILY to (serverOsFamily ?: ""), + TelemetryProperty.VERSION to (version ?: "") + ) + ) } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt index 0dd1d72d..186b246d 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt @@ -12,7 +12,7 @@ import com.segment.analytics.messages.TrackMessage * * @param project */ -@Service +@Service(Service.Level.PROJECT) internal class TelemetryService(private val project: Project) { internal var analytics: Analytics = Analytics.builder("KEY").build() diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/probe/PluginActivatedProbe.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/probe/PluginActivatedProbe.kt index 8e22274c..cc1672b7 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/probe/PluginActivatedProbe.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/probe/PluginActivatedProbe.kt @@ -15,7 +15,7 @@ private val logger: Logger = logger() * * @param project Project where the plugin is set up */ -@Service +@Service(Service.Level.PROJECT) class PluginActivatedProbe(private val project: Project) { fun pluginActivated() { val telemetry = project.getService(TelemetryService::class.java) diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/LogMessageTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/LogMessageTest.kt index 64097d77..e1d51ed8 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/LogMessageTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/LogMessageTest.kt @@ -5,7 +5,7 @@ import com.mongodb.jbplugin.mockProject import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -class LogMessageTest { +open class LogMessageTest { private val gson: Gson = Gson() @Test diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationServiceTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationServiceTest.kt new file mode 100644 index 00000000..49871ff5 --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/RuntimeInformationServiceTest.kt @@ -0,0 +1,82 @@ +package com.mongodb.jbplugin.observability + +import com.intellij.openapi.application.ApplicationInfo +import com.intellij.openapi.application.PermanentInstallationID +import com.intellij.openapi.util.SystemInfo +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.MockedStatic +import org.mockito.Mockito.`when` +import org.mockito.Mockito.mock +import org.mockito.Mockito.mockStatic + +class RuntimeInformationServiceTest { + private lateinit var permanentInstallationId: MockedStatic + private lateinit var applicationInfo: MockedStatic + private lateinit var systemInfo: MockedStatic + + @BeforeEach + fun setUp() { + permanentInstallationId = mockStatic(PermanentInstallationID::class.java) + applicationInfo = mockStatic(ApplicationInfo::class.java) + systemInfo = mockStatic(SystemInfo::class.java) + } + + @AfterEach + fun tearDown() { + permanentInstallationId.closeOnDemand() + applicationInfo.closeOnDemand() + systemInfo.closeOnDemand() + } + + @Test + fun `loads all information from runtime`() { + permanentInstallationId.`when` { + PermanentInstallationID.get() + }.thenReturn("123456") + + val appInfoInstance = mock().apply { + `when`(this.fullApplicationName).thenReturn("Test Application") + `when`(this.fullVersion).thenReturn("1984.1.1") + } + + applicationInfo.`when` { + ApplicationInfo.getInstance() + }.thenReturn(appInfoInstance) + + systemInfo.`when` { + SystemInfo.getOsNameAndVersion() + }.thenReturn("Test OS 2708") + + val service = RuntimeInformationService() + + val runtimeInfo = service.get() + assertEquals("123456", runtimeInfo.userId) + assertEquals("Test OS 2708", runtimeInfo.osName) + assertNotNull(runtimeInfo.arch) + assertNotNull(runtimeInfo.jvmVendor) + assertNotNull(runtimeInfo.jvmVersion) + assertEquals("Test Application", runtimeInfo.applicationName) + assertEquals("1984.1.1", runtimeInfo.buildVersion) + } + + @Test + fun `loads the default value on exception`() { + permanentInstallationId.`when` { + PermanentInstallationID.get() + }.thenThrow(RuntimeException("Oops, I did it again.")) + + val appInfoInstance = mock().apply { + `when`(this.fullApplicationName).thenReturn("Test Application") + `when`(this.fullVersion).thenReturn("1984.1.1") + } + + val service = RuntimeInformationService() + + val runtimeInfo = service.get() + assertEquals("", runtimeInfo.userId) + } +} diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt index 2ac35c6c..cc491ead 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt @@ -29,4 +29,33 @@ internal class TelemetryServiceTest { } ) } + + @Test + fun `sends a new connection event as a tracking event`() { + val mockRuntimeInfo = mockRuntimeInformationService(userId = "654321") + val service = TelemetryService(mockProject( + runtimeInformationService = mockRuntimeInfo + )).apply { + analytics = mock() + } + + service.sendEvent(TelemetryEvent.NewConnection( + isAtlas = true, + isLocalhost = false, + isEnterprise = true, + isGenuine = true, + nonGenuineServerName = null, + serverOsFamily = null, + version = "8.0" + )) + + verify(service.analytics).enqueue( + argThat { + build().let { + it.userId() == "654321" && + it.type().name == "track" + } + } + ) + } }