From cb1566082fdb01f4a12816c9ed53b9d863f88b5e Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 29 Jan 2025 17:23:13 +0000 Subject: [PATCH 1/4] Gradle updated to use libs.versions.toml JAVA-5291 --- bson-kotlin/build.gradle.kts | 16 +- bson-kotlinx/build.gradle.kts | 32 ++- build.gradle | 111 ++++------ driver-benchmarks/build.gradle | 2 +- driver-core/build.gradle | 37 ++-- driver-kotlin-coroutine/build.gradle.kts | 33 ++- driver-kotlin-extensions/build.gradle.kts | 22 +- driver-kotlin-sync/build.gradle.kts | 25 +-- driver-lambda/build.gradle | 22 +- driver-reactive-streams/build.gradle | 15 +- driver-sync/build.gradle | 2 +- driver-workload-executor/build.gradle | 20 +- graalvm-native-image-app/build.gradle | 15 +- gradle/libs.versions.toml | 178 +++++++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 257 +++++++++++++--------- mongodb-crypt/build.gradle.kts | 17 +- 18 files changed, 480 insertions(+), 326 deletions(-) create mode 100644 gradle/libs.versions.toml diff --git a/bson-kotlin/build.gradle.kts b/bson-kotlin/build.gradle.kts index 45e8c9c0e5d..84b6deabd31 100644 --- a/bson-kotlin/build.gradle.kts +++ b/bson-kotlin/build.gradle.kts @@ -18,12 +18,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.kotlin.jvm") - `java-library` + id("java-library") // Test based plugins - id("com.diffplug.spotless") - id("org.jetbrains.dokka") - id("io.gitlab.arturbosch.detekt") + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.detekt) } repositories { @@ -39,13 +39,13 @@ ext.set("pomName", "Bson Kotlin") dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) api(project(path = ":bson", configuration = "default")) - implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation(libs.kotlin.reflect) - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") + testImplementation(libs.junit.kotlin) testImplementation(project(path = ":driver-core", configuration = "default")) } diff --git a/bson-kotlinx/build.gradle.kts b/bson-kotlinx/build.gradle.kts index ac0b07f18eb..d2b3e13919b 100644 --- a/bson-kotlinx/build.gradle.kts +++ b/bson-kotlinx/build.gradle.kts @@ -19,12 +19,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.kotlin.jvm") kotlin("plugin.serialization") - `java-library` + id("java-library") // Test based plugins - id("com.diffplug.spotless") - id("org.jetbrains.dokka") - id("io.gitlab.arturbosch.detekt") + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.detekt) } repositories { @@ -38,10 +38,6 @@ description = "Bson Kotlinx Codecs" ext.set("pomName", "Bson Kotlinx") -ext.set("kotlinxDatetimeVersion", "0.4.0") - -val kotlinxDatetimeVersion: String by ext - java { registerFeature("dateTimeSupport") { usingSourceSet(sourceSets["main"]) } registerFeature("jsonSupport") { usingSourceSet(sourceSets["main"]) } @@ -49,21 +45,21 @@ java { dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) - implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.5.0")) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-core") - "dateTimeSupportImplementation"("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDatetimeVersion") - "jsonSupportImplementation"("org.jetbrains.kotlinx:kotlinx-serialization-json") + implementation(platform(libs.kotlinx.serialization)) + implementation(libs.kotlinx.serialization.core) + "dateTimeSupportImplementation"(libs.kotlinx.serialization.datetime) + "jsonSupportImplementation"(libs.kotlinx.serialization.json) api(project(path = ":bson", configuration = "default")) - implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation(libs.kotlin.reflect) - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") testImplementation(project(path = ":driver-core", configuration = "default")) - testImplementation("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDatetimeVersion") - testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json") + testImplementation(libs.junit.kotlin) + testImplementation(libs.kotlinx.serialization.datetime) + testImplementation(libs.kotlinx.serialization.json) } kotlin { explicitApi() } diff --git a/build.gradle b/build.gradle index 4715dfb27ff..3e22e54aa6b 100644 --- a/build.gradle +++ b/build.gradle @@ -14,33 +14,21 @@ * limitations under the License. */ -apply plugin: 'eclipse' -apply plugin: 'idea' - -buildscript { - repositories { - mavenLocal() - mavenCentral() - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:7.0.0' - classpath "com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.15" - classpath 'biz.aQute.bnd:biz.aQute.bnd.gradle:5.1.2' - - // Scala plugins - classpath "com.adtran:scala-multiversion-plugin:2.0.4" - classpath "com.diffplug.spotless:spotless-plugin-gradle:6.14.0" - - // kotlin plugins - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10" - classpath "org.jetbrains.kotlin:kotlin-serialization:1.8.10" - classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10" - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.21.0" - - // Test logging plugin - classpath 'com.adarshr:gradle-test-logger-plugin:2.1.0' - } +plugins { + id("eclipse") + id("idea") + + alias(libs.plugins.bnd) apply false + alias(libs.plugins.detekt) apply false + alias(libs.plugins.dokka) apply false + alias(libs.plugins.download) apply false + alias(libs.plugins.kotlin) apply false + alias(libs.plugins.kotlin.serialization) apply false + alias(libs.plugins.optional) apply false + alias(libs.plugins.scala.multiversion) apply false + alias(libs.plugins.spotbugs) apply false + alias(libs.plugins.spotless) apply false + alias(libs.plugins.test.logger) apply false } ////////////////////////////////////////// @@ -49,17 +37,6 @@ buildscript { ext { configDir = new File(rootDir, 'config') - jnrUnixsocketVersion = '0.38.17' - nettyVersion = '4.1.87.Final' - snappyVersion = '1.1.10.3' - zstdVersion = '1.5.5-3' - awsSdkV2Version = '2.18.9' - awsSdkV1Version = '1.12.337' - projectReactorVersion = '2022.0.0' - junitBomVersion = '5.10.2' - logbackVersion = '1.3.14' - graalSdkVersion = '24.0.0' - reflectionsVersion = '0.9.10' gitVersion = getGitVersion() } @@ -110,27 +87,21 @@ configure(javaProjects) { } configure(scalaProjects) { - apply plugin: 'scala' - apply plugin: 'java-library' - apply plugin: 'idea' + apply plugin: "java-library" + apply plugin: "scala" apply plugin: "com.adtran.scala-multiversion-plugin" apply plugin: "com.diffplug.spotless" group = 'org.mongodb.scala' dependencies { - api ('org.scala-lang:scala-library:%scala-version%') - api ('org.scala-lang:scala-reflect:%scala-version%') - - testImplementation(platform("org.junit:junit-bom:$junitBomVersion")) - testImplementation("org.junit.vintage:junit-vintage-engine") - - testImplementation('org.scalatest:scalatest-flatspec_%%:3.2.9') - testImplementation('org.scalatest:scalatest-shouldmatchers_%%:3.2.9') - testImplementation('org.scalatestplus:junit-4-13_%%:3.2.9.0') - testImplementation('org.scalatestplus:mockito-3-12_%%:3.2.10.0') - testImplementation("ch.qos.logback:logback-classic:$logbackVersion") - testImplementation("org.reflections:reflections:$reflectionsVersion") + api(libs.scala.library) + api(libs.scala.reflect) + + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.bundles.junit.vintage) + testImplementation(libs.bundles.scalatest) + testImplementation(libs.reflections) } test{ @@ -178,12 +149,12 @@ configure(javaMainProjects) { apply plugin: 'java-library' dependencies { - compileOnly 'com.google.code.findbugs:jsr305:1.3.9' - api 'org.slf4j:slf4j-api:1.7.6', optional - testImplementation 'com.google.code.findbugs:jsr305:1.3.9' + compileOnly(libs.findbugs.jsr) + api(libs.slf4j, optional) + testImplementation(libs.findbugs.jsr) // https://issues.apache.org/jira/browse/GROOVY-10194 - testImplementation 'org.codehaus.groovy:groovy-all:3.0.9' + testImplementation(libs.groovy) } /* Compiling */ @@ -252,25 +223,19 @@ configure(javaCodeCheckedProjects) { apply plugin: 'com.adarshr.test-logger' dependencies { - testImplementation(platform("org.junit:junit-bom:$junitBomVersion")) - testImplementation('org.junit.jupiter:junit-jupiter') - testImplementation('org.junit.jupiter:junit-jupiter-params') - testImplementation('org.junit.jupiter:junit-jupiter-engine') - testImplementation('org.junit.vintage:junit-vintage-engine') - - testImplementation platform('org.spockframework:spock-bom:2.1-groovy-3.0') - testImplementation 'org.spockframework:spock-core' - testImplementation 'org.spockframework:spock-junit4' + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.bundles.junit.vintage) + + testImplementation(platform(libs.spock.bom)) + testImplementation(libs.bundles.spock) + if ('8'.equals(findProperty("javaVersion"))) { - testImplementation("org.mockito:mockito-core:4.6.1") - testImplementation("org.mockito:mockito-inline:4.6.1") + testImplementation(libs.bundles.mockito.java8) } else { - testImplementation("org.mockito:mockito-core:5.11.0") + testImplementation(libs.bundles.mockito) } - testImplementation 'cglib:cglib-nodep:2.2.2' - testImplementation 'org.objenesis:objenesis:1.3' - testImplementation 'org.hamcrest:hamcrest-all:1.3' - testImplementation "ch.qos.logback:logback-classic:$logbackVersion" + testImplementation(libs.cglib) + testImplementation(libs.objenesis) testImplementation project(':util:spock') //Adding categories to classpath } diff --git a/driver-benchmarks/build.gradle b/driver-benchmarks/build.gradle index 91d979cff68..b8c5ac0b62b 100644 --- a/driver-benchmarks/build.gradle +++ b/driver-benchmarks/build.gradle @@ -32,7 +32,7 @@ sourceSets { dependencies { api project(':driver-sync') api project(':mongodb-crypt') - implementation "ch.qos.logback:logback-classic:$logbackVersion" + implementation(libs.logback.classic) } javadoc { diff --git a/driver-core/build.gradle b/driver-core/build.gradle index a44f65bbc1b..900015bf79e 100644 --- a/driver-core/build.gradle +++ b/driver-core/build.gradle @@ -16,7 +16,7 @@ plugins { - id 'com.github.gmazzo.buildconfig' version '3.0.3' + alias(libs.plugins.build.config) } archivesBaseName = 'mongodb-driver-core' @@ -33,7 +33,6 @@ configurations { } } -def classifiers = ["linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64"] dependencies { api project(path: ':bson', configuration: 'default') implementation project(path: ':bson-record-codec', configuration: 'default') @@ -41,30 +40,26 @@ dependencies { implementation project(path: ':bson-kotlinx', configuration: 'default'), optional implementation project(path: ':mongodb-crypt', configuration: 'default'), optional - implementation "com.github.jnr:jnr-unixsocket:$jnrUnixsocketVersion", optional - api platform("io.netty:netty-bom:$nettyVersion") - api "io.netty:netty-buffer", optional - api "io.netty:netty-transport", optional - api "io.netty:netty-handler", optional - compileOnly "org.graalvm.sdk:graal-sdk:$graalSdkVersion" + implementation(libs.jnr.unixsocket, optional) + api(platform(libs.netty.bom), optional) + api(libs.bundles.netty, optional) + compileOnly(libs.graal.sdk) - // Optionally depend on both AWS SDK v2 and v1. The driver will use v2 is present, v1 if present, or built-in functionality if - // neither are present - implementation "software.amazon.awssdk:auth:$awsSdkV2Version", optional - implementation "software.amazon.awssdk:sts:$awsSdkV2Version", optional - implementation "com.amazonaws:aws-java-sdk-core:$awsSdkV1Version", optional - implementation "com.amazonaws:aws-java-sdk-sts:$awsSdkV1Version", optional + // Optionally depend on both AWS SDK v2 and v1. + // The driver will use v2 is present, v1 if present, or built-in functionality if neither are present + implementation(libs.bundles.aws.java.sdk.v1, optional) + implementation(libs.bundles.aws.java.sdk.v2, optional) - implementation "org.xerial.snappy:snappy-java:$snappyVersion", optional - implementation "com.github.luben:zstd-jni:$zstdVersion", optional + implementation(libs.snappy.java, optional) + implementation(libs.zstd.jni, optional) testImplementation project(':bson').sourceSets.test.output - testImplementation('org.junit.jupiter:junit-jupiter-api') - testImplementation("org.reflections:reflections:$reflectionsVersion") - testRuntimeOnly "io.netty:netty-tcnative-boringssl-static" + testImplementation(libs.bundles.junit) + testImplementation(libs.reflections) - classifiers.forEach { - testRuntimeOnly "io.netty:netty-tcnative-boringssl-static::$it" + testRuntimeOnly(libs.netty.boringssl) + ["linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64"].each { arch -> + testRuntimeOnly(variantOf(libs.netty.boringssl) { classifier(arch) }) } } diff --git a/driver-kotlin-coroutine/build.gradle.kts b/driver-kotlin-coroutine/build.gradle.kts index 96ac4cc31eb..59ef13952f2 100644 --- a/driver-kotlin-coroutine/build.gradle.kts +++ b/driver-kotlin-coroutine/build.gradle.kts @@ -18,12 +18,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.kotlin.jvm") - `java-library` + id("java-library") // Test based plugins - id("com.diffplug.spotless") - id("org.jetbrains.dokka") - id("io.gitlab.arturbosch.detekt") + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.detekt) } repositories { @@ -56,26 +56,25 @@ val integrationTestImplementation: Configuration by dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) - implementation(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive") + implementation(platform(libs.kotlinx.coroutines.bom)) + api(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.coroutines.reactive) api(project(path = ":bson", configuration = "default")) api(project(path = ":driver-reactive-streams", configuration = "default")) implementation(project(path = ":bson-kotlin", configuration = "default")) - testImplementation("org.jetbrains.kotlin:kotlin-reflect") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") - testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0") - testImplementation("org.mockito:mockito-junit-jupiter:4.11.0") - testImplementation("org.assertj:assertj-core:3.24.2") - testImplementation("io.github.classgraph:classgraph:4.8.154") + testImplementation(libs.kotlin.reflect) + testImplementation(libs.junit.kotlin) + testImplementation(libs.bundles.mockito.kotlin) + testImplementation(libs.assertj) + testImplementation(libs.classgraph) - integrationTestImplementation("org.jetbrains.kotlin:kotlin-test-junit") - integrationTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test") + integrationTestImplementation(libs.junit.kotlin) + integrationTestImplementation(libs.kotlinx.coroutines.test) integrationTestImplementation(project(path = ":driver-sync")) integrationTestImplementation(project(path = ":driver-core")) integrationTestImplementation(project(path = ":bson")) diff --git a/driver-kotlin-extensions/build.gradle.kts b/driver-kotlin-extensions/build.gradle.kts index 76f36ca33b2..fc0e134749a 100644 --- a/driver-kotlin-extensions/build.gradle.kts +++ b/driver-kotlin-extensions/build.gradle.kts @@ -18,12 +18,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.kotlin.jvm") - `java-library` + id("java-library") // Test based plugins - id("com.diffplug.spotless") - id("org.jetbrains.dokka") - id("io.gitlab.arturbosch.detekt") + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.detekt) } repositories { @@ -41,8 +41,8 @@ java { registerFeature("kotlinDrivers") { usingSourceSet(sourceSets["main"]) } } dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) api(project(path = ":driver-core", configuration = "default")) @@ -51,11 +51,11 @@ dependencies { "kotlinDriversImplementation"(project(path = ":driver-kotlin-sync", configuration = "default")) "kotlinDriversImplementation"(project(path = ":driver-kotlin-coroutine", configuration = "default")) - testImplementation("org.jetbrains.kotlin:kotlin-reflect") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") - testImplementation("org.assertj:assertj-core:3.24.2") - testImplementation("io.github.classgraph:classgraph:4.8.154") - testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0") + testImplementation(libs.kotlin.reflect) + testImplementation(libs.junit.kotlin) + testImplementation(libs.bundles.mockito.kotlin) + testImplementation(libs.assertj) + testImplementation(libs.classgraph) } kotlin { explicitApi() } diff --git a/driver-kotlin-sync/build.gradle.kts b/driver-kotlin-sync/build.gradle.kts index e7fb132cb36..e0131613a97 100644 --- a/driver-kotlin-sync/build.gradle.kts +++ b/driver-kotlin-sync/build.gradle.kts @@ -18,12 +18,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.kotlin.jvm") - `java-library` + id("java-library") // Test based plugins - id("com.diffplug.spotless") - id("org.jetbrains.dokka") - id("io.gitlab.arturbosch.detekt") + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.detekt) } repositories { @@ -56,21 +56,20 @@ val integrationTestImplementation: Configuration by dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) api(project(path = ":bson", configuration = "default")) api(project(path = ":driver-sync", configuration = "default")) implementation(project(path = ":bson-kotlin", configuration = "default")) - testImplementation("org.jetbrains.kotlin:kotlin-reflect") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") - testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0") - testImplementation("org.mockito:mockito-junit-jupiter:4.11.0") - testImplementation("org.assertj:assertj-core:3.24.2") - testImplementation("io.github.classgraph:classgraph:4.8.154") + testImplementation(libs.kotlin.reflect) + testImplementation(libs.junit.kotlin) + testImplementation(libs.bundles.mockito.kotlin) + testImplementation(libs.assertj) + testImplementation(libs.classgraph) - integrationTestImplementation("org.jetbrains.kotlin:kotlin-test-junit") + integrationTestImplementation(libs.junit.kotlin) integrationTestImplementation(project(path = ":driver-sync")) integrationTestImplementation(project(path = ":driver-core")) } diff --git a/driver-lambda/build.gradle b/driver-lambda/build.gradle index d7b9928e8f7..d1e4f624629 100644 --- a/driver-lambda/build.gradle +++ b/driver-lambda/build.gradle @@ -14,23 +14,13 @@ * limitations under the License. */ -buildscript { - repositories { - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:6.1.0' - } -} plugins { + id("java") id("application") + alias(libs.plugins.shadow) } -apply plugin: 'application' -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'java' - compileJava { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -53,10 +43,10 @@ dependencies { implementation project(':driver-sync') implementation project(':bson') - implementation('com.amazonaws:aws-lambda-java-core:1.2.2') - implementation('com.amazonaws:aws-lambda-java-events:3.11.1') - implementation(platform("org.junit:junit-bom:$junitBomVersion")) - implementation('org.junit.jupiter:junit-jupiter-api') + implementation(libs.aws.lambda.core) + implementation(libs.aws.lambda.events) + implementation(platform(libs.junit.bom)) + implementation(libs.bundles.junit) } diff --git a/driver-reactive-streams/build.gradle b/driver-reactive-streams/build.gradle index 7b86f010484..f50a12de147 100644 --- a/driver-reactive-streams/build.gradle +++ b/driver-reactive-streams/build.gradle @@ -21,20 +21,21 @@ dependencies { api project(path: ':bson', configuration: 'default') api project(path: ':driver-core', configuration: 'default') - api 'org.reactivestreams:reactive-streams:1.0.4' - implementation platform("io.projectreactor:reactor-bom:$projectReactorVersion") - implementation 'io.projectreactor:reactor-core' + api(libs.reactive.streams) + implementation(platform(libs.project.reactor.bom)) + implementation(libs.project.reactor.core) testImplementation project(':bson').sourceSets.test.output testImplementation project(':driver-sync') testImplementation project(':driver-sync').sourceSets.test.output testImplementation project(':driver-core').sourceSets.test.output - testImplementation 'org.reactivestreams:reactive-streams-tck:1.0.4' - testImplementation 'io.projectreactor:reactor-test' + testImplementation(libs.reactive.streams.tck) + + testImplementation(libs.project.reactor.test) if ('8'.equals(findProperty("javaVersion"))) { - testImplementation 'org.mockito:mockito-junit-jupiter:4.6.1' + testImplementation(libs.bundles.mockito.java8) } else { - testImplementation 'org.mockito:mockito-junit-jupiter:5.11.0' + testImplementation(libs.bundles.mockito) } testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') diff --git a/driver-sync/build.gradle b/driver-sync/build.gradle index 1c2f3ac6c59..2ea76dbd829 100644 --- a/driver-sync/build.gradle +++ b/driver-sync/build.gradle @@ -28,7 +28,7 @@ dependencies { testImplementation project(':driver-core').sourceSets.test.output testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') - testImplementation('com.amazonaws:aws-lambda-java-core:1.2.1') + testImplementation(libs.aws.lambda.core) } sourceSets { diff --git a/driver-workload-executor/build.gradle b/driver-workload-executor/build.gradle index 7c48e444dc2..8885e1fd59c 100644 --- a/driver-workload-executor/build.gradle +++ b/driver-workload-executor/build.gradle @@ -14,18 +14,12 @@ * limitations under the License. */ -buildscript { - repositories { - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:6.1.0' - } +plugins { + id("java") + id("application") + alias(libs.plugins.shadow) } -apply plugin: 'application' -apply plugin: 'com.github.johnrengelman.shadow' - mainClassName = "com.mongodb.workload.WorkloadExecutor" sourceSets { @@ -43,10 +37,8 @@ dependencies { implementation project(':driver-sync') implementation project(':driver-core').sourceSets.test.output implementation project(':driver-sync').sourceSets.test.output - implementation "ch.qos.logback:logback-classic:$logbackVersion" - implementation(platform("org.junit:junit-bom:$junitBomVersion")) - implementation('org.junit.jupiter:junit-jupiter') - implementation('org.junit.vintage:junit-vintage-engine') + implementation(platform(libs.junit.bom)) + implementation(libs.bundles.junit.vintage) } javadoc { diff --git a/graalvm-native-image-app/build.gradle b/graalvm-native-image-app/build.gradle index b3d7335f9d9..e9a2c0433bb 100644 --- a/graalvm-native-image-app/build.gradle +++ b/graalvm-native-image-app/build.gradle @@ -17,8 +17,8 @@ // Note requires a Gradle project flag `-PincludeGraalvm` (see settings.gradle). plugins { - id 'application' - id 'org.graalvm.buildtools.native' version '0.9.23' + id("application") + alias(libs.plugins.graalvm.buildtools) } application { @@ -113,9 +113,10 @@ dependencies { implementation project(':driver-sync').sourceSets.test.output implementation project(':driver-legacy').sourceSets.test.output implementation project(':driver-reactive-streams').sourceSets.test.output - implementation 'org.slf4j:slf4j-api:2.0.12' - implementation "ch.qos.logback:logback-classic:$logbackVersion" - implementation platform("io.projectreactor:reactor-bom:$projectReactorVersion") - implementation 'io.projectreactor:reactor-core' - implementation "org.graalvm.sdk:nativeimage:$graalSdkVersion" + + implementation(libs.slf4j) + implementation(libs.logback) + implementation(platform(libs.reactor.bom)) + implementation(libs.reactor.core) + implementation(libs.graal.sdk.native) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000000..7eaf08263b4 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,178 @@ +# Copyright 2008-present MongoDB, Inc. +# +# 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. + +[versions] +aws-sdk-v1 = "1.12.337" +aws-sdk-v2 = "2.18.9" +graal-sdk = "24.0.0" +jna = "5.11.0" +jnr-unixsocket = "0.38.17" +netty-bom = "4.1.87.Final" +project-reactor-bom = "2022.0.0" +reactive-streams = "1.0.4" +snappy = "1.1.10.3" +zstd = "1.5.5-3" + +kotlin = "1.8.10" +kotlinx-coroutines-bom = "1.6.4" +kotlinx-datetime = "0.4.0" +kotlinx-serialization = "1.5.0" + +scala = "%scala-version%" # Handled by the scala multiversion plugin + +# Test +assertj = "3.24.2" +aws-lambda-core = "1.2.2" +aws-lambda-events = "3.11.1" +cglib = "2.2.2" +classgraph = "4.8.154" +findbugs-jsr = "1.3.9" +groovy = "3.0.9" +hamcrest = "1.3" +junit-bom = "5.10.2" +logback = "1.3.14" +mockito = "5.11.0" +mockito-java8 = "4.6.1" +mockito-kotlin = "4.1.0" +objenesis = "1.3" +reflections = "0.9.10" +scalatest = "3.2.9" +scalatest-plus = "3.2.10.0" +slf4j = "1.7.6" +spock-bom = "2.1-groovy-3.0" + +# Plugins +plugin-bnd = "5.1.2" +plugin-build-config = "3.0.3" +plugin-detekt = "1.21.0" +plugin-dokka = "1.8.10" +plugin-download = "5.6.0" +plugin-graalvm = "0.9.23" +plugin-optional-base = "7.0.0" +plugin-scala-multiversion = "2.0.4" +plugin-shadow = "6.1.0" +plugin-spotbugs = "6.0.15" +plugin-spotless = "6.14.0" +plugin-test-logger = "2.1.0" + +[libraries] +aws-java-sdk-v1-core = { module = "com.amazonaws:aws-java-sdk-core", version.ref = "aws-sdk-v1" } +aws-java-sdk-v1-sts = { module = "com.amazonaws:aws-java-sdk-sts", version.ref = "aws-sdk-v1" } +aws-java-sdk-v2-auth = { module = "software.amazon.awssdk:auth", version.ref = "aws-sdk-v2" } +aws-java-sdk-v2-sts = { module = "software.amazon.awssdk:sts", version.ref = "aws-sdk-v2" } + +jna = { module = "net.java.dev.jna:jna", version.ref = "jna" } +jnr-unixsocket = { module = "com.github.jnr:jnr-unixsocket", version.ref = "jnr-unixsocket" } + +netty-bom = { module = "io.netty:netty-bom", version.ref = "netty-bom" } +netty-buffer = { module = "io.netty:netty-buffer" } +netty-handler = { module = "io.netty:netty-handler" } +netty-transport = { module = "io.netty:netty-transport" } + +project-reactor-bom = { module = "io.projectreactor:reactor-bom", version.ref = "project-reactor-bom" } +project-reactor-core = { module = "io.projectreactor:reactor-core" } +reactive-streams = { module = " org.reactivestreams:reactive-streams", version.ref = "reactive-streams" } + +slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +snappy-java = { module = "org.xerial.snappy:snappy-java", version.ref = "snappy" } +zstd-jni = { module = "com.github.luben:zstd-jni", version.ref = "zstd" } + +graal-sdk = { module = "org.graalvm.sdk:graal-sdk", version.ref = "graal-sdk" } +graal-sdk-native = { module = "org.graalvm.sdk:native", version.ref = "graal-sdk" } + +kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom" } +kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } +kotlinx-coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "kotlinx-coroutines-bom" } +kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" } +kotlinx-coroutines-reactive = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-reactive" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" } +kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "kotlinx-serialization" } +kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } +kotlinx-serialization-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } + +scala-library = {module = "org.scala-lang:scala-library", version.ref = "scala" } +scala-reflect = {module = "org.scala-lang:scala-reflect", version.ref = "scala" } + +# Test +junit-bom = { module = "org.junit:junit-bom", version.ref = "junit-bom" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } +junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" } +junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine" } +junit-kotlin = { module = "org.jetbrains.kotlin:kotlin-test-junit" } + +spock-bom = { module = "org.spockframework:spock-bom", version.ref = "spock-bom" } +spock-core = { module = "org.spockframework:spock-core" } +spock-junit4 = { module = "org.spockframework:spock-junit4" } + +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } +mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } +mockito-junit-jupiter-java8 = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito-java8" } +mockito-core-java8 = { module = "org.mockito:mockito-core", version.ref = "mockito-java8" } +mockito-inline-java8 = { module = "org.mockito:mockito-inline", version.ref = "mockito-java8" } +mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockito-kotlin" } + +scalatest-flatspec = { module = "org.scalatest:scalatest-flatspec_%%", version.ref = "scalatest" } +scalatest-should-matchers = { module = "org.scalatest:scalatest-shouldmatchers_%%", version.ref = "scalatest" } +scalatest-plus-junit4 = { module = "org.scalatestplus:junit-4-13_%%", version.ref = "scalatest-plus" } +scalatest-plus-mockito = { module = "org.scalatestplus:mockito-3-12_%%", version.ref = "scalatest-plus" } + +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test" } + +assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } +aws-lambda-core = { module = " com.amazonaws:aws-lambda-java-core", version.ref = "aws-lambda-core" } +aws-lambda-events = { module = " com.amazonaws:aws-lambda-java-events", version.ref = "aws-lambda-events" } +cglib = { module = "cglib:cglib-nodep", version.ref = "cglib" } +classgraph = { module = "io.github.classgraph:classgraph", version.ref = "classgraph" } +findbugs-jsr = { module = "com.google.code.findbugs:jsr305", version.ref = "findbugs-jsr" } +groovy = { module = "org.codehaus.groovy:groovy-all", version.ref = "groovy" } +hamcrest-all = { module = "org.hamcrest:hamcrest-all", version.ref = "hamcrest" } +logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +netty-boringssl = { module = "io.netty:netty-tcnative-boringssl-static" } +objenesis = { module = "org.objenesis:objenesis", version.ref = "objenesis" } +project-reactor-test = { module = "io.projectreactor:reactor-test" } +reactive-streams-tck = { module = " org.reactivestreams:reactive-streams-tck", version.ref = "reactive-streams" } +reflections = { module = "org.reflections:reflections", version.ref = "reflections" } + +[bundles] +aws-java-sdk-v1 = ["aws-java-sdk-v1-core", "aws-java-sdk-v1-sts"] +aws-java-sdk-v2 = ["aws-java-sdk-v2-auth", "aws-java-sdk-v2-sts"] +netty = ["netty-buffer", "netty-handler", "netty-transport"] + +# Test +junit = ["junit-jupiter", "junit-jupiter-params", "junit-jupiter-engine", "junit-jupiter", "logback-classic", "hamcrest-all"] +junit-vintage = ["junit-vintage-engine", "junit-jupiter-params", "junit-jupiter-engine", "junit-jupiter", "logback-classic", "hamcrest-all"] +scalatest = ["scalatest-flatspec", "scalatest-should-matchers", "scalatest-plus-junit4", "scalatest-plus-mockito"] +spock = ["spock-core", "spock-junit4"] + +mockito = ["mockito-junit-jupiter", "mockito-core"] +mockito-java8 = ["mockito-junit-jupiter-java8", "mockito-core-java8", "mockito-inline-java8"] +mockito-kotlin = ["mockito-kotlin", "mockito-junit-jupiter-java8"] + +[plugins] +bnd = { id = "biz.aQute.bnd", version.ref = "plugin-bnd" } +build-config = { id = "com.github.gmazzo.buildconfig", version.ref = "plugin-build-config" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "plugin-detekt" } +dokka = { id = "org.jetbrains.dokka", version.ref = "plugin-dokka" } +download = { id = "de.undercouch.download", version.ref = "plugin-download" } +graalvm-buildtools = { id = "org.graalvm.buildtools.native", version.ref = "plugin-graalvm" } +kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +optional = { id = "nebula.optional-base", version.ref = "plugin-optional-base" } +scala-multiversion = { id = "com.adtran.scala-multiversion-plugin", version.ref = "plugin-scala-multiversion" } +shadow = { id = "com.github.johnrengelman.shadow", version.ref = "plugin-shadow" } +spotbugs = { id = "com.github.spotbugs", version.ref = "plugin-spotbugs" } +spotless = { id = "com.diffplug.spotless", version.ref = "plugin-spotless" } +test-logger = { id = "com.adarshr.test-logger", version.ref = "plugin-test-logger" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 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 B8dv}T delta 17845 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 X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102e092..3994438e229 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c811..1b6c787337f 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/mongodb-crypt/build.gradle.kts b/mongodb-crypt/build.gradle.kts index 6c07a315185..405d16a9e79 100644 --- a/mongodb-crypt/build.gradle.kts +++ b/mongodb-crypt/build.gradle.kts @@ -17,19 +17,8 @@ import de.undercouch.gradle.tasks.download.Download -buildscript { - repositories { - mavenCentral() - google() - } - dependencies { - "classpath"(group = "net.java.dev.jna", name = "jna", version = "5.11.0") - } -} - plugins { - // Needed to download libmongocrypt from s3. - id("de.undercouch.download") version "5.6.0" + alias(libs.plugins.download) } group = "org.mongodb" @@ -44,10 +33,10 @@ java { dependencies { api(project(path = ":bson", configuration = "default")) - api("net.java.dev.jna:jna:5.11.0") + api(libs.jna) // Tests - testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation(libs.bundles.junit) } /* From 2a8587e1a5a3f9e3447d66a58dec0c8530009788 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Tue, 4 Mar 2025 17:25:30 +0000 Subject: [PATCH 2/4] Port b0e19bc --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7eaf08263b4..d26a5ae56a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,8 +13,8 @@ # limitations under the License. [versions] -aws-sdk-v1 = "1.12.337" -aws-sdk-v2 = "2.18.9" +aws-sdk-v1 = "1.12.782" +aws-sdk-v2 = "2.30.31" graal-sdk = "24.0.0" jna = "5.11.0" jnr-unixsocket = "0.38.17" From c4053a42759e621829c739248abf623938433e4c Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Mon, 24 Mar 2025 10:30:39 +0000 Subject: [PATCH 3/4] Gradle modernization (#1642) Added buildSrclibrary conventions and language based configurations. - Updated to Gradle 8 (JAVA-5756) - Removed `util:taglets` as now in `buildSrc`. - Moved `util:spock` into `driver-core` as the annotation is now shared via `testArtifacts`. - Added optional support (JAVA-5757) Migrated tests to work with conventions: - Refactored `JsonPoweredTestHelper` to handle either local and jar based resources - Refactored test cases to use new `JsonPoweredTestHelper.getTestDocuments` method - Refactored test cases to normalize usage of loading test data - Moved scala / kotlin integration tests into a standardized `integerationTest` directory Update github action and put version in `gradle.properties`. JAVA-5756 JAVA-5757 JAVA-5758 --- .evergreen/.evg.yml | 6 +- .evergreen/publish.sh | 4 +- .github/workflows/bump-version.sh | 4 +- bom/build.gradle.kts | 136 ++++++- bson-kotlin/build.gradle.kts | 126 +------ bson-kotlinx/build.gradle.kts | 141 +------ bson-record-codec/build.gradle | 41 -- bson-record-codec/build.gradle.kts | 53 +++ bson-scala/build.gradle | 67 ---- bson-scala/build.gradle.kts | 37 ++ .../org/mongodb/scala/bson/BaseSpec.scala | 3 - .../scala/bson/codecs/MacrosSpec.scala | 1 + bson/build.gradle.kts | 39 ++ .../test/unit/org/bson/GenericBsonTest.java | 7 +- .../vector/BinaryVectorGenericBsonTest.java | 12 +- .../test/unit/util/JsonPoweredTestHelper.java | 128 +++---- build.gradle | 356 ------------------ util/spock/build.gradle => build.gradle.kts | 4 + buildSrc/build.gradle.kts | 83 ++++ buildSrc/settings.gradle.kts | 21 ++ .../mongodb/doclet}/AtlasManualTaglet.java | 1 + .../java/com/mongodb/doclet}/DocTaglet.java | 21 +- .../com/mongodb/doclet}/DochubTaglet.java | 2 +- .../com/mongodb/doclet}/ManualTaglet.java | 2 +- .../mongodb/doclet}/ServerReleaseTaglet.java | 2 +- buildSrc/src/main/kotlin/ProjectExtensions.kt | 56 +++ .../src/main/kotlin/conventions/Companion.kt | 29 ++ .../main/kotlin/conventions/bnd.gradle.kts | 6 + .../kotlin/conventions/codenarc.gradle.kts | 25 ++ .../main/kotlin/conventions/detekt.gradle.kts | 44 +++ .../main/kotlin/conventions/dokka.gradle.kts | 47 +++ .../kotlin/conventions/git-version.gradle.kts | 31 ++ .../kotlin/conventions/javadoc.gradle.kts | 125 ++++++ .../kotlin/conventions/optional.gradle.kts | 33 ++ .../kotlin/conventions/publishing.gradle.kts | 174 +++++++++ .../kotlin/conventions/scaladoc.gradle.kts | 34 ++ .../kotlin/conventions/spotbugs.gradle.kts | 53 +++ .../kotlin/conventions/spotless.gradle.kts | 69 ++++ .../conventions/test-artifacts.gradle.kts | 43 +++ .../test-include-optionals.gradle.kts | 35 +- .../conventions/testing-base.gradle.kts | 107 ++++++ .../testing-integration.gradle.kts | 50 +++ .../testing-junit-vintage.gradle.kts | 26 ++ .../conventions/testing-junit.gradle.kts | 26 ++ .../conventions/testing-mockito.gradle.kts | 19 +- .../testing-spock-exclude-slow.gradle.kts | 36 ++ .../conventions/testing-spock.gradle.kts | 42 +++ buildSrc/src/main/kotlin/project/Companion.kt | 26 ++ .../src/main/kotlin/project/base.gradle.kts | 10 + .../src/main/kotlin/project/java.gradle.kts | 50 +++ .../src/main/kotlin/project/kotlin.gradle.kts | 67 ++++ .../src/main/kotlin/project/scala.gradle.kts | 105 ++++++ config/detekt/baseline.xml | 21 +- config/spock/ExcludeSlow.groovy | 2 +- config/spock/OnlySlow.groovy | 2 +- .../{build.gradle => build.gradle.kts} | 42 +-- driver-core/build.gradle | 96 ----- driver-core/build.gradle.kts | 100 +++++ .../AggregatesFunctionalSpecification.groovy | 3 +- .../netty/NettyStreamSpecification.groovy | 2 +- ...yncSocketChannelStreamSpecification.groovy | 2 +- .../AsyncStreamTimeoutsSpecification.groovy | 2 +- .../StreamSocketAddressSpecification.groovy | 2 +- .../CommandOperationSpecification.groovy | 2 +- ...ixedBulkWriteOperationSpecification.groovy | 2 +- .../com/mongodb/AuthConnectionStringTest.java | 17 +- .../com/mongodb/ConnectionStringTest.java | 18 +- .../ReadConcernConnectionStringTest.java | 22 +- .../com/mongodb/ReadConcernDocumentTest.java | 21 +- .../test/unit/com/mongodb/UriOptionsTest.java | 18 +- .../WriteConcernConnectionStringTest.java | 21 +- .../com/mongodb/WriteConcernDocumentTest.java | 23 +- .../ServerSelectionSelectionTest.java | 24 +- .../AbstractConnectionPoolTest.java | 17 +- ...tractServerDiscoveryAndMonitoringTest.java | 10 +- .../BaseClusterSpecification.groovy | 2 +- .../DefaultConnectionPoolSpecification.groovy | 2 +- ...rDiscoveryAndMonitoringMonitoringTest.java | 4 +- .../ServerDiscoveryAndMonitoringTest.java | 4 +- .../connection/ServerSelectionRttTest.java | 9 +- ...erverSelectionWithinLatencyWindowTest.java | 23 +- .../src/test/unit/com/mongodb/spock/Slow.java | 26 ++ driver-kotlin-coroutine/build.gradle.kts | 170 +-------- .../kotlin/client/coroutine/SmokeTests.kt | 0 .../client/coroutine/UnifiedCrudTest.kt | 0 .../kotlin/client/coroutine/UnifiedTest.kt | 0 .../syncadapter/SyncAggregateIterable.kt | 0 .../syncadapter/SyncChangeStreamIterable.kt | 0 .../syncadapter/SyncClientSession.kt | 0 .../syncadapter/SyncDistinctIterable.kt | 0 .../coroutine/syncadapter/SyncFindIterable.kt | 0 .../SyncListCollectionNamesIterable.kt | 0 .../SyncListCollectionsIterable.kt | 0 .../syncadapter/SyncListDatabasesIterable.kt | 0 .../syncadapter/SyncListIndexesIterable.kt | 0 .../SyncListSearchIndexesIterable.kt | 0 .../syncadapter/SyncMapReduceIterable.kt | 0 .../SyncMongoChangeStreamCursor.kt | 0 .../coroutine/syncadapter/SyncMongoClient.kt | 0 .../coroutine/syncadapter/SyncMongoCluster.kt | 0 .../syncadapter/SyncMongoCollection.kt | 0 .../coroutine/syncadapter/SyncMongoCursor.kt | 0 .../syncadapter/SyncMongoDatabase.kt | 0 .../syncadapter/SyncMongoIterable.kt | 0 driver-kotlin-extensions/build.gradle.kts | 150 +------- .../kotlin/client/model/AggregatesTest.kt | 2 +- .../kotlin/client/model/ExtensionsApiTest.kt | 2 +- .../kotlin/client/model/FiltersTest.kt | 2 +- .../kotlin/client/model/IndexesTest.kt | 2 +- .../kotlin/client/model/KPropertiesTest.kt | 2 +- .../kotlin/client/model/ProjectionTest.kt | 2 +- .../mongodb/kotlin/client/model/SortsTest.kt | 2 +- .../kotlin/client/model/UpdatesTest.kt | 2 +- driver-kotlin-sync/build.gradle.kts | 164 +------- .../com/mongodb/kotlin/client/SmokeTests.kt | 0 .../mongodb/kotlin/client/UnifiedCrudTest.kt | 0 .../com/mongodb/kotlin/client/UnifiedTest.kt | 0 .../syncadapter/SyncAggregateIterable.kt | 0 .../syncadapter/SyncChangeStreamIterable.kt | 0 .../client/syncadapter/SyncClientSession.kt | 0 .../syncadapter/SyncDistinctIterable.kt | 0 .../client/syncadapter/SyncFindIterable.kt | 0 .../SyncListCollectionNamesIterable.kt | 0 .../SyncListCollectionsIterable.kt | 0 .../syncadapter/SyncListDatabasesIterable.kt | 0 .../syncadapter/SyncListIndexesIterable.kt | 0 .../SyncListSearchIndexesIterable.kt | 0 .../SyncMongoChangeStreamCursor.kt | 0 .../client/syncadapter/SyncMongoClient.kt | 0 .../client/syncadapter/SyncMongoCluster.kt | 0 .../client/syncadapter/SyncMongoCollection.kt | 0 .../client/syncadapter/SyncMongoCursor.kt | 0 .../client/syncadapter/SyncMongoDatabase.kt | 0 .../client/syncadapter/SyncMongoIterable.kt | 0 .../{build.gradle => build.gradle.kts} | 42 +-- driver-legacy/build.gradle.kts | 47 +++ .../MongoClientSessionSpecification.groovy | 2 +- driver-reactive-streams/build.gradle | 82 ---- driver-reactive-streams/build.gradle.kts | 78 ++++ .../ClientSideEncryptionCorpusTest.java | 6 +- ...entSideEncryptionExternalKeyVaultTest.java | 8 +- .../ClientSideEncryptionSessionTest.java | 8 +- .../MongoClientSessionSpecification.groovy | 2 +- ...activeInitialDnsSeedlistDiscoveryTest.java | 3 +- .../client/unified/ChangeStreamsTest.java | 4 +- .../unified/ClientSideEncryptionTest.java | 4 +- .../ClientSideOperationTimeoutTest.java | 4 +- .../unified/CollectionManagementTest.java | 4 +- .../client/unified/CommandLoggingTest.java | 4 +- .../client/unified/CommandMonitoringTest.java | 4 +- .../unified/ConnectionPoolLoggingTest.java | 4 +- .../client/unified/IndexManagmentTest.java | 4 +- .../client/unified/LoadBalancerTest.java | 4 +- .../unified/ServerSelectionLoggingTest.java | 4 +- .../client/unified/SessionsTest.java | 4 +- .../client/unified/UnifiedCrudTest.java | 4 +- .../client/unified/UnifiedGridFSTest.java | 4 +- .../unified/UnifiedReactiveStreamsTest.java | 4 +- .../unified/UnifiedRetryableReadsTest.java | 4 +- .../unified/UnifiedRetryableWritesTest.java | 4 +- ...ifiedServerDiscoveryAndMonitoringTest.java | 4 +- .../unified/UnifiedTransactionsTest.java | 4 +- .../unified/UnifiedWriteConcernTest.java | 4 +- .../client/unified/VersionedApiTest.java | 4 +- driver-scala/build.gradle | 126 ------- driver-scala/build.gradle.kts | 60 +++ .../scala/org/mongodb/scala/BaseSpec.scala | 3 - ...deEncryptionBypassAutoEncryptionSpec.scala | 0 .../scala/ClientSideEncryptionTest.scala | 0 .../scala/org/mongodb/scala/FuturesSpec.scala | 0 .../scala/MongoCollectionCaseClassSpec.scala | 0 .../mongodb/scala/RequiresMongoDBISpec.scala | 0 .../mongodb/scala/TestMongoClientHelper.scala | 0 ...DocumentationChangeStreamExampleSpec.scala | 0 .../DocumentationExampleSpec.scala | 0 ...DocumentationTransactionsExampleSpec.scala | 0 .../scala/gridfs/GridFSObservableSpec.scala | 8 +- .../syncadapter/SyncAggregateIterable.scala | 0 .../SyncChangeStreamIterable.scala | 0 .../scala/syncadapter/SyncClientSession.scala | 0 .../syncadapter/SyncDistinctIterable.scala | 0 .../scala/syncadapter/SyncFindIterable.scala | 0 .../SyncListCollectionsIterable.scala | 0 .../SyncListDatabasesIterable.scala | 0 .../syncadapter/SyncListIndexesIterable.scala | 0 .../SyncListSearchIndexesIterable.scala | 0 .../syncadapter/SyncMapReduceIterable.scala | 0 .../scala/syncadapter/SyncMongoClient.scala | 0 .../scala/syncadapter/SyncMongoCluster.scala | 0 .../syncadapter/SyncMongoCollection.scala | 0 .../scala/syncadapter/SyncMongoCursor.scala | 0 .../scala/syncadapter/SyncMongoDatabase.scala | 0 .../scala/syncadapter/SyncMongoIterable.scala | 0 .../mongodb/scala/syncadapter/package.scala | 0 ...EncryptionAutoEncryptionSettingsTour.scala | 0 ...nExplicitEncryptionAndDecryptionTour.scala | 0 ...EncryptionExplicitEncryptionOnlyTour.scala | 0 .../tour/ClientSideEncryptionSimpleTour.scala | 0 .../scala/tour/GridFSTour.scala | 0 .../scala/tour/Helpers.scala | 0 .../scala/tour/QuickTour.scala | 0 .../scala/tour/QuickTourCaseClass.scala | 0 .../scala/ApiAliasAndCompanionSpec.scala | 1 + .../scala/org/mongodb/scala/BaseSpec.scala | 3 - driver-sync/build.gradle | 55 --- driver-sync/build.gradle.kts | 59 +++ ...tractClientSideEncryptionDeadlockTest.java | 6 +- ...tSideEncryptionExplicitEncryptionTest.java | 10 +- ...SideEncryptionNotSpawnMongocryptdTest.java | 17 +- ...EncryptionRangeExplicitEncryptionTest.java | 17 +- .../AbstractClientSideEncryptionTest.java | 16 +- ...lientSideEncryption25LookupProseTests.java | 10 +- .../ClientSideEncryptionCorpusTest.java | 6 +- ...entSideEncryptionExternalKeyVaultTest.java | 6 +- .../ClientSideEncryptionSessionTest.java | 7 +- .../ClientSideOperationTimeoutTest.java | 4 +- .../InitialDnsSeedlistDiscoveryTest.java | 19 +- .../MongoClientSessionSpecification.groovy | 2 +- .../SyncInitialDnsSeedlistDiscoveryTest.java | 3 +- .../client/unified/ChangeStreamsTest.java | 4 +- .../unified/ClientSideEncryptionTest.java | 4 +- .../unified/CollectionManagementTest.java | 4 +- .../client/unified/CommandLoggingTest.java | 4 +- .../client/unified/CommandMonitoringTest.java | 4 +- .../unified/ConnectionPoolLoggingTest.java | 4 +- .../client/unified/IndexManagmentTest.java | 4 +- .../client/unified/LoadBalancerTest.java | 4 +- .../unified/ServerSelectionLoggingTest.java | 4 +- .../mongodb/client/unified/SessionsTest.java | 4 +- .../unified/UnifiedAtlasDataLakeTest.java | 4 +- .../client/unified/UnifiedAuthTest.java | 4 +- .../client/unified/UnifiedCrudTest.java | 4 +- .../client/unified/UnifiedGridFSTest.java | 4 +- .../unified/UnifiedRetryableReadsTest.java | 4 +- .../unified/UnifiedRetryableWritesTest.java | 4 +- ...ifiedServerDiscoveryAndMonitoringTest.java | 4 +- .../client/unified/UnifiedSyncTest.java | 4 +- .../mongodb/client/unified/UnifiedTest.java | 12 +- .../unified/UnifiedTestFailureValidator.java | 4 +- .../client/unified/UnifiedTestValidator.java | 4 +- .../unified/UnifiedTransactionsTest.java | 4 +- .../unified/UnifiedWriteConcernTest.java | 4 +- .../client/unified/VersionedApiTest.java | 4 +- ...WithTransactionHelperTransactionsTest.java | 4 +- .../{build.gradle => build.gradle.kts} | 35 +- graalvm-native-image-app/build.gradle | 122 ------ graalvm-native-image-app/build.gradle.kts | 185 +++++++++ .../internal/graalvm/NativeImageApp.java | 2 +- .../native-image/resource-config.json | 6 - gradle.properties | 8 +- gradle/deploy.gradle | 80 ---- gradle/javaToolchain.gradle | 107 ------ gradle/javadoc.gradle | 120 ------ gradle/libs.versions.toml | 72 +++- gradle/publish.gradle | 267 ------------- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 61624 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 18 +- gradlew.bat | 15 +- mongodb-crypt/build.gradle.kts | 143 +++---- settings.gradle | 40 -- settings.gradle.kts | 49 +++ .../src/main/util/spock/annotations/Slow.java | 11 - 263 files changed, 2863 insertions(+), 3028 deletions(-) delete mode 100644 bson-record-codec/build.gradle create mode 100644 bson-record-codec/build.gradle.kts delete mode 100644 bson-scala/build.gradle create mode 100644 bson-scala/build.gradle.kts create mode 100644 bson/build.gradle.kts delete mode 100644 build.gradle rename util/spock/build.gradle => build.gradle.kts (93%) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/settings.gradle.kts rename {util/taglets/src/main => buildSrc/src/main/java/com/mongodb/doclet}/AtlasManualTaglet.java (97%) rename {util/taglets/src/main => buildSrc/src/main/java/com/mongodb/doclet}/DocTaglet.java (93%) rename {util/taglets/src/main => buildSrc/src/main/java/com/mongodb/doclet}/DochubTaglet.java (97%) rename {util/taglets/src/main => buildSrc/src/main/java/com/mongodb/doclet}/ManualTaglet.java (97%) rename {util/taglets/src/main => buildSrc/src/main/java/com/mongodb/doclet}/ServerReleaseTaglet.java (97%) create mode 100644 buildSrc/src/main/kotlin/ProjectExtensions.kt create mode 100644 buildSrc/src/main/kotlin/conventions/Companion.kt rename util/build.gradle => buildSrc/src/main/kotlin/conventions/bnd.gradle.kts (77%) create mode 100644 buildSrc/src/main/kotlin/conventions/codenarc.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/detekt.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/dokka.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/git-version.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/javadoc.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/optional.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/publishing.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/scaladoc.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/spotbugs.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/spotless.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/test-artifacts.gradle.kts rename driver-legacy/build.gradle => buildSrc/src/main/kotlin/conventions/test-include-optionals.gradle.kts (50%) create mode 100644 buildSrc/src/main/kotlin/conventions/testing-base.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/testing-integration.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/testing-junit-vintage.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/testing-junit.gradle.kts rename bson/build.gradle => buildSrc/src/main/kotlin/conventions/testing-mockito.gradle.kts (67%) create mode 100644 buildSrc/src/main/kotlin/conventions/testing-spock-exclude-slow.gradle.kts create mode 100644 buildSrc/src/main/kotlin/conventions/testing-spock.gradle.kts create mode 100644 buildSrc/src/main/kotlin/project/Companion.kt rename util/taglets/build.gradle => buildSrc/src/main/kotlin/project/base.gradle.kts (80%) create mode 100644 buildSrc/src/main/kotlin/project/java.gradle.kts create mode 100644 buildSrc/src/main/kotlin/project/kotlin.gradle.kts create mode 100644 buildSrc/src/main/kotlin/project/scala.gradle.kts rename driver-benchmarks/{build.gradle => build.gradle.kts} (50%) delete mode 100644 driver-core/build.gradle create mode 100644 driver-core/build.gradle.kts create mode 100644 driver-core/src/test/unit/com/mongodb/spock/Slow.java rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/SmokeTests.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedCrudTest.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedTest.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncAggregateIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncChangeStreamIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncClientSession.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncFindIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionNamesIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionsIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListDatabasesIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListIndexesIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListSearchIndexesIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMapReduceIterable.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoChangeStreamCursor.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoClient.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCollection.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCursor.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoDatabase.kt (100%) rename driver-kotlin-coroutine/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/SmokeTests.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionNamesIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListSearchIndexesIterable.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCursor.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoDatabase.kt (100%) rename driver-kotlin-sync/src/{integration => integrationTest}/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoIterable.kt (100%) rename driver-lambda/{build.gradle => build.gradle.kts} (63%) create mode 100644 driver-legacy/build.gradle.kts delete mode 100644 driver-reactive-streams/build.gradle create mode 100644 driver-reactive-streams/build.gradle.kts delete mode 100644 driver-scala/build.gradle create mode 100644 driver-scala/build.gradle.kts rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/BaseSpec.scala (88%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/ClientSideEncryptionBypassAutoEncryptionSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/ClientSideEncryptionTest.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/FuturesSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/MongoCollectionCaseClassSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/RequiresMongoDBISpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/TestMongoClientHelper.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala (98%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoClient.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/org/mongodb/scala/syncadapter/package.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/ClientSideEncryptionSimpleTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/GridFSTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/Helpers.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/QuickTour.scala (100%) rename driver-scala/src/{integration => integrationTest}/scala/tour/QuickTourCaseClass.scala (100%) delete mode 100644 driver-sync/build.gradle create mode 100644 driver-sync/build.gradle.kts rename driver-workload-executor/{build.gradle => build.gradle.kts} (53%) delete mode 100644 graalvm-native-image-app/build.gradle create mode 100644 graalvm-native-image-app/build.gradle.kts delete mode 100644 gradle/deploy.gradle delete mode 100644 gradle/javaToolchain.gradle delete mode 100644 gradle/javadoc.gradle delete mode 100644 gradle/publish.gradle delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts delete mode 100644 util/spock/src/main/util/spock/annotations/Slow.java diff --git a/.evergreen/.evg.yml b/.evergreen/.evg.yml index 66b809e38a0..5a8b5ff4ece 100644 --- a/.evergreen/.evg.yml +++ b/.evergreen/.evg.yml @@ -1875,15 +1875,15 @@ axes: - id: "2.11" display_name: "Scala 2.11" variables: - SCALA: "2.11.12" + SCALA: "2.11" - id: "2.12" display_name: "Scala 2.12" variables: - SCALA: "2.12.20" + SCALA: "2.12" - id: "2.13" display_name: "Scala 2.13" variables: - SCALA: "2.13.15" + SCALA: "2.13" # Choice of MongoDB storage engine - id: storage-engine diff --git a/.evergreen/publish.sh b/.evergreen/publish.sh index e3f9f365d42..9a3e9eb405f 100755 --- a/.evergreen/publish.sh +++ b/.evergreen/publish.sh @@ -27,5 +27,5 @@ SYSTEM_PROPERTIES="-Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.g ./gradlew -version ./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info ${TASK} # Scala 2.13 is published as result of this gradle execution. -./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info :bson-scala:${TASK} :driver-scala:${TASK} -PdefaultScalaVersions=2.12.12 -./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info :bson-scala:${TASK} :driver-scala:${TASK} -PdefaultScalaVersions=2.11.12 +./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info :bson-scala:${TASK} :driver-scala:${TASK} -PscalaVersion=2.12 +./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info :bson-scala:${TASK} :driver-scala:${TASK} -PscalaVersion=2.11 diff --git a/.github/workflows/bump-version.sh b/.github/workflows/bump-version.sh index 5f39df82d79..eaa92163bfa 100755 --- a/.github/workflows/bump-version.sh +++ b/.github/workflows/bump-version.sh @@ -9,5 +9,5 @@ fi FROM_VERSION=$1 TO_VERSION=$2 -sed --in-place "s/version = '${FROM_VERSION}'/version = '${TO_VERSION}'/g" build.gradle -git commit -m "Version: bump ${TO_VERSION}" build.gradle +sed --in-place "s/version=${FROM_VERSION}/version=${TO_VERSION}/g" gradle.properties +git commit -m "Version: bump ${TO_VERSION}" gradle.properties diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 5d1fb81c384..20e9ee015b7 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -1,6 +1,30 @@ -group = "org.mongodb" -description = "This Bill of Materials POM simplifies dependency management when referencing multiple" + - " MongoDB Java Driver artifacts in projects using Gradle or Maven." +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureMavenPublication +import groovy.util.Node +import groovy.util.NodeList + +plugins { + id("java-platform") + id("project.base") + id("conventions.publishing") + id("conventions.spotless") +} + +base.archivesName.set("mongodb-driver-bom") dependencies { constraints { @@ -21,3 +45,109 @@ dependencies { api(project(":driver-scala")) } } + +/* + * Handle the multiple versions of Scala we support as defined in `gradle.properties` + */ +val defaultScalaVersion: String = project.findProperty("defaultScalaVersion")!!.toString() +val scalaVersions: List? = project.findProperty("supportedScalaVersions")?.toString()?.split(",") + +assert(!scalaVersions.isNullOrEmpty()) { + "Scala versions must be provided as a comma-separated list in the 'supportedScalaVersions' project property" +} + +/* + * Apply the Java Platform plugin to create the BOM + * Modify the generated POM to include all supported versions of Scala for driver-scala or bson-scala. + */ +configureMavenPublication { + components.findByName("javaPlatform")?.let { from(it) } + + pom { + name.set("bom") + description.set( + "This Bill of Materials POM simplifies dependency management when referencing multiple MongoDB Java Driver artifacts in projects using Gradle or Maven.") + + withXml { + val pomXml: Node = asNode() + + val dependencyManagementNode = pomXml.getNode("dependencyManagement") + assert(dependencyManagementNode != null) { + " node not found in the generated BOM POM" + } + val dependenciesNode = dependencyManagementNode.getNode("dependencies") + assert(dependenciesNode != null) { " node not found in the generated BOM POM" } + + val existingScalaDeps = + dependenciesNode!! + .children() + .map { it as Node } + .filter { it.getNode("artifactId")?.text()?.contains("scala") ?: false } + + existingScalaDeps.forEach { + val groupId: String = it.getNode("groupId")!!.text() + val originalArtifactId: String = it.getNode("artifactId")!!.text() + val artifactVersion: String = it.getNode("version")!!.text() + + // Add multiple versions with Scala suffixes for each Scala-related dependency. + scalaVersions!!.forEach { scalaVersion -> + if (scalaVersion != defaultScalaVersion) { + // Replace scala version suffix + val newArtifactId: String = originalArtifactId.replace(defaultScalaVersion, scalaVersion) + val dependencyNode = dependenciesNode.appendNode("dependency") + dependencyNode.appendNode("groupId", groupId) + dependencyNode.appendNode("artifactId", newArtifactId) + dependencyNode.appendNode("version", artifactVersion) + } + } + } + } + } +} + +/* + * Validate the BOM file. + */ +tasks.withType { + doLast { + pom.withXml { + val pomXml: Node = asNode() + val dependenciesNode = pomXml.getNode("dependencyManagement").getNode("dependencies") + assert(dependenciesNode!!.children().isNotEmpty()) { + "BOM must contain more then one element:\n$destination" + } + + dependenciesNode + .children() + .map { it as Node } + .forEach { + val groupId: String = it.getNode("groupId")!!.text() + assert(groupId.startsWith("org.mongodb")) { + "BOM must contain only 'org.mongodb' dependencies, but found '$groupId':\n$destination" + } + + /* + * The and tags should be omitted in BOM dependencies. + * This ensures that consuming projects have the flexibility to decide whether a dependency is optional in their context. + * + * The BOM's role is to provide version information, not to dictate inclusion or exclusion of dependencies. + */ + assert(it.getNode("scope") == null) { + "BOM must not contain elements in dependency:\n$destination" + } + assert(it.getNode("optional") == null) { + "BOM must not contain elements in dependency:\n$destination" + } + } + } + } +} + +/** A node lookup helper. */ +private fun Node?.getNode(nodeName: String): Node? { + val found = this?.get(nodeName) + if (found is NodeList && found.isNotEmpty()) { + return found[0] as Node + } + return null +} diff --git a/bson-kotlin/build.gradle.kts b/bson-kotlin/build.gradle.kts index 84b6deabd31..2cfd4413637 100644 --- a/bson-kotlin/build.gradle.kts +++ b/bson-kotlin/build.gradle.kts @@ -13,133 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import io.gitlab.arturbosch.detekt.Detekt -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication -plugins { - id("org.jetbrains.kotlin.jvm") - id("java-library") - - // Test based plugins - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.detekt) -} - -repositories { - mavenCentral() - google() -} +plugins { id("project.kotlin") } base.archivesName.set("bson-kotlin") -description = "Bson Kotlin Codecs" - -ext.set("pomName", "Bson Kotlin") - dependencies { - // Align versions of all Kotlin components - implementation(platform(libs.kotlin.bom)) - implementation(libs.kotlin.stdlib.jdk8) - api(project(path = ":bson", configuration = "default")) implementation(libs.kotlin.reflect) - testImplementation(libs.junit.kotlin) + // Test case checks MongoClientSettings.getDefaultCodecRegistry() support testImplementation(project(path = ":driver-core", configuration = "default")) } -kotlin { explicitApi() } - -tasks.withType { kotlinOptions.jvmTarget = "1.8" } - -// =========================== -// Code Quality checks -// =========================== -spotless { - kotlinGradle { - ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") - } - - kotlin { - target("**/*.kt") - ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license")) - } - - format("extraneous") { - target("*.xml", "*.yml", "*.md") - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() +configureMavenPublication { + pom { + name.set("BSON Kotlin") + description.set("The BSON Codec for Kotlin") + url.set("https://bsonspec.org") } } -tasks.named("check") { dependsOn("spotlessApply") } - -detekt { - allRules = true // fail build on any finding - buildUponDefaultConfig = true // preconfigure defaults - config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, - // overwriting default behavior - baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt - source = - files( - file("src/main/kotlin"), - file("src/test/kotlin"), - file("src/integrationTest/kotlin"), - ) -} - -tasks.withType().configureEach { - reports { - html.required.set(true) // observe findings in your browser with structure and code snippets - xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins - txt.required.set(false) // similar to the console output, contains issue signature to manually edit - } -} - -spotbugs { showProgress.set(true) } - -// =========================== -// Test Configuration -// =========================== - -tasks.test { useJUnitPlatform() } - -// =========================== -// Dokka Configuration -// =========================== -val dokkaOutputDir = "${rootProject.buildDir}/docs/${base.archivesName.get()}" - -tasks.dokkaHtml.configure { - outputDirectory.set(file(dokkaOutputDir)) - moduleName.set(base.archivesName.get()) -} - -val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } - -project.parent?.tasks?.named("docs") { - dependsOn(tasks.dokkaHtml) - mustRunAfter(cleanDokka) -} - -tasks.javadocJar.configure { - dependsOn(cleanDokka, tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(dokkaOutputDir) -} - -// =========================== -// Sources publishing configuration -// =========================== -tasks.sourcesJar { from(project.sourceSets.main.map { it.kotlin }) } - -afterEvaluate { tasks.jar { manifest { attributes["Automatic-Module-Name"] = "org.mongodb.bson.kotlin" } } } +configureJarManifest { attributes["Automatic-Module-Name"] = "org.mongodb.bson.kotlin" } diff --git a/bson-kotlinx/build.gradle.kts b/bson-kotlinx/build.gradle.kts index d2b3e13919b..1671a876edf 100644 --- a/bson-kotlinx/build.gradle.kts +++ b/bson-kotlinx/build.gradle.kts @@ -13,146 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import io.gitlab.arturbosch.detekt.Detekt -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication plugins { - id("org.jetbrains.kotlin.jvm") - kotlin("plugin.serialization") - id("java-library") - - // Test based plugins - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.detekt) -} - -repositories { - mavenCentral() - google() + id("project.kotlin") + alias(libs.plugins.kotlin.serialization) } base.archivesName.set("bson-kotlinx") -description = "Bson Kotlinx Codecs" - -ext.set("pomName", "Bson Kotlinx") - -java { - registerFeature("dateTimeSupport") { usingSourceSet(sourceSets["main"]) } - registerFeature("jsonSupport") { usingSourceSet(sourceSets["main"]) } -} - dependencies { - // Align versions of all Kotlin components - implementation(platform(libs.kotlin.bom)) - implementation(libs.kotlin.stdlib.jdk8) - + api(project(path = ":bson", configuration = "default")) implementation(platform(libs.kotlinx.serialization)) implementation(libs.kotlinx.serialization.core) - "dateTimeSupportImplementation"(libs.kotlinx.serialization.datetime) - "jsonSupportImplementation"(libs.kotlinx.serialization.json) - - api(project(path = ":bson", configuration = "default")) implementation(libs.kotlin.reflect) - testImplementation(project(path = ":driver-core", configuration = "default")) - testImplementation(libs.junit.kotlin) - testImplementation(libs.kotlinx.serialization.datetime) - testImplementation(libs.kotlinx.serialization.json) -} - -kotlin { explicitApi() } - -tasks.withType { kotlinOptions.jvmTarget = "1.8" } - -// =========================== -// Code Quality checks -// =========================== -spotless { - kotlinGradle { - ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") - } - - kotlin { - target("**/*.kt") - ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license")) - } - - format("extraneous") { - target("*.xml", "*.yml", "*.md") - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } -} - -tasks.named("check") { dependsOn("spotlessApply") } + optionalApi(libs.kotlinx.serialization.datetime) + optionalApi(libs.kotlinx.serialization.json) -detekt { - allRules = true // fail build on any finding - buildUponDefaultConfig = true // preconfigure defaults - config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, - // overwriting default behavior - baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt - source = - files( - file("src/main/kotlin"), - file("src/test/kotlin"), - file("src/integrationTest/kotlin"), - ) + // Test case checks MongoClientSettings.getDefaultCodecRegistry() support + testImplementation(project(path = ":driver-core", configuration = "default")) } -tasks.withType().configureEach { - reports { - html.required.set(true) // observe findings in your browser with structure and code snippets - xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins - txt.required.set(false) // similar to the console output, contains issue signature to manually edit +configureMavenPublication { + pom { + name.set("BSON Kotlinx") + description.set("The BSON Codec for Kotlinx serialization") + url.set("https://bsonspec.org") } } -spotbugs { showProgress.set(true) } - -// =========================== -// Test Configuration -// =========================== - -tasks.test { useJUnitPlatform() } - -// =========================== -// Dokka Configuration -// =========================== -val dokkaOutputDir = "${rootProject.buildDir}/docs/${base.archivesName.get()}" - -tasks.dokkaHtml.configure { - outputDirectory.set(file(dokkaOutputDir)) - moduleName.set(base.archivesName.get()) -} - -val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } - -project.parent?.tasks?.named("docs") { - dependsOn(tasks.dokkaHtml) - mustRunAfter(cleanDokka) -} - -tasks.javadocJar.configure { - dependsOn(cleanDokka, tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(dokkaOutputDir) -} - -// =========================== -// Sources publishing configuration -// =========================== -tasks.sourcesJar { from(project.sourceSets.main.map { it.kotlin }) } - -afterEvaluate { tasks.jar { manifest { attributes["Automatic-Module-Name"] = "org.mongodb.bson.kotlinx" } } } +configureJarManifest { attributes["Automatic-Module-Name"] = "org.mongodb.bson.kotlinx" } diff --git a/bson-record-codec/build.gradle b/bson-record-codec/build.gradle deleted file mode 100644 index 5a880461a77..00000000000 --- a/bson-record-codec/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -archivesBaseName = 'bson-record-codec' -description = 'The BSON Codec for Java records' - -ext { - pomName = 'BSON Record Codec' -} - -dependencies { - api project(path: ':bson', configuration: 'default') - testImplementation project(':bson').sourceSets.test.output - testImplementation project(':driver-core') -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.bson.record.codec' - jar.manifest.attributes['Bundle-SymbolicName'] = 'org.mongodb.bson-record-codec' -} - -tasks.withType(Test) { - test.onlyIf { javaVersion.isCompatibleWith(javaVersion.VERSION_17) } -} - -tasks.withType(Javadoc) { - dependsOn(project(':bson').tasks.withType(Javadoc), project(':driver-core').tasks.withType(Javadoc)) -} diff --git a/bson-record-codec/build.gradle.kts b/bson-record-codec/build.gradle.kts new file mode 100644 index 00000000000..5165679c06b --- /dev/null +++ b/bson-record-codec/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.test-artifacts") +} + +base.archivesName.set("bson-record-codec") + +dependencies { + api(project(path = ":bson", configuration = "default")) + + // Test case checks MongoClientSettings.getDefaultCodecRegistry() support + testImplementation(project(path = ":driver-core", configuration = "default")) +} + +configureMavenPublication { + pom { + name.set("BSON Record Codec") + description.set("The BSON Codec for Java records") + url.set("https://bsonspec.org") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.bson.record.codec" + attributes["Bundle-SymbolicName"] = "org.mongodb.bson-record-codec" +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType { options.release.set(17) } + +tasks.withType().configureEach { onlyIf { javaVersion.isCompatibleWith(JavaVersion.VERSION_17) } } diff --git a/bson-scala/build.gradle b/bson-scala/build.gradle deleted file mode 100644 index 5d21ed521b5..00000000000 --- a/bson-scala/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -description = "A Scala wrapper / extension to the bson library" -archivesBaseName = 'mongo-scala-bson' - -dependencies { - api project(path: ':bson', configuration: 'default') -} - -sourceSets { - main { - scala { - if(scalaVersion.startsWith("2.13")) { - srcDirs = ["src/main/scala", "src/main/scala-2.13+"] - } else { - srcDirs = ["src/main/scala", "src/main/scala-2.13-"] - } - } - } -} - -tasks.withType(Test) { - doFirst { - println("Running Test task using scala version: $scalaVersion") - } -} - -// =================== -// Scala checks -// =================== -tasks.register("scalaCheck") { - description = "Runs all the Scala checks" - group = "verification" - - dependsOn("clean", "compileTestScala", "check") - tasks.findByName("check").mustRunAfter("clean") -} - -ext { - pomName = 'Mongo Scala Bson Library' -} - -test { - maxParallelForks = 1 -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.bson.scala' - jar.manifest.attributes['Import-Package'] = [ - '!scala.*', - '*' - ].join(',') -} diff --git a/bson-scala/build.gradle.kts b/bson-scala/build.gradle.kts new file mode 100644 index 00000000000..e23087ae314 --- /dev/null +++ b/bson-scala/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { id("project.scala") } + +base.archivesName.set("mongo-scala-bson") + +dependencies { api(project(path = ":bson", configuration = "default")) } + +configureMavenPublication { + pom { + name.set("Mongo Scala BSON Library") + description.set("A Scala wrapper / extension to the BSON library") + url.set("https://bsonspec.org") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.bson.scala" + attributes["Bundle-SymbolicName"] = "org.mongodb.scala.mongo-scala-bson" + attributes["Import-Package"] = "!scala.*,*" +} diff --git a/bson-scala/src/test/scala/org/mongodb/scala/bson/BaseSpec.scala b/bson-scala/src/test/scala/org/mongodb/scala/bson/BaseSpec.scala index ad6cab0069a..4ac18c5b31c 100644 --- a/bson-scala/src/test/scala/org/mongodb/scala/bson/BaseSpec.scala +++ b/bson-scala/src/test/scala/org/mongodb/scala/bson/BaseSpec.scala @@ -15,10 +15,7 @@ */ package org.mongodb.scala.bson -import org.junit.runner.RunWith import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -import org.scalatestplus.junit.JUnitRunner -@RunWith(classOf[JUnitRunner]) abstract class BaseSpec extends AnyFlatSpec with Matchers {} diff --git a/bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/MacrosSpec.scala b/bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/MacrosSpec.scala index c16215a16e8..e3c8ded2d89 100644 --- a/bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/MacrosSpec.scala +++ b/bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/MacrosSpec.scala @@ -531,6 +531,7 @@ class MacrosSpec extends BaseSpec { } it should "support tagged types in case classes" in { + assume(!scala.util.Properties.versionNumberString.startsWith("2.11")) val a = 1.asInstanceOf[Int with Tag] val b = "b".asInstanceOf[String with Tag] val c = Map("c" -> 0).asInstanceOf[Map[String with Tag, Int with Tag] with Tag] diff --git a/bson/build.gradle.kts b/bson/build.gradle.kts new file mode 100644 index 00000000000..fab3cdaacb5 --- /dev/null +++ b/bson/build.gradle.kts @@ -0,0 +1,39 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.testing-junit") + id("conventions.testing-spock") + id("conventions.test-artifacts") +} + +base.archivesName.set("bson") + +configureMavenPublication { + pom { + name.set("BSON") + description.set("The BSON library") + url.set("https://bsonspec.org") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.bson" + attributes["Import-Package"] = "org.slf4j.*;resolution:=optional" +} diff --git a/bson/src/test/unit/org/bson/GenericBsonTest.java b/bson/src/test/unit/org/bson/GenericBsonTest.java index 6ba2c6ae382..582ec5d83dc 100644 --- a/bson/src/test/unit/org/bson/GenericBsonTest.java +++ b/bson/src/test/unit/org/bson/GenericBsonTest.java @@ -25,11 +25,9 @@ import org.junit.jupiter.params.provider.MethodSource; import util.JsonPoweredTestHelper; -import java.io.File; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; -import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -283,10 +281,9 @@ private void throwIfValueIsStringContainingReplacementCharacter(final BsonDocume } - private static Stream data() throws URISyntaxException, IOException { + private static Stream data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/bson")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/bson")) { for (BsonValue curValue : testDocument.getArray("valid", new BsonArray())) { BsonDocument testCaseDocument = curValue.asDocument(); data.add(Arguments.of( diff --git a/bson/src/test/unit/org/bson/vector/BinaryVectorGenericBsonTest.java b/bson/src/test/unit/org/bson/vector/BinaryVectorGenericBsonTest.java index 858174d7cd9..35326281c66 100644 --- a/bson/src/test/unit/org/bson/vector/BinaryVectorGenericBsonTest.java +++ b/bson/src/test/unit/org/bson/vector/BinaryVectorGenericBsonTest.java @@ -16,6 +16,7 @@ package org.bson.vector; +import org.bson.BinaryVector; import org.bson.BsonArray; import org.bson.BsonBinary; import org.bson.BsonDocument; @@ -23,16 +24,12 @@ import org.bson.BsonValue; import org.bson.Float32BinaryVector; import org.bson.PackedBitBinaryVector; -import org.bson.BinaryVector; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -73,7 +70,7 @@ class BinaryVectorGenericBsonTest { @ParameterizedTest(name = "{0}") - @MethodSource("provideTestCases") + @MethodSource("data") void shouldPassAllOutcomes(@SuppressWarnings("unused") final String description, final BsonDocument testDefinition, final BsonDocument testCase) { assumeFalse(TEST_NAMES_TO_IGNORE.contains(testCase.get("description").asString().getValue())); @@ -254,10 +251,9 @@ private static float parseFloat(final BsonString bsonValue) { } } - private static Stream provideTestCases() throws URISyntaxException, IOException { + private static Stream data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/bson-binary-vector")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/bson-binary-vector")) { for (BsonValue curValue : testDocument.getArray("tests", new BsonArray())) { BsonDocument testCaseDocument = curValue.asDocument(); data.add(Arguments.of(createTestCaseDescription(testDocument, testCaseDocument), testDocument, testCaseDocument)); diff --git a/bson/src/test/unit/util/JsonPoweredTestHelper.java b/bson/src/test/unit/util/JsonPoweredTestHelper.java index 4507e64301b..a94e3c5cb80 100644 --- a/bson/src/test/unit/util/JsonPoweredTestHelper.java +++ b/bson/src/test/unit/util/JsonPoweredTestHelper.java @@ -17,105 +17,107 @@ package util; import org.bson.BsonDocument; +import org.bson.BsonString; +import org.bson.BsonValue; import org.bson.codecs.BsonDocumentCodec; import org.bson.codecs.DecoderContext; import org.bson.json.JsonReader; import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.net.URL; +import java.net.URI; import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.PathMatcher; import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.function.Function; -import static java.nio.file.Files.isDirectory; -import static java.util.stream.Collectors.toMap; +import static org.bson.assertions.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; public final class JsonPoweredTestHelper { - public static BsonDocument getTestDocument(final File file) throws IOException { - return new BsonDocumentCodec().decode(new JsonReader(getFileAsString(file)), DecoderContext.builder().build()); + public static BsonDocument getTestDocument(final String resourcePath) { + BsonDocument testDocument = getTestDocumentWithMetaData(resourcePath); + testDocument.remove("resourcePath"); + testDocument.remove("fileName"); + return testDocument; } - public static BsonDocument getTestDocument(final String resourcePath) throws IOException, URISyntaxException { - return getTestDocument(new File(JsonPoweredTestHelper.class.getResource(resourcePath).toURI())); - } - - public static Path testDir(final String resourceName) { - URL res = JsonPoweredTestHelper.class.getResource(resourceName); - if (res == null) { - throw new AssertionError("Did not find " + resourceName); - } - try { - Path dir = Paths.get(res.toURI()); - if (!isDirectory(dir)) { - throw new AssertionError(dir + " is not a directory"); + public static Collection getTestData(final String resourcePath) { + List data = new ArrayList<>(); + for (BsonDocument document : getTestDocuments(resourcePath)) { + for (BsonValue test : document.getArray("tests")) { + BsonDocument testDocument = test.asDocument(); + data.add(new Object[]{document.getString("fileName").getValue(), + testDocument.getString("description").getValue(), + testDocument.getString("uri", new BsonString("")).getValue(), + testDocument}); } - return dir; - } catch (URISyntaxException e) { - throw new RuntimeException(e); } + return data; } - public static Map testDocs(final Path dir) { - PathMatcher jsonMatcher = FileSystems.getDefault().getPathMatcher("glob:**.json"); + public static List getTestDocuments(final String resourcePath) { + List files = new ArrayList<>(); try { - return Files.list(dir) - .filter(jsonMatcher::matches) - .collect(toMap(Function.identity(), path -> { - try { - return getTestDocument(path.toFile()); - } catch (IOException e) { - throw new RuntimeException(e); + URI resource = assertNotNull(JsonPoweredTestHelper.class.getResource(resourcePath)).toURI(); + try (FileSystem fileSystem = (resource.getScheme().equals("jar") ? FileSystems.newFileSystem(resource, Collections.emptyMap()) : null)) { + Path myPath = Paths.get(resource); + Files.walkFileTree(myPath, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attrs) throws IOException { + if (filePath.toString().endsWith(".json")) { + if (fileSystem == null) { + files.add(getTestDocumentWithMetaData(filePath.toString().substring(filePath.toString().lastIndexOf(resourcePath)))); + } else { + files.add(getTestDocumentWithMetaData(filePath.toString())); + } } - })); - } catch (IOException e) { - throw new RuntimeException(e); + return super.visitFile(filePath, attrs); + } + }); + } + } catch (Exception e) { + fail("Unable to load resource", e); } + return files; } - public static List getTestFiles(final String resourcePath) throws URISyntaxException { - List files = new ArrayList<>(); - addFilesFromDirectory(new File(JsonPoweredTestHelper.class.getResource(resourcePath).toURI()), files); - return files; + private static BsonDocument getTestDocumentWithMetaData(final String resourcePath) { + JsonReader jsonReader = new JsonReader(resourcePathToString(resourcePath)); + BsonDocument testDocument = new BsonDocumentCodec().decode(jsonReader, DecoderContext.builder().build()); + testDocument.append("resourcePath", new BsonString(resourcePath)) + .append("fileName", new BsonString(resourcePath.substring(resourcePath.lastIndexOf('/') + 1))); + return testDocument; } - private static String getFileAsString(final File file) throws IOException { + private static String resourcePathToString(final String resourcePath) { StringBuilder stringBuilder = new StringBuilder(); String line; - String ls = System.getProperty("line.separator"); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { - while ((line = reader.readLine()) != null) { - stringBuilder.append(line); - stringBuilder.append(ls); - } - } - return stringBuilder.toString(); - } - - private static void addFilesFromDirectory(final File directory, final List files) { - String[] fileNames = directory.list(); - if (fileNames != null) { - for (String fileName : fileNames) { - File file = new File(directory, fileName); - if (file.isDirectory()) { - addFilesFromDirectory(file, files); - } else if (file.getName().endsWith(".json")) { - files.add(file); + String ls = System.lineSeparator(); + try (InputStream inputStream = JsonPoweredTestHelper.class.getResourceAsStream(resourcePath)) { + assertNotNull(inputStream); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append(ls); } } + } catch (Exception e) { + fail("Unable to load resource", e); } + return stringBuilder.toString(); } private JsonPoweredTestHelper() { diff --git a/build.gradle b/build.gradle deleted file mode 100644 index f9f767ef652..00000000000 --- a/build.gradle +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -plugins { - id("eclipse") - id("idea") - - alias(libs.plugins.bnd) apply false - alias(libs.plugins.detekt) apply false - alias(libs.plugins.dokka) apply false - alias(libs.plugins.download) apply false - alias(libs.plugins.kotlin) apply false - alias(libs.plugins.kotlin.serialization) apply false - alias(libs.plugins.optional) apply false - alias(libs.plugins.scala.multiversion) apply false - alias(libs.plugins.spotbugs) apply false - alias(libs.plugins.spotless) apply false - alias(libs.plugins.test.logger) apply false -} - -////////////////////////////////////////// -// Common behavior // -////////////////////////////////////////// - -ext { - configDir = new File(rootDir, 'config') - jnrUnixsocketVersion = '0.38.17' - nettyVersion = '4.1.87.Final' - snappyVersion = '1.1.10.3' - zstdVersion = '1.5.5-3' - awsSdkV2Version = '2.30.31' - awsSdkV1Version = '1.12.782' - projectReactorVersion = '2022.0.0' - junitBomVersion = '5.10.2' - logbackVersion = '1.3.14' - graalSdkVersion = '24.0.0' - reflectionsVersion = '0.9.10' - gitVersion = getGitVersion() -} - -def configDir = ext.configDir -def utilProjects = project(":util").allprojects -def bomProjects = project(":bom") -def coreProjects = subprojects - utilProjects -def scalaProjects = subprojects.findAll { it.name.contains('scala') } - bomProjects -def javaProjects = subprojects - scalaProjects - bomProjects -def javaMainProjects = javaProjects - utilProjects -def javaCodeCheckedProjects = javaMainProjects.findAll { !['driver-benchmarks', 'driver-workload-executor', 'driver-lambda'].contains(it.name) } -def javaAndScalaTestedProjects = javaCodeCheckedProjects + scalaProjects - -configure(coreProjects) { - apply plugin: 'idea' - - group = 'org.mongodb' - version = '5.4.0-SNAPSHOT' - - repositories { - mavenLocal() - google() - mavenCentral() - - // Uncomment this to test with a snapshot build of mongodb-crypt - maven { - url 'https://oss.sonatype.org/content/repositories/snapshots' - content { - includeGroup "org.mongodb" - } - } - } -} - -configure(javaProjects) { - apply plugin: 'java-library' - - sourceSets { - main { - java.srcDirs = ['src/main'] - } - } - - tasks.withType(GenerateModuleMetadata) { - enabled = false - } - -} - -configure(scalaProjects) { - apply plugin: "java-library" - apply plugin: "scala" - apply plugin: "com.adtran.scala-multiversion-plugin" - apply plugin: "com.diffplug.spotless" - - group = 'org.mongodb.scala' - - dependencies { - api(libs.scala.library) - api(libs.scala.reflect) - - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.bundles.junit.vintage) - testImplementation(libs.bundles.scalatest) - testImplementation(libs.reflections) - } - - test{ - useJUnitPlatform { - includeEngines('junit-jupiter', 'junit-vintage') - } - } - - spotless { - scala { - scalafmt().configFile("$configDir/scala/scalafmt.conf") - } - } - compileScala.dependsOn('spotlessApply') - compileTestScala.dependsOn('spotlessApply') - - tasks.withType(ScalaCompile) { - scalaCompileOptions.deprecation = false - if(scalaVersion.startsWith("2.11")) { - scalaCompileOptions.additionalParameters = [ - // support static methods in interfaces - "-target:jvm-1.8" - ] - } - if(scalaVersion.startsWith("2.13")) { - scalaCompileOptions.additionalParameters = [ - "-feature", - "-unchecked", - "-language:reflectiveCalls", - "-Wconf:cat=deprecation:ws", - "-Wconf:msg=While parsing annotations in:silent", - "-Xlint:strict-unsealed-patmat" - ] - } - - } - - tasks.withType(GenerateModuleMetadata) { - enabled = false - } -} - -configure(javaMainProjects) { - apply plugin: 'nebula.optional-base' - apply plugin: 'java-library' - - dependencies { - compileOnly(libs.findbugs.jsr) - api(libs.slf4j, optional) - - testImplementation(libs.findbugs.jsr) - // https://issues.apache.org/jira/browse/GROOVY-10194 - testImplementation(libs.groovy) - } - - /* Compiling */ - tasks.withType(AbstractCompile) { - options.encoding = 'ISO-8859-1' - options.fork = true - options.debug = true - options.compilerArgs = ['-Xlint:all'] - } -} - -configure(javaAndScalaTestedProjects) { - /* Testing */ - tasks.withType(Test) { - systemProperties(System.getProperties().findAll { it.key.toString().startsWith("org.mongodb.") }) - systemProperty('jna.library.path', System.getProperty('jna.library.path')) - - project.ext.buildingWith = { propertyName -> - project.hasProperty(propertyName) && project.property(propertyName).toBoolean() - } - - if (project.buildingWith('ssl.enabled')) { - if (project.hasProperty('ssl.keyStoreType')) { - systemProperties( - 'javax.net.ssl.keyStoreType': project.property('ssl.keyStoreType'), - 'javax.net.ssl.keyStore': project.property('ssl.keyStore'), - 'javax.net.ssl.keyStorePassword': project.property('ssl.keyStorePassword') - ) - } - if (project.hasProperty('ssl.trustStoreType')) { - systemProperties( - 'javax.net.ssl.trustStoreType': project.property('ssl.trustStoreType'), - 'javax.net.ssl.trustStore': project.property('ssl.trustStore'), - 'javax.net.ssl.trustStorePassword': project.property('ssl.trustStorePassword') - ) - } - if (project.hasProperty('ocsp.property')) { - systemProperties( - 'org.mongodb.test.ocsp.tls.should.succeed': project.property('ocsp.tls.should.succeed'), - 'java.security.properties': file(project.property('ocsp.property')), - 'com.sun.net.ssl.checkRevocation': project.property('ssl.checkRevocation'), - 'jdk.tls.client.enableStatusRequestExtension': project.property('client.enableStatusRequestExtension'), - 'jdk.tls.client.protocols': project.property('client.protocols') - ) - } - } - - if (project.buildingWith('gssapi.enabled')) { - systemProperties( - 'sun.security.krb5.debug': project.getProperty('sun.security.krb5.debug'), - 'javax.security.auth.useSubjectCredsOnly': "false", - 'java.security.krb5.kdc': project.getProperty('krb5.kdc'), - 'java.security.krb5.realm': project.getProperty('krb5.realm'), - 'java.security.auth.login.config': project.getProperty('auth.login.config'), - ) - } - } -} - -configure(javaCodeCheckedProjects) { - apply plugin: 'checkstyle' - apply plugin: "com.github.spotbugs" - apply plugin: 'jacoco' - apply plugin: 'groovy' - apply plugin: 'codenarc' - apply plugin: 'com.adarshr.test-logger' - - dependencies { - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.bundles.junit.vintage) - - testImplementation(platform(libs.spock.bom)) - testImplementation(libs.bundles.spock) - - if ('8'.equals(findProperty("javaVersion"))) { - testImplementation(libs.bundles.mockito.java8) - } else { - testImplementation(libs.bundles.mockito) - } - testImplementation(libs.cglib) - testImplementation(libs.objenesis) - testImplementation project(':util:spock') //Adding categories to classpath - } - - sourceSets { - test { - groovy.srcDirs = ['src/test/functional', 'src/test/unit'] - } - } - - /* Testing */ - tasks.withType(Test) { - maxHeapSize = "4g" - maxParallelForks = 1 - - useJUnitPlatform { - includeEngines('junit-jupiter', 'junit-vintage', 'spock') - excludeTags('Slow') - } - systemProperty('spock.configuration', "${configDir}/spock/ExcludeSlow.groovy") - - jacoco { enabled = false } - - testLogging { - exceptionFormat = 'full' - events("passed", "skipped", "failed") - } - - testlogger { - theme 'standard' - showExceptions false - showStackTraces false - showFullStackTraces false - } - } - - task testSlowOnly(type: Test) { - dependsOn('testSlowGroovy') - useJUnitPlatform { - includeEngines('junit-jupiter', 'junit-vintage') - includeTags('Slow') - } - } - - task testSlowGroovy(type: Test) { - useJUnitPlatform { - includeEngines( 'spock') - } - systemProperty('spock.configuration', "${configDir}/spock/OnlySlow.groovy") - } - - gradle.taskGraph.whenReady { taskGraph -> - if (taskGraph.hasTask(testCoverage)) { - tasks.withType(Test) { jacoco { enabled = true } } - } - } - - task testCoverage(dependsOn: test) - - /* Code quality */ - tasks.withType(Checkstyle) { - reports { - xml.required = true - html.required = true - } - } - - checkstyle { - toolVersion = "9.1" - } - - spotbugs { - if (!project.buildingWith('ssdlcReport.enabled')) { - excludeFilter = new File(configDir, 'spotbugs/exclude.xml') - } - } - - codenarc { - toolVersion = '1.6.1' - reportFormat = project.buildingWith('xmlReports.enabled') ? 'xml' : 'html' - } - - spotbugsMain { - reports { - xml.enabled = project.buildingWith('xmlReports.enabled') - html.enabled = !project.buildingWith('xmlReports.enabled') - sarif.enabled = project.buildingWith('ssdlcReport.enabled') - } - } - - spotbugsTest { - enabled = false - } -} - -def getGitVersion() { - def describeStdOut = new ByteArrayOutputStream() - exec { - commandLine 'git', 'describe', '--tags', '--always', '--dirty' - standardOutput = describeStdOut - } - describeStdOut.toString().substring(1).trim() -} - -apply from: 'gradle/javaToolchain.gradle' -apply from: 'gradle/publish.gradle' -apply from: 'gradle/deploy.gradle' -apply from: 'gradle/javadoc.gradle' diff --git a/util/spock/build.gradle b/build.gradle.kts similarity index 93% rename from util/spock/build.gradle rename to build.gradle.kts index 4498034e07a..287017f0ed4 100644 --- a/util/spock/build.gradle +++ b/build.gradle.kts @@ -14,3 +14,7 @@ * limitations under the License. */ +plugins { + id("eclipse") + id("idea") +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000000..23095a6700b --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,83 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import dev.panuszewski.gradle.pluginMarker + +plugins { + id("java-library") + `kotlin-dsl` + alias(libs.plugins.spotless) + alias(libs.plugins.detekt) apply false +} + +repositories { + gradlePluginPortal() + mavenCentral() + google() +} + +// Dependencies needed for the configuration of the plugins +// Uses `pluginMarker` from the `typesafe-conventions` plugin, see `settings.gradle.kts` +dependencies { + implementation(pluginMarker(libs.plugins.bnd)) + implementation(pluginMarker(libs.plugins.detekt)) + implementation(pluginMarker(libs.plugins.dokka)) + implementation(pluginMarker(libs.plugins.kotlin.gradle)) + implementation(pluginMarker(libs.plugins.spotbugs)) + implementation(pluginMarker(libs.plugins.spotless)) + implementation(pluginMarker(libs.plugins.test.logger)) +} + +// Spotless configuration for `buildSrc` code. +spotless { + kotlinGradle { + target("**/*.gradle.kts") + ktfmt("0.39").dropboxStyle().configure { + it.setMaxWidth(120) + it.setRemoveUnusedImport(true) + } + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + licenseHeaderFile( + "../config/mongodb.license", "(package|group|plugins|import|buildscript|rootProject|@Suppress)") + } + + kotlin { + target("**/*.kt") + ktfmt().dropboxStyle().configure { + it.setMaxWidth(120) + it.setRemoveUnusedImport(true) + } + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + licenseHeaderFile(rootProject.file("../config/mongodb.license")) + } + + java { + palantirJavaFormat() + target("src/*/java/**/*.java") + removeUnusedImports() + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + licenseHeaderFile(rootProject.file("../config/mongodb.license")) + } +} + +java { toolchain { languageVersion.set(JavaLanguageVersion.of("17")) } } + +tasks.findByName("check")?.dependsOn("spotlessCheck") diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 00000000000..ae51c27d8ae --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,21 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +plugins { + // Add support for `libs.versions.toml` within `buildSrc` + // https://github.com/radoslaw-panuszewski/typesafe-conventions-gradle-plugin + // https://github.com/gradle/gradle/issues/15383 + id("dev.panuszewski.typesafe-conventions") version "0.4.1" +} diff --git a/util/taglets/src/main/AtlasManualTaglet.java b/buildSrc/src/main/java/com/mongodb/doclet/AtlasManualTaglet.java similarity index 97% rename from util/taglets/src/main/AtlasManualTaglet.java rename to buildSrc/src/main/java/com/mongodb/doclet/AtlasManualTaglet.java index 004ce1b64c1..673b55a6bf6 100644 --- a/util/taglets/src/main/AtlasManualTaglet.java +++ b/buildSrc/src/main/java/com/mongodb/doclet/AtlasManualTaglet.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.mongodb.doclet; public final class AtlasManualTaglet extends DocTaglet { @Override diff --git a/util/taglets/src/main/DocTaglet.java b/buildSrc/src/main/java/com/mongodb/doclet/DocTaglet.java similarity index 93% rename from util/taglets/src/main/DocTaglet.java rename to buildSrc/src/main/java/com/mongodb/doclet/DocTaglet.java index c63265e40a4..0f51f45f197 100644 --- a/util/taglets/src/main/DocTaglet.java +++ b/buildSrc/src/main/java/com/mongodb/doclet/DocTaglet.java @@ -13,15 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import com.sun.source.doctree.DocTree; -import com.sun.source.doctree.UnknownBlockTagTree; -import jdk.javadoc.doclet.Taglet; - -import javax.lang.model.element.Element; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +package com.mongodb.doclet; import static java.util.Arrays.asList; import static jdk.javadoc.doclet.Taglet.Location.CONSTRUCTOR; @@ -31,6 +23,14 @@ import static jdk.javadoc.doclet.Taglet.Location.PACKAGE; import static jdk.javadoc.doclet.Taglet.Location.TYPE; +import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.UnknownBlockTagTree; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.Element; +import jdk.javadoc.doclet.Taglet; + public abstract class DocTaglet implements Taglet { @Override @@ -49,7 +49,8 @@ public String toString(List tags, Element element) { return null; } - StringBuilder buf = new StringBuilder(String.format("
%s
", getHeader())); + StringBuilder buf = + new StringBuilder(String.format("
%s
", getHeader())); for (DocTree tag : tags) { String text = ((UnknownBlockTagTree) tag).getContent().get(0).toString(); buf.append("
").append(genLink(text)).append("
"); diff --git a/util/taglets/src/main/DochubTaglet.java b/buildSrc/src/main/java/com/mongodb/doclet/DochubTaglet.java similarity index 97% rename from util/taglets/src/main/DochubTaglet.java rename to buildSrc/src/main/java/com/mongodb/doclet/DochubTaglet.java index 2092e8ffa5c..a6b960eaa27 100644 --- a/util/taglets/src/main/DochubTaglet.java +++ b/buildSrc/src/main/java/com/mongodb/doclet/DochubTaglet.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.mongodb.doclet; public class DochubTaglet extends DocTaglet { @@ -30,5 +31,4 @@ protected String getHeader() { protected String getBaseDocURI() { return "https://dochub.mongodb.org/"; } - } diff --git a/util/taglets/src/main/ManualTaglet.java b/buildSrc/src/main/java/com/mongodb/doclet/ManualTaglet.java similarity index 97% rename from util/taglets/src/main/ManualTaglet.java rename to buildSrc/src/main/java/com/mongodb/doclet/ManualTaglet.java index 8ccbc2b9f62..ff49c9ab37c 100644 --- a/util/taglets/src/main/ManualTaglet.java +++ b/buildSrc/src/main/java/com/mongodb/doclet/ManualTaglet.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.mongodb.doclet; public class ManualTaglet extends DocTaglet { @@ -30,5 +31,4 @@ protected String getHeader() { protected String getBaseDocURI() { return "https://www.mongodb.com/docs/manual/"; } - } diff --git a/util/taglets/src/main/ServerReleaseTaglet.java b/buildSrc/src/main/java/com/mongodb/doclet/ServerReleaseTaglet.java similarity index 97% rename from util/taglets/src/main/ServerReleaseTaglet.java rename to buildSrc/src/main/java/com/mongodb/doclet/ServerReleaseTaglet.java index 6508ceab712..9b4f88fbf92 100644 --- a/util/taglets/src/main/ServerReleaseTaglet.java +++ b/buildSrc/src/main/java/com/mongodb/doclet/ServerReleaseTaglet.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.mongodb.doclet; public class ServerReleaseTaglet extends DocTaglet { @@ -30,5 +31,4 @@ protected String getHeader() { protected String getBaseDocURI() { return "https://www.mongodb.com/docs/manual/release-notes/"; } - } diff --git a/buildSrc/src/main/kotlin/ProjectExtensions.kt b/buildSrc/src/main/kotlin/ProjectExtensions.kt new file mode 100644 index 00000000000..a369aefc9d2 --- /dev/null +++ b/buildSrc/src/main/kotlin/ProjectExtensions.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import org.gradle.api.Project +import org.gradle.api.java.archives.Manifest +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.bundling.Jar +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.withType + +object ProjectExtensions { + + /** + * Extension function to get and validate the current scala version + * + * See: gradle.properties for `supportedScalaVersions` and `defaultScalaVersion` + */ + fun Project.scalaVersion(): String { + val supportedScalaVersions = (project.property("supportedScalaVersions") as String).split(",") + val scalaVersion: String = + (project.findProperty("scalaVersion") ?: project.property("defaultScalaVersion")) as String + + if (!supportedScalaVersions.contains(scalaVersion)) { + throw UnsupportedOperationException( + """Scala version: $scalaVersion is not a supported scala version. + |Supported versions: $supportedScalaVersions + """ + .trimMargin()) + } + + return scalaVersion + } + + /** Extension function to configure the maven publication */ + fun Project.configureMavenPublication(configure: MavenPublication.() -> Unit = {}) { + val publishing = extensions.getByName("publishing") as org.gradle.api.publish.PublishingExtension + publishing.publications.named("maven") { configure() } + } + + /** Extension function to configure the jars manifest */ + fun Project.configureJarManifest(configure: Manifest.() -> Unit = {}) { + tasks.withType { manifest { afterEvaluate { configure() } } } + } +} diff --git a/buildSrc/src/main/kotlin/conventions/Companion.kt b/buildSrc/src/main/kotlin/conventions/Companion.kt new file mode 100644 index 00000000000..c28eef2a080 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/Companion.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import org.gradle.accessors.dm.LibrariesForLibs +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +// Adds the `libs` value for use in conventions +internal val Project.libs: LibrariesForLibs + get() = extensions.getByType() + +/** Extension function to determine if a project property has been set. */ +fun Project.buildingWith(name: String): Boolean { + return this.findProperty(name)?.toString()?.toBoolean() ?: false +} diff --git a/util/build.gradle b/buildSrc/src/main/kotlin/conventions/bnd.gradle.kts similarity index 77% rename from util/build.gradle rename to buildSrc/src/main/kotlin/conventions/bnd.gradle.kts index 6a2444433a7..39a4513b41d 100644 --- a/util/build.gradle +++ b/buildSrc/src/main/kotlin/conventions/bnd.gradle.kts @@ -13,3 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package conventions + +// Gradle Plugin for developing OSGi bundles with Bnd. +// https://plugins.gradle.org/plugin/biz.aQute.bnd.builder + +plugins { id("biz.aQute.bnd.builder") } diff --git a/buildSrc/src/main/kotlin/conventions/codenarc.gradle.kts b/buildSrc/src/main/kotlin/conventions/codenarc.gradle.kts new file mode 100644 index 00000000000..25cd5c00cc8 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/codenarc.gradle.kts @@ -0,0 +1,25 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// The CodeNarc plugin performs quality checks on your project’s Groovy source files +// https://docs.gradle.org/current/userguide/codenarc_plugin.html +plugins { id("codenarc") } + +codenarc { + toolVersion = "1.6.1" + reportFormat = if (project.buildingWith("xmlReports.enabled")) "xml" else "html" +} diff --git a/buildSrc/src/main/kotlin/conventions/detekt.gradle.kts b/buildSrc/src/main/kotlin/conventions/detekt.gradle.kts new file mode 100644 index 00000000000..3ca88eac418 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/detekt.gradle.kts @@ -0,0 +1,44 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import io.gitlab.arturbosch.detekt.Detekt + +// Static code analysis for Kotlin +// https://plugins.gradle.org/plugin/io.gitlab.arturbosch.detekt +plugins { id("io.gitlab.arturbosch.detekt") } + +detekt { + allRules = true // fail build on any finding + buildUponDefaultConfig = true // preconfigure defaults + config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, + // overwriting default behavior + baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt + source = + files( + file("src/main/kotlin"), + file("src/test/kotlin"), + file("src/integrationTest/kotlin"), + ) +} + +tasks.withType().configureEach { + reports { + html.required.set(true) // observe findings in your browser with structure and code snippets + xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins + txt.required.set(false) // similar to the console output, contains issue signature to manually edit + } +} diff --git a/buildSrc/src/main/kotlin/conventions/dokka.gradle.kts b/buildSrc/src/main/kotlin/conventions/dokka.gradle.kts new file mode 100644 index 00000000000..8ad68409662 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/dokka.gradle.kts @@ -0,0 +1,47 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Dokka, the documentation engine for Kotlin +// https://plugins.gradle.org/plugin/org.jetbrains.dokka +plugins { + id("org.jetbrains.dokka") + id("conventions.publishing") +} + +// Create a generic `docs` task +tasks.register("docs") { + group = "documentation" + dependsOn("dokkaHtml") +} + +val dokkaOutputDir: Provider = rootProject.layout.buildDirectory.dir("docs/${base.archivesName.get()}") + +tasks.dokkaHtml.configure { + outputDirectory.set(dokkaOutputDir.get().asFile) + moduleName.set(base.archivesName.get()) +} + +val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } + +// Ensure dokka is used for the javadoc +afterEvaluate { + tasks.named("javadocJar").configure { + dependsOn("cleanDokka", "dokkaHtml") + archiveClassifier.set("javadoc") + from(dokkaOutputDir) + } +} diff --git a/buildSrc/src/main/kotlin/conventions/git-version.gradle.kts b/buildSrc/src/main/kotlin/conventions/git-version.gradle.kts new file mode 100644 index 00000000000..5370f59cea9 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/git-version.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Provides the current git version for the build + +val gitVersion: Provider = + providers + .exec { commandLine("git", "describe", "--tags", "--always", "--dirty") } + .standardOutput + .asText + .map { it.trim().removePrefix("r") } + +// Allows access to gitVersion extension to other conventions +extensions.add("gitVersion", gitVersion) + +// Debug task that outputs the gitVersion. +tasks.register("gitVersion") { doLast { println("Git version: ${gitVersion.get()}") } } diff --git a/buildSrc/src/main/kotlin/conventions/javadoc.gradle.kts b/buildSrc/src/main/kotlin/conventions/javadoc.gradle.kts new file mode 100644 index 00000000000..8ab2ef5bb5b --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/javadoc.gradle.kts @@ -0,0 +1,125 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Provides the Javadoc configuration for the build +plugins { + id("java-library") + id("maven-publish") +} + +// Create a generic `docs` task +tasks.register("docs") { + group = "documentation" + dependsOn("javadoc") +} + +tasks.withType { + exclude("**/com/mongodb/**/assertions/**") + exclude("**/com/mongodb/**/internal/**") + exclude("**/org/bson/**/internal/**") + + setDestinationDir(rootProject.file("build/docs/${project.base.archivesName.get()}")) + + val standardDocletOptions = options as StandardJavadocDocletOptions + standardDocletOptions.apply { + author(true) + version(true) + links = + listOf( + "https://docs.oracle.com/en/java/javase/11/docs/api/", + "https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/") + tagletPath(rootProject.projectDir.resolve("buildSrc/build/classes/java/main")) + taglets("com.mongodb.doclet.AtlasManualTaglet") + taglets("com.mongodb.doclet.ManualTaglet") + taglets("com.mongodb.doclet.DochubTaglet") + taglets("com.mongodb.doclet.ServerReleaseTaglet") + encoding = "UTF-8" + charSet("UTF-8") + docEncoding("UTF-8") + addBooleanOption("html5", true) + addBooleanOption("-allow-script-in-comments", true) + header( + """ + + """.trimIndent()) + } + + // Customizations for specific projects + afterEvaluate { + val docVersion = docVersion(project.version as String) + if (project.name != "bson") linksOfflineHelper(docVersion, "bson", standardDocletOptions) + if (!project.name.contains("bson") && project.name != "mongodb-driver-core") + linksOfflineHelper(docVersion, "mongodb-driver-core", standardDocletOptions) + if (!project.name.contains("bson") && project.name != "mongodb-driver-sync") + linksOfflineHelper(docVersion, "mongodb-driver-sync", standardDocletOptions) + } +} + +// Helper functions +internal fun docVersion(version: String): String { + val (major, minor, patch) = version.split("-").first().split(".").map { it.toInt() } + var docVersion = "${major}.${minor}" + if (version.contains("-SNAPSHOT") && patch == 0 && minor > 0) { + docVersion = "${major}.${minor - 1}" + } + return docVersion +} + +internal fun linksOfflineHelper(docVersion: String, packageName: String, options: StandardJavadocDocletOptions): Unit { + val docsPath = rootProject.file("build/docs/${packageName}") + if (docsPath.exists()) { + options.apply { + linksOffline( + "http://mongodb.github.io/mongo-java-driver/${docVersion}/apidocs/${packageName}/", docsPath.path) + } + } +} diff --git a/buildSrc/src/main/kotlin/conventions/optional.gradle.kts b/buildSrc/src/main/kotlin/conventions/optional.gradle.kts new file mode 100644 index 00000000000..1bf10321971 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/optional.gradle.kts @@ -0,0 +1,33 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Provides the optional dependencies support eg: optionalApi, optionalImplementation +plugins { + id("java-library") + id("maven-publish") +} + +java { registerFeature("optional") { usingSourceSet(sourceSets["main"]) } } + +// Suppress POM warnings for the optional features (eg: optionalApi, optionalImplementation) +afterEvaluate { + configurations + .filter { it.name.startsWith("optional") } + .forEach { optional -> + publishing.publications.named("maven") { suppressPomMetadataWarningsFor(optional.name) } + } +} diff --git a/buildSrc/src/main/kotlin/conventions/publishing.gradle.kts b/buildSrc/src/main/kotlin/conventions/publishing.gradle.kts new file mode 100644 index 00000000000..bd27acfabb5 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/publishing.gradle.kts @@ -0,0 +1,174 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Provides the publishing configuration for the build +// +// Note: Further configuration can be achieved using the `project.configureMavenPublication` and +// `project.configureJarManifest` helpers. +// See: `ProjectExtensions.kt` for more information +plugins { + id("conventions.git-version") + id("maven-publish") + id("signing") +} + +val signingKey: Provider = providers.gradleProperty("signingKey") +val signingPassword: Provider = providers.gradleProperty("signingPassword") +val nexusUsername: Provider = providers.gradleProperty("nexusUsername") +val nexusPassword: Provider = providers.gradleProperty("nexusPassword") +@Suppress("UNCHECKED_CAST") val gitVersion: Provider = project.findProperty("gitVersion") as Provider + +tasks.withType().configureEach { + // Gradle warns about some signing tasks using publishing task outputs without explicit + // dependencies. Here's a quick fix. + dependsOn(tasks.withType()) + mustRunAfter(tasks.withType()) + + doLast { + logger.lifecycle("[task: ${name}] ${publication.groupId}:${publication.artifactId}:${publication.version}") + } +} + +val localBuildRepo: Provider = rootProject.layout.buildDirectory.dir("repo") + +val sonatypeRepositoryReleaseUrl: Provider = provider { + if (version.toString().endsWith("SNAPSHOT")) { + "https://oss.sonatype.org/content/repositories/snapshots/" + } else { + "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + } +} + +publishing { + repositories { + maven { + url = uri(sonatypeRepositoryReleaseUrl) + if (nexusUsername.isPresent && nexusPassword.isPresent) { + credentials { + username = nexusUsername.get() + password = nexusPassword.get() + } + } + } + + // publish to local dir, for artifact tracking and testing + // `./gradlew publishMavenPublicationToLocalBuildRepository` + maven { + url = uri(localBuildRepo.get()) + name = "LocalBuild" + } + } + + publications.create("maven") { + components.findByName("java")?.let { from(it) } + + pom { + url.set("https://www.mongodb.com/") + scm { + url.set("https://github.com/mongodb/mongo-java-driver") + connection.set("scm:https://github.com/mongodb/mongo-java-driver.git") + developerConnection.set("scm:https://github.com/mongodb/mongo-java-driver.git") + } + + developers { + developer { + name.set("Various") + organization.set("MongoDB") + } + } + + licenses { + license { + name.set("The Apache License, Version 2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + } + + // Ensure get the final set `base.archivesName` not the default one (project name). + afterEvaluate { artifactId = base.archivesName.get() } + } +} + +tasks.withType { + manifest { attributes["-exportcontents"] = "*;-noimport:=true" } + + afterEvaluate { + manifest { + if (attributes.containsKey("-nomanifest")) { + attributes.remove("-exportcontents") + } else { + attributes["Bundle-Version"] = project.version + attributes["Bundle-SymbolicName"] = + "${project.findProperty("group")}.${project.findProperty("archivesBaseName")}" + attributes["Build-Version"] = gitVersion.get() + attributes["Bundle-Name"] = base.archivesName.get() + } + } + } +} + +signing { + if (signingKey.isPresent && signingPassword.isPresent) { + logger.debug("[${project.displayName}] Signing is enabled") + useInMemoryPgpKeys(signingKey.get(), signingPassword.get()) + } +} + +tasks.named("clean") { delete.add(localBuildRepo) } + +tasks.withType { enabled = false } + +tasks.register("publishSnapshots") { + group = "publishing" + description = "Publishes snapshots to Sonatype" + + if (version.toString().endsWith("-SNAPSHOT")) { + dependsOn(tasks.withType()) + } +} + +tasks.register("publishArchives") { + group = "publishing" + description = "Publishes a release and uploads to Sonatype / Maven Central" + + val currentGitVersion = gitVersion.get() + val gitVersionMatch = currentGitVersion == version + doFirst { + if (!gitVersionMatch) { + val cause = + """ + Version mismatch: + ================= + + $version != $currentGitVersion + + The project version does not match the git tag. + """.trimMargin() + throw GradleException(cause) + } else { + println("Publishing: ${project.name} : $currentGitVersion") + } + } + if (gitVersionMatch) { + dependsOn(tasks.withType()) + } +} + +// workaround for https://github.com/gradle/gradle/issues/16543 +inline fun TaskContainer.provider(taskName: String): Provider = + providers.provider { taskName }.flatMap { named(it) } diff --git a/buildSrc/src/main/kotlin/conventions/scaladoc.gradle.kts b/buildSrc/src/main/kotlin/conventions/scaladoc.gradle.kts new file mode 100644 index 00000000000..b14d9573e72 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/scaladoc.gradle.kts @@ -0,0 +1,34 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Provides the scaladoc configuration for the build +plugins { + id("scala") + id("conventions.publishing") +} + +// Create a generic `docs` task +tasks.register("docs") { + group = "documentation" + dependsOn("scaladoc") +} + +tasks.withType { + group = "documentation" + + destinationDir = rootProject.file("build/docs/${project.base.archivesName.get()}") +} diff --git a/buildSrc/src/main/kotlin/conventions/spotbugs.gradle.kts b/buildSrc/src/main/kotlin/conventions/spotbugs.gradle.kts new file mode 100644 index 00000000000..d675fd27139 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/spotbugs.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import com.github.spotbugs.snom.SpotBugsTask +import org.gradle.kotlin.dsl.dependencies +import project.libs + +// Performs quality checks on your project's Java source files using SpotBug +// https://plugins.gradle.org/plugin/com.github.spotbugs +plugins { + id("java-library") + id("com.github.spotbugs") +} + +dependencies { + compileOnly(libs.findbugs.jsr) + + testImplementation(libs.findbugs.jsr) +} + +spotbugs { + if (!project.buildingWith("ssdlcReport.enabled")) { + excludeFilter.set(rootProject.file("config/spotbugs/exclude.xml")) + } +} + +tasks.withType().configureEach { + if (name == "spotbugsMain") { + reports { + register("xml") { required.set(project.buildingWith("xmlReports.enabled")) } + register("html") { required.set(!project.buildingWith("xmlReports.enabled")) } + register("sarif") { required.set(project.buildingWith("ssdlcReport.enabled")) } + } + } else if (name == "spotbugsTest") { + enabled = false + } else if (name == "spotbugsIntegrationTest") { + enabled = false + } +} diff --git a/buildSrc/src/main/kotlin/conventions/spotless.gradle.kts b/buildSrc/src/main/kotlin/conventions/spotless.gradle.kts new file mode 100644 index 00000000000..f4175ec0c6a --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/spotless.gradle.kts @@ -0,0 +1,69 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import com.diffplug.gradle.spotless.SpotlessApply +import com.diffplug.gradle.spotless.SpotlessCheck + +// Spotless - keep your code spotless +// https://plugins.gradle.org/plugin/com.diffplug.spotless +plugins { id("com.diffplug.spotless") } + +val doesNotHaveACustomLicenseHeader = "/^(?s)(?!.*@custom-license-header).*/" + +spotless { + kotlinGradle { + ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") + } + + scala { + target("**/*.scala") + scalafmt().configFile(rootProject.file("config/scala/scalafmt.conf")) + } + + kotlin { + target("**/*.kt") + ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + licenseHeaderFile(rootProject.file("config/mongodb.license")) + .named("standard") + .onlyIfContentMatches(doesNotHaveACustomLicenseHeader) + } + + format("extraneous") { + target("*.xml", "*.yml", "*.md") + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + } +} + +tasks.named("check") { dependsOn("spotlessApply") } + +tasks { + withType().configureEach { + notCompatibleWithConfigurationCache("https://github.com/diffplug/spotless/issues/644") + } + withType().configureEach { + notCompatibleWithConfigurationCache("https://github.com/diffplug/spotless/issues/644") + } +} diff --git a/buildSrc/src/main/kotlin/conventions/test-artifacts.gradle.kts b/buildSrc/src/main/kotlin/conventions/test-artifacts.gradle.kts new file mode 100644 index 00000000000..f82a88c7df9 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/test-artifacts.gradle.kts @@ -0,0 +1,43 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import project.DEFAULT_JAVA_VERSION + +// Allows test artifacts (resources and code) to be shared between projects +plugins { id("java-library") } + +/** Create a test artifact configuration so that test resources can be consumed by other projects. */ +val testArtifacts by configurations.creating +val testJar by + tasks.registering(Jar::class) { + archiveBaseName.set("${project.name}-test") + from(sourceSets.test.get().output) + setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE) + } + +val testJavaVersion: Int = findProperty("javaVersion")?.toString()?.toInt() ?: DEFAULT_JAVA_VERSION + +tasks.withType() { + mustRunAfter(testJar) + + // Needed for OidcAuthenticationProseTests calls `field.setAccessible(true)` + if (testJavaVersion >= DEFAULT_JAVA_VERSION) { + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + } +} + +artifacts { add("testArtifacts", testJar) } diff --git a/driver-legacy/build.gradle b/buildSrc/src/main/kotlin/conventions/test-include-optionals.gradle.kts similarity index 50% rename from driver-legacy/build.gradle rename to buildSrc/src/main/kotlin/conventions/test-include-optionals.gradle.kts index 7266e724f7d..e7fde0b4c0f 100644 --- a/driver-legacy/build.gradle +++ b/buildSrc/src/main/kotlin/conventions/test-include-optionals.gradle.kts @@ -13,30 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package conventions +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.project -archivesBaseName = 'mongodb-driver-legacy' -description = 'The MongoDB Legacy Driver' -ext { - pomName = 'The Legacy MongoDB Driver' -} - -sourceSets { - test.groovy.srcDirs += ['src/examples'] -} +// Adds common optional dependencies to the testImplementations +dependencies { -test { - exclude 'tour/**' -} + // Encryption testing + "testImplementation"(project(path = ":mongodb-crypt", configuration = "default")) -dependencies { - api project(':bson') - api project(':driver-core') - api project(':driver-sync') + // Netty stream type testing + "testImplementation"(platform(libs.netty.bom)) + "testImplementation"(libs.bundles.netty) - testImplementation project(':bson').sourceSets.test.output - testImplementation project(':driver-core').sourceSets.test.output - testImplementation project(':driver-sync').sourceSets.test.output + // Snappy / zstd testing + "testImplementation"(libs.snappy.java) + "testImplementation"(libs.zstd.jni) - testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') + // Socket testing + "testImplementation"(libs.jnr.unixsocket) } diff --git a/buildSrc/src/main/kotlin/conventions/testing-base.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-base.gradle.kts new file mode 100644 index 00000000000..8aa6d25a5fd --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-base.gradle.kts @@ -0,0 +1,107 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import com.adarshr.gradle.testlogger.theme.ThemeType +import project.DEFAULT_JAVA_VERSION + +// Default test configuration for projects +// +// Utilizes the test-logger plugin: +// https://plugins.gradle.org/plugin/com.adarshr.test-logger +plugins { + id("java-library") + id("com.adarshr.test-logger") +} + +tasks.withType { + maxHeapSize = "4g" + maxParallelForks = 1 + + useJUnitPlatform() + + // Pass any `org.mongodb.*` system settings + systemProperties = + System.getProperties() + .map { (key, value) -> Pair(key.toString(), value) } + .filter { it.first.startsWith("org.mongodb.") } + .toMap() + + // Convert any ssl based properties + if (project.buildingWith("ssl.enabled")) { + if (project.hasProperty("ssl.keyStoreType")) { + systemProperties( + mapOf( + "javax.net.ssl.keyStoreType" to project.property("ssl.keyStoreType"), + "javax.net.ssl.keyStore" to project.property("ssl.keyStore"), + "javax.net.ssl.keyStorePassword" to project.property("ssl.keyStorePassword"))) + } + if (project.hasProperty("ssl.trustStoreType")) { + systemProperties( + mapOf( + "javax.net.ssl.trustStoreType" to project.property("ssl.trustStoreType"), + "javax.net.ssl.trustStore" to project.property("ssl.trustStore"), + "javax.net.ssl.trustStorePassword" to project.property("ssl.trustStorePassword"))) + } + if (project.hasProperty("ocsp.property")) { + systemProperties( + mapOf( + "org.mongodb.test.ocsp.tls.should.succeed" to project.property("ocsp.tls.should.succeed"), + "java.security.properties" to file(project.property("ocsp.property").toString()), + "com.sun.net.ssl.checkRevocation" to project.property("ssl.checkRevocation"), + "jdk.tls.client.enableStatusRequestExtension" to + project.property("client.enableStatusRequestExtension"), + "jdk.tls.client.protocols" to project.property("client.protocols"))) + } + } + + // Convert gssapi properties + if (project.buildingWith("gssapi.enabled")) { + systemProperties( + mapOf( + "sun.security.krb5.debug" to project.property("sun.security.krb5.debug"), + "javax.security.auth.useSubjectCredsOnly" to "false", + "java.security.krb5.kdc" to project.property("krb5.kdc"), + "java.security.krb5.realm" to project.property("krb5.realm"), + "java.security.auth.login.config" to project.property("auth.login.config"), + )) + } + + // Allow testing with an alternative JDK version + val testJavaVersion: Int = findProperty("javaVersion")?.toString()?.toInt() ?: DEFAULT_JAVA_VERSION + javaLauncher.set(javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(testJavaVersion) }) +} + +// Pretty test output +testlogger { + theme = ThemeType.STANDARD + showExceptions = true + showStackTraces = true + showFullStackTraces = false + showCauses = true + slowThreshold = 2000 + showSummary = true + showSimpleNames = false + showPassed = true + showSkipped = true + showFailed = true + showOnlySlow = false + showStandardStreams = false + showPassedStandardStreams = true + showSkippedStandardStreams = true + showFailedStandardStreams = true + logLevel = LogLevel.LIFECYCLE +} diff --git a/buildSrc/src/main/kotlin/conventions/testing-integration.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-integration.gradle.kts new file mode 100644 index 00000000000..bdd30028b18 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-integration.gradle.kts @@ -0,0 +1,50 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Adds separate `integrationTest` configuration to a project +// Allows unit and integrations tests to be separate tasks +// +// See: +// https://docs.gradle.org/current/samples/sample_jvm_multi_project_with_additional_test_types.html +plugins { id("java-library") } + +val integrationTest by sourceSets.creating + +configurations[integrationTest.implementationConfigurationName].extendsFrom(configurations.testImplementation.get()) + +configurations[integrationTest.runtimeOnlyConfigurationName].extendsFrom(configurations.testRuntimeOnly.get()) + +val integrationTestTask = + tasks.register("integrationTest") { + description = "Runs integration tests." + group = "verification" + useJUnitPlatform() + + testClassesDirs = integrationTest.output.classesDirs + classpath = configurations[integrationTest.runtimeClasspathConfigurationName] + integrationTest.output + shouldRunAfter(tasks.test) + } + +tasks.findByName("check")?.dependsOn(integrationTestTask) + +dependencies { + "integrationTestImplementation"(project) + "integrationTestImplementation"(platform(libs.junit.bom)) + "integrationTestImplementation"(libs.bundles.junit.vintage) +} + +sourceSets["integrationTest"].java.srcDirs("src/integrationTest", "src/integrationTest/java") diff --git a/buildSrc/src/main/kotlin/conventions/testing-junit-vintage.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-junit-vintage.gradle.kts new file mode 100644 index 00000000000..48f6eee92eb --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-junit-vintage.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Default junit vintage (aka junit4) test configuration for projects +plugins { id("conventions.testing-base") } + +dependencies { + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.bundles.junit.vintage) +} + +sourceSets["test"].java { srcDirs("src/test", "src/test/unit", "src/test/functional") } diff --git a/buildSrc/src/main/kotlin/conventions/testing-junit.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-junit.gradle.kts new file mode 100644 index 00000000000..7e72c5101bf --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-junit.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +// Default junit test configuration for projects +plugins { id("conventions.testing-base") } + +dependencies { + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.bundles.junit) +} + +sourceSets["test"].java { srcDirs("src/test", "src/test/unit", "src/test/functional") } diff --git a/bson/build.gradle b/buildSrc/src/main/kotlin/conventions/testing-mockito.gradle.kts similarity index 67% rename from bson/build.gradle rename to buildSrc/src/main/kotlin/conventions/testing-mockito.gradle.kts index d2b2ed3ba0e..08c33262e9e 100644 --- a/bson/build.gradle +++ b/buildSrc/src/main/kotlin/conventions/testing-mockito.gradle.kts @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package conventions -archivesBaseName = 'bson' -description = 'The BSON library' +// Adds mockito support to a project +plugins { id("java-library") } -ext { - pomName = 'BSON' - pomURL = 'https://bsonspec.org' -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.bson' - jar.manifest.attributes['Import-Package'] = 'org.slf4j.*;resolution:=optional' +dependencies { + if (project.findProperty("javaVersion")?.toString().equals("8")) { + testImplementation(libs.bundles.mockito.java8) + } else { + testImplementation(libs.bundles.mockito) + } } diff --git a/buildSrc/src/main/kotlin/conventions/testing-spock-exclude-slow.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-spock-exclude-slow.gradle.kts new file mode 100644 index 00000000000..706bca27e8c --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-spock-exclude-slow.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import org.gradle.api.tasks.testing.Test +import org.gradle.kotlin.dsl.withType + +// Adds groovy spock testing framework support +// See: https://spockframework.org/ +plugins { id("conventions.testing-spock") } + +tasks.withType().configureEach { + exclude("examples/**") + useJUnitPlatform { excludeTags("Slow") } + + systemProperty("spock.configuration", "${rootProject.file("config/spock/ExcludeSlow.groovy")}") +} + +tasks.register("testSlowOnly", Test::class.java) { + useJUnitPlatform { includeTags("Slow") } + + systemProperty("spock.configuration", "${rootProject.file("config/spock/OnlySlow.groovy")}") +} diff --git a/buildSrc/src/main/kotlin/conventions/testing-spock.gradle.kts b/buildSrc/src/main/kotlin/conventions/testing-spock.gradle.kts new file mode 100644 index 00000000000..e4d46007856 --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/testing-spock.gradle.kts @@ -0,0 +1,42 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +import org.gradle.kotlin.dsl.dependencies +import project.libs + +// Adds groovy spock testing framework support +// See: https://spockframework.org/ +plugins { + id("groovy") + id("conventions.codenarc") + id("conventions.testing-base") + id("conventions.testing-junit-vintage") +} + +dependencies { + testImplementation(platform(libs.spock.bom)) + testImplementation(libs.bundles.spock) +} + +sourceSets { + test { + groovy { srcDirs("src/test", "src/test/unit", "src/test/functional", "src/examples") } + + // Disable java src directories - groovy will compile the mixed java and groovy test code + java { setSrcDirs(emptyList()) } + } +} diff --git a/buildSrc/src/main/kotlin/project/Companion.kt b/buildSrc/src/main/kotlin/project/Companion.kt new file mode 100644 index 00000000000..b4b9650031a --- /dev/null +++ b/buildSrc/src/main/kotlin/project/Companion.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 project + +import org.gradle.accessors.dm.LibrariesForLibs +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +// Adds the `libs` value for use in project +internal val Project.libs: LibrariesForLibs + get() = extensions.getByType() + +internal const val DEFAULT_JAVA_VERSION = 17 diff --git a/util/taglets/build.gradle b/buildSrc/src/main/kotlin/project/base.gradle.kts similarity index 80% rename from util/taglets/build.gradle rename to buildSrc/src/main/kotlin/project/base.gradle.kts index 4498034e07a..ed13c40cb76 100644 --- a/util/taglets/build.gradle +++ b/buildSrc/src/main/kotlin/project/base.gradle.kts @@ -13,4 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package project +plugins { id("conventions.git-version") } + +group = "org.mongodb" + +repositories { + mavenLocal() + google() + mavenCentral() +} diff --git a/buildSrc/src/main/kotlin/project/java.gradle.kts b/buildSrc/src/main/kotlin/project/java.gradle.kts new file mode 100644 index 00000000000..60861167f17 --- /dev/null +++ b/buildSrc/src/main/kotlin/project/java.gradle.kts @@ -0,0 +1,50 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 project + +plugins { + id("java-library") + id("checkstyle") + id("project.base") + id("conventions.bnd") + id("conventions.javadoc") + id("conventions.optional") + id("conventions.publishing") + id("conventions.spotbugs") + id("conventions.spotless") + id("conventions.testing-junit") +} + +dependencies { "optionalApi"(libs.slf4j) } + +logger.info("Compiling ${project.name} using JDK${DEFAULT_JAVA_VERSION}") + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + toolchain { languageVersion = JavaLanguageVersion.of(DEFAULT_JAVA_VERSION) } + + withSourcesJar() + withJavadocJar() +} + +tasks.withType { + options.encoding = "UTF-8" + options.release.set(8) +} + +sourceSets["main"].java { srcDir("src/main") } diff --git a/buildSrc/src/main/kotlin/project/kotlin.gradle.kts b/buildSrc/src/main/kotlin/project/kotlin.gradle.kts new file mode 100644 index 00000000000..f6bad54d696 --- /dev/null +++ b/buildSrc/src/main/kotlin/project/kotlin.gradle.kts @@ -0,0 +1,67 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 project + +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + +plugins { + kotlin("jvm") + id("project.base") + id("conventions.bnd") + id("conventions.detekt") + id("conventions.dokka") + id("conventions.optional") + id("conventions.publishing") + id("conventions.spotbugs") + id("conventions.spotless") + id("conventions.testing-integration") + id("conventions.testing-junit") +} + +/* Compiling */ +logger.info("Compiling ${project.name} using JDK${DEFAULT_JAVA_VERSION}") + +kotlin { + explicitApi() + jvmToolchain(DEFAULT_JAVA_VERSION) +} + +tasks.withType { compilerOptions { jvmTarget = JvmTarget.JVM_1_8 } } + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + withSourcesJar() + withJavadocJar() +} + +dependencies { + "optionalApi"(libs.slf4j) + + // Align versions of all Kotlin components + implementation(platform(libs.kotlin.bom)) + implementation(libs.kotlin.stdlib.jdk8) + + testImplementation(libs.kotlin.reflect) + testImplementation(libs.junit.kotlin) + testImplementation(libs.bundles.mockito.kotlin) + testImplementation(libs.assertj) + testImplementation(libs.classgraph) + + "integrationTestImplementation"(libs.junit.kotlin) +} diff --git a/buildSrc/src/main/kotlin/project/scala.gradle.kts b/buildSrc/src/main/kotlin/project/scala.gradle.kts new file mode 100644 index 00000000000..9e3d36b957b --- /dev/null +++ b/buildSrc/src/main/kotlin/project/scala.gradle.kts @@ -0,0 +1,105 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 project + +import ProjectExtensions.configureMavenPublication +import ProjectExtensions.scalaVersion + +plugins { + id("scala") + id("project.base") + id("conventions.bnd") + id("conventions.optional") + id("conventions.publishing") + id("conventions.scaladoc") + id("conventions.spotless") + id("conventions.testing-junit") + id("conventions.testing-integration") +} + +group = "org.mongodb.scala" + +val scalaVersion: String by lazy { project.scalaVersion() } + +sourceSets["integrationTest"].scala.srcDir("src/integrationTest/scala") + +tasks.register("scalaCheck") { + description = "Runs all the Scala checks" + group = "verification" + + dependsOn("clean", "compileTestScala", "check") + tasks.findByName("check")?.mustRunAfter("clean") +} + +tasks.withType { + doFirst { println("Running Test task using scala version: $scalaVersion") } + useJUnitPlatform() +} + +tasks.named("clean") { delete.add(rootProject.file("build/docs/")) } + +afterEvaluate { + configureMavenPublication { artifactId = "${base.archivesName.get()}_${scalaVersion}" } + + // ============================================ + // Scala version specific configuration + // ============================================ + val compileOptions = mutableListOf("-target:jvm-1.8") + when (scalaVersion) { + "2.13" -> { + dependencies { + api(libs.bundles.scala.v2.v13) + + testImplementation(libs.bundles.scala.test.v2.v13) + } + sourceSets { main { scala { setSrcDirs(listOf("src/main/scala", "src/main/scala-2.13+")) } } } + + compileOptions.addAll( + listOf( + "-feature", + "-unchecked", + "-language:reflectiveCalls", + "-Wconf:cat=deprecation:ws", + "-Xlint:strict-unsealed-patmat")) + } + "2.12" -> { + dependencies { + api(libs.bundles.scala.v2.v12) + + testImplementation(libs.bundles.scala.test.v2.v12) + } + sourceSets { main { scala { setSrcDirs(listOf("src/main/scala", "src/main/scala-2.13-")) } } } + } + "2.11" -> { + dependencies { + api(libs.bundles.scala.v2.v11) + + testImplementation(libs.bundles.scala.test.v2.v11) + } + // Reuse the scala-2.12 source as its compatible. + sourceSets { main { scala { setSrcDirs(listOf("src/main/scala", "src/main/scala-2.13-")) } } } + + compileOptions.add("-Xexperimental") + } + } + + tasks.withType { + doFirst { println("Compiling using scala version: $scalaVersion") } + + scalaCompileOptions.isDeprecation = false + scalaCompileOptions.additionalParameters = compileOptions + } +} diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index 718bfeabbf1..d462c314e9c 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -2,22 +2,35 @@ + EmptyDefaultConstructor:UnifiedCrudTest.kt$UnifiedCrudTest$() + EmptyDefaultConstructor:UnifiedTest.kt$UnifiedTest$() + EmptyFunctionBlock:SyncMongoCursor.kt$SyncMongoCursor${} IteratorNotThrowingNoSuchElementException:MongoCursor.kt$MongoCursor<T : Any> : IteratorCloseable LargeClass:MongoCollectionTest.kt$MongoCollectionTest LongMethod:FindFlowTest.kt$FindFlowTest$@Test fun shouldCallTheUnderlyingMethods() LongMethod:FindIterableTest.kt$FindIterableTest$@Test fun shouldCallTheUnderlyingMethods() LongMethod:KotlinSerializerCodecTest.kt$KotlinSerializerCodecTest$@Test fun testDataClassOptionalBsonValues() - MaxLineLength:MapReduceFlow.kt$MapReduceFlow$* - MaxLineLength:MapReduceIterable.kt$MapReduceIterable$* + MaxLineLength:ListCollectionNamesFlow.kt$ListCollectionNamesFlow$* + MaxLineLength:ListCollectionNamesIterable.kt$ListCollectionNamesIterable$* MaxLineLength:ListCollectionsFlow.kt$ListCollectionsFlow$* MaxLineLength:ListCollectionsIterable.kt$ListCollectionsIterable$* - MaxLineLength:ListCollectionNamesIterable.kt$ListCollectionNamesIterable$* - MaxLineLength:ListCollectionNamesFlow.kt$ListCollectionNamesFlow$* + MaxLineLength:MapReduceFlow.kt$MapReduceFlow$* + MaxLineLength:MapReduceIterable.kt$MapReduceIterable$* SwallowedException:MockitoHelper.kt$MockitoHelper.DeepReflectionEqMatcher$e: Throwable TooManyFunctions:ClientSession.kt$ClientSession : jClientSession TooManyFunctions:FindFlow.kt$FindFlow<T : Any> : Flow TooManyFunctions:FindIterable.kt$FindIterable<T : Any> : MongoIterable TooManyFunctions:MongoCollection.kt$MongoCollection<T : Any> TooManyFunctions:MongoDatabase.kt$MongoDatabase + TooManyFunctions:SyncClientSession.kt$SyncClientSession : JClientSession + TooManyFunctions:SyncFindIterable.kt$SyncFindIterable<T : Any> : JFindIterableSyncMongoIterable + TooManyFunctions:SyncMongoCluster.kt$SyncMongoCluster : JMongoCluster + TooManyFunctions:SyncMongoCollection.kt$SyncMongoCollection<T : Any> : JMongoCollection + TooManyFunctions:SyncMongoDatabase.kt$SyncMongoDatabase : JMongoDatabase + UnnecessaryAbstractClass:UnifiedTest.kt$UnifiedTest$UnifiedTest + UnsafeCallOnNullableType:SmokeTests.kt$SmokeTests$collection!! + UnusedPrivateMember:SyncMongoIterable.kt$SyncMongoIterable$private var timeoutMode: TimeoutMode? = null + VarCouldBeVal:SyncMongoIterable.kt$SyncMongoIterable$private var timeoutMode: TimeoutMode? = null + WildcardImport:SyncMongoDatabase.kt$import com.mongodb.client.* diff --git a/config/spock/ExcludeSlow.groovy b/config/spock/ExcludeSlow.groovy index db9671d4261..033fbdb2a7d 100644 --- a/config/spock/ExcludeSlow.groovy +++ b/config/spock/ExcludeSlow.groovy @@ -2,5 +2,5 @@ package spock runner { println "Excluding Slow Spock tests" - exclude util.spock.annotations.Slow + exclude com.mongodb.spock.Slow } diff --git a/config/spock/OnlySlow.groovy b/config/spock/OnlySlow.groovy index f333feaa94b..d98c04bd826 100644 --- a/config/spock/OnlySlow.groovy +++ b/config/spock/OnlySlow.groovy @@ -2,5 +2,5 @@ package spock runner { println "Only including Slow Spock tests" - include util.spock.annotations.Slow + include com.mongodb.spock.Slow } diff --git a/driver-benchmarks/build.gradle b/driver-benchmarks/build.gradle.kts similarity index 50% rename from driver-benchmarks/build.gradle rename to driver-benchmarks/build.gradle.kts index 644fe2ed435..eac033920e3 100644 --- a/driver-benchmarks/build.gradle +++ b/driver-benchmarks/build.gradle.kts @@ -14,41 +14,41 @@ * limitations under the License. */ -apply plugin: 'application' +plugins { + id("application") + id("java-library") + id("project.base") +} -mainClassName = "com.mongodb.benchmark.benchmarks.BenchmarkSuite" +application { + mainClass = "com.mongodb.benchmark.benchmarks.BenchmarkSuite" + applicationDefaultJvmArgs = listOf( + "-Dorg.mongodb.benchmarks.data=${System.getProperty("org.mongodb.benchmarks.data")}", + "-Dorg.mongodb.benchmarks.output=${System.getProperty("org.mongodb.benchmarks.output")}") +} sourceSets { main { - java { - srcDir 'src/main' - } - resources { - srcDir 'src/resources' - } + java { setSrcDirs(listOf("src/main")) } + resources { setSrcDirs(listOf("src/resources")) } } } dependencies { - api project(':driver-sync') - api project(':mongodb-crypt') - + api(project(":driver-sync")) + api(project(":mongodb-crypt")) implementation(libs.logback.classic) implementation(libs.jmh.core) annotationProcessor(libs.jmh.generator.annprocess) } -tasks.register("jmh", JavaExec) { - group = 'benchmark' - description = 'Run JMH benchmarks.' - mainClass = 'org.openjdk.jmh.Main' - classpath = sourceSets.main.runtimeClasspath +tasks.register("jmh") { + group = "benchmark" + description = "Run JMH benchmarks." + mainClass = "org.openjdk.jmh.Main" + classpath = sourceSets.main.get().runtimeClasspath } -javadoc { +tasks.withType().configureEach { enabled = false } - -applicationDefaultJvmArgs = ["-Dorg.mongodb.benchmarks.data=" + System.getProperty('org.mongodb.benchmarks.data'), - "-Dorg.mongodb.benchmarks.output=" + System.getProperty('org.mongodb.benchmarks.output')] - diff --git a/driver-core/build.gradle b/driver-core/build.gradle deleted file mode 100644 index 900015bf79e..00000000000 --- a/driver-core/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - - -plugins { - alias(libs.plugins.build.config) -} - -archivesBaseName = 'mongodb-driver-core' -description = 'Shared components for the Synchronous and Reactive Streams implementations of the MongoDB Java Driver.' - -ext { - pomName = 'MongoDB Java Driver Core' -} - -configurations { - consumableTestRuntimeOnly { - extendsFrom testRuntimeOnly - canBeConsumed = true - } -} - -dependencies { - api project(path: ':bson', configuration: 'default') - implementation project(path: ':bson-record-codec', configuration: 'default') - implementation project(path: ':bson-kotlin', configuration: 'default'), optional - implementation project(path: ':bson-kotlinx', configuration: 'default'), optional - implementation project(path: ':mongodb-crypt', configuration: 'default'), optional - - implementation(libs.jnr.unixsocket, optional) - api(platform(libs.netty.bom), optional) - api(libs.bundles.netty, optional) - compileOnly(libs.graal.sdk) - - // Optionally depend on both AWS SDK v2 and v1. - // The driver will use v2 is present, v1 if present, or built-in functionality if neither are present - implementation(libs.bundles.aws.java.sdk.v1, optional) - implementation(libs.bundles.aws.java.sdk.v2, optional) - - implementation(libs.snappy.java, optional) - implementation(libs.zstd.jni, optional) - - testImplementation project(':bson').sourceSets.test.output - testImplementation(libs.bundles.junit) - testImplementation(libs.reflections) - - testRuntimeOnly(libs.netty.boringssl) - ["linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64"].each { arch -> - testRuntimeOnly(variantOf(libs.netty.boringssl) { classifier(arch) }) - } -} - -buildConfig { - className('MongoDriverVersion') - packageName('com.mongodb.internal.build') - useJavaOutput() - buildConfigField('String', 'NAME', '"mongo-java-driver"') - buildConfigField('String', 'VERSION', "\"${gitVersion}\"") -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.driver.core' - jar.manifest.attributes['Bundle-SymbolicName'] = 'org.mongodb.driver-core' - jar.manifest.attributes['Import-Package'] = [ - '!sun.misc.*', // Used by DirectBufferDeallocator only for java 8 - '!sun.nio.ch.*', // Used by DirectBufferDeallocator only for java 8 - '!javax.annotation.*', // Brought in by com.google.code.findbugs:annotations - '!com.oracle.svm.core.annotate.*', // this dependency is provided by the GraalVM runtime - 'io.netty.*;resolution:=optional', - 'com.amazonaws.*;resolution:=optional', - 'software.amazon.awssdk.*;resolution:=optional', - 'org.xerial.snappy.*;resolution:=optional', - 'com.github.luben.zstd.*;resolution:=optional', - 'org.slf4j.*;resolution:=optional', - 'jnr.unixsocket.*;resolution:=optional', - 'com.mongodb.internal.crypt.capi.*;resolution:=optional', - 'jdk.net.*;resolution:=optional', // Used by SocketStreamHelper & depends on JDK version - 'org.bson.codecs.record.*;resolution:=optional', // Depends on JDK version - 'org.bson.codecs.kotlin.*;resolution:=optional', - 'org.bson.codecs.kotlinx.*;resolution:=optional', - '*' // import all that is not excluded or modified before - ].join(',') -} diff --git a/driver-core/build.gradle.kts b/driver-core/build.gradle.kts new file mode 100644 index 00000000000..4c1c63c53ea --- /dev/null +++ b/driver-core/build.gradle.kts @@ -0,0 +1,100 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.test-artifacts") + id("conventions.testing-mockito") + id("conventions.testing-junit") + id("conventions.testing-spock-exclude-slow") + alias(libs.plugins.build.config) +} + +base.archivesName.set("mongodb-driver-core") + +buildConfig { + className("MongoDriverVersion") + packageName("com.mongodb.internal.build") + useJavaOutput() + buildConfigField("String", "NAME", "\"mongo-java-driver\"") + buildConfigField("String", "VERSION", "\"${(project.findProperty("gitVersion") as Provider<*>?)?.get()}\"") +} + +dependencies { + api(project(path = ":bson", configuration = "default")) + implementation(project(path = ":bson-record-codec", configuration = "default")) + compileOnly(libs.graal.sdk) + + optionalImplementation(project(path = ":bson-kotlin", configuration = "default")) + optionalImplementation(project(path = ":bson-kotlinx", configuration = "default")) + optionalImplementation(project(path = ":mongodb-crypt", configuration = "default")) + optionalImplementation(libs.jnr.unixsocket) + optionalApi(platform(libs.netty.bom)) + optionalApi(libs.bundles.netty) + + // Optionally depend on both AWS SDK v2 and v1. + // The driver will choose: v2 or v1 or fallback to built-in functionality + optionalImplementation(libs.bundles.aws.java.sdk.v1) + optionalImplementation(libs.bundles.aws.java.sdk.v2) + + optionalImplementation(libs.snappy.java) + optionalImplementation(libs.zstd.jni) + + testImplementation(project(path = ":bson", configuration = "testArtifacts")) + testImplementation(libs.reflections) + testRuntimeOnly(libs.netty.tcnative.boringssl) + listOf("linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64").forEach { arch -> + testRuntimeOnly(variantOf(libs.netty.tcnative.boringssl) { classifier(arch) }) + } +} + +configureMavenPublication { + pom { + name.set("MongoDB Java Driver Core") + description.set( + "Shared components for the Synchronous and Reactive Streams implementations of the MongoDB Java Driver.") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.core" + attributes["Bundle-SymbolicName"] = "org.mongodb.driver-core" + attributes["Import-Package"] = + listOf( + "!sun.misc.*", // Used by DirectBufferDeallocator only for java 8 + "!sun.nio.ch.*", // Used by DirectBufferDeallocator only for java 8 + "!javax.annotation.*", // Brought in by com.google.code.findbugs:annotations + "!com.oracle.svm.core.annotate.*", // this dependency is provided by the GraalVM + // runtime + "io.netty.*;resolution:=optional", + "com.amazonaws.*;resolution:=optional", + "software.amazon.awssdk.*;resolution:=optional", + "org.xerial.snappy.*;resolution:=optional", + "com.github.luben.zstd.*;resolution:=optional", + "org.slf4j.*;resolution:=optional", + "jnr.unixsocket.*;resolution:=optional", + "com.mongodb.internal.crypt.capi.*;resolution:=optional", + "jdk.net.*;resolution:=optional", // Used by SocketStreamHelper & depends on JDK + // version + "org.bson.codecs.record.*;resolution:=optional", // Depends on JDK version + "org.bson.codecs.kotlin.*;resolution:=optional", + "org.bson.codecs.kotlinx.*;resolution:=optional", + "*" // import all that is not excluded or modified before + ) + .joinToString(",") +} diff --git a/driver-core/src/test/functional/com/mongodb/client/model/AggregatesFunctionalSpecification.groovy b/driver-core/src/test/functional/com/mongodb/client/model/AggregatesFunctionalSpecification.groovy index 82c63393e7e..388736a9a82 100644 --- a/driver-core/src/test/functional/com/mongodb/client/model/AggregatesFunctionalSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/client/model/AggregatesFunctionalSpecification.groovy @@ -1336,7 +1336,8 @@ class AggregatesFunctionalSpecification extends OperationFunctionalSpecification [1, 2, 3, 4, 1, 2, 3, 4, 4.1] 'num' | 'partitionId' | densify(field, partitionRangeWithStep(1), densifyOptions().partitionByFields([partitionByField])) | [1, 2, 3, 4.1] - 'date' | null | densify(field, rangeWithStep(Instant.EPOCH, Instant.ofEpochMilli(BigInteger.TWO.pow(32).longValueExact()) + 1, + 'date' | null | densify(field, rangeWithStep(Instant.EPOCH, Instant.ofEpochMilli(BigInteger.TWO.pow(32).longValueExact()) + .plusMillis(1), // there is a server bug that prevents using `step` larger than 2^31 - 1 in versions before 6.1 BigInteger.TWO.pow(31).longValueExact() - 1, MongoTimeUnit.MILLISECOND)) | [Instant.EPOCH, diff --git a/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy b/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy index 012ba23e339..e582e0fc398 100644 --- a/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy @@ -13,7 +13,7 @@ import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.socket.nio.NioSocketChannel import spock.lang.IgnoreIf import spock.lang.Specification -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy index 0ac6b8fd9df..85f23350984 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy @@ -9,7 +9,7 @@ import com.mongodb.connection.SslSettings import com.mongodb.spi.dns.InetAddressResolver import spock.lang.IgnoreIf import spock.lang.Specification -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.CountDownLatch diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy index 6efe88806e8..3589362b8ac 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy @@ -26,7 +26,7 @@ import com.mongodb.connection.ServerId import com.mongodb.connection.SocketSettings import com.mongodb.internal.connection.netty.NettyStreamFactory import spock.lang.IgnoreIf -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.TimeUnit diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy index 42886648a2c..0283ce44f7b 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy @@ -8,7 +8,7 @@ import com.mongodb.spi.dns.InetAddressResolver import spock.lang.Ignore import spock.lang.IgnoreIf import spock.lang.Specification -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import javax.net.SocketFactory import java.util.concurrent.TimeUnit diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CommandOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/CommandOperationSpecification.groovy index a9f74ca50b3..57aee534fd0 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/operation/CommandOperationSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CommandOperationSpecification.groovy @@ -23,7 +23,7 @@ import org.bson.BsonDocument import org.bson.BsonInt32 import org.bson.BsonString import org.bson.codecs.BsonDocumentCodec -import util.spock.annotations.Slow +import com.mongodb.spock.Slow class CommandOperationSpecification extends OperationFunctionalSpecification { diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/MixedBulkWriteOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/MixedBulkWriteOperationSpecification.groovy index 9363f6a1812..6bdedf2ff60 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/operation/MixedBulkWriteOperationSpecification.groovy +++ b/driver-core/src/test/functional/com/mongodb/internal/operation/MixedBulkWriteOperationSpecification.groovy @@ -46,7 +46,7 @@ import org.bson.codecs.BsonDocumentCodec import org.bson.codecs.DocumentCodec import org.bson.types.ObjectId import spock.lang.IgnoreIf -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import static com.mongodb.ClusterFixture.configureFailPoint import static com.mongodb.ClusterFixture.disableFailPoint diff --git a/driver-core/src/test/unit/com/mongodb/AuthConnectionStringTest.java b/driver-core/src/test/unit/com/mongodb/AuthConnectionStringTest.java index cab5b0e0365..8e8a78008e7 100644 --- a/driver-core/src/test/unit/com/mongodb/AuthConnectionStringTest.java +++ b/driver-core/src/test/unit/com/mongodb/AuthConnectionStringTest.java @@ -29,12 +29,7 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import static com.mongodb.AuthenticationMechanism.MONGODB_OIDC; import static com.mongodb.MongoCredential.OIDC_CALLBACK_KEY; @@ -61,16 +56,8 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/auth/legacy")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{file.getName(), test.asDocument().getString("description").getValue(), - test.asDocument().getString("uri").getValue(), test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/auth/legacy"); } private void testInvalidUris() { diff --git a/driver-core/src/test/unit/com/mongodb/ConnectionStringTest.java b/driver-core/src/test/unit/com/mongodb/ConnectionStringTest.java index 80cc9f65e83..312c3698d8b 100644 --- a/driver-core/src/test/unit/com/mongodb/ConnectionStringTest.java +++ b/driver-core/src/test/unit/com/mongodb/ConnectionStringTest.java @@ -17,17 +17,11 @@ package com.mongodb; import org.bson.BsonDocument; -import org.bson.BsonValue; import org.junit.Test; import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import static org.junit.Assume.assumeFalse; @@ -70,15 +64,7 @@ public void shouldPassAllOutcomes() { @Parameterized.Parameters(name = "{1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/connection-string")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{file.getName(), test.asDocument().getString("description").getValue(), - test.asDocument().getString("uri").getValue(), test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/connection-string"); } } diff --git a/driver-core/src/test/unit/com/mongodb/ReadConcernConnectionStringTest.java b/driver-core/src/test/unit/com/mongodb/ReadConcernConnectionStringTest.java index 7d228604460..f45a620bfdf 100644 --- a/driver-core/src/test/unit/com/mongodb/ReadConcernConnectionStringTest.java +++ b/driver-core/src/test/unit/com/mongodb/ReadConcernConnectionStringTest.java @@ -19,18 +19,12 @@ import junit.framework.TestCase; import org.bson.BsonBoolean; import org.bson.BsonDocument; -import org.bson.BsonValue; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; // See https://github.com/mongodb/specifications/tree/master/source/read-write-concern/tests/ @RunWith(Parameterized.class) @@ -39,7 +33,8 @@ public class ReadConcernConnectionStringTest extends TestCase { private final String input; private final BsonDocument definition; - public ReadConcernConnectionStringTest(final String description, final String input, final BsonDocument definition) { + public ReadConcernConnectionStringTest(@SuppressWarnings("unused") final String fileName, final String description, + final String input, final BsonDocument definition) { this.description = description; this.input = input; this.definition = definition; @@ -59,16 +54,7 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/read-concern/connection-string")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{test.asDocument().getString("description").getValue(), - test.asDocument().getString("uri").getValue(), - test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/read-concern/connection-string"); } } diff --git a/driver-core/src/test/unit/com/mongodb/ReadConcernDocumentTest.java b/driver-core/src/test/unit/com/mongodb/ReadConcernDocumentTest.java index 0555d368b91..9b49ec3a6d8 100644 --- a/driver-core/src/test/unit/com/mongodb/ReadConcernDocumentTest.java +++ b/driver-core/src/test/unit/com/mongodb/ReadConcernDocumentTest.java @@ -19,18 +19,12 @@ import junit.framework.TestCase; import org.bson.BsonBoolean; import org.bson.BsonDocument; -import org.bson.BsonValue; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; // See https://github.com/mongodb/specifications/tree/master/source/read-write-concern/tests/connection-string @RunWith(Parameterized.class) @@ -38,7 +32,8 @@ public class ReadConcernDocumentTest extends TestCase { private final String description; private final BsonDocument definition; - public ReadConcernDocumentTest(final String description, final BsonDocument definition) { + public ReadConcernDocumentTest(@SuppressWarnings("unused") final String fileName, final String description, + @SuppressWarnings("unused") final String uri, final BsonDocument definition) { this.description = description; this.definition = definition; } @@ -71,15 +66,7 @@ private ReadConcern getReadConcern(final BsonDocument readConcernDocument) { } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/read-concern/document")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{test.asDocument().getString("description").getValue(), - test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/read-concern/document"); } } diff --git a/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java b/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java index 3ca5ce0aa76..03915c27258 100644 --- a/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java +++ b/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java @@ -18,17 +18,11 @@ import org.bson.BsonBoolean; import org.bson.BsonDocument; -import org.bson.BsonValue; import org.junit.Test; import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import static org.junit.Assume.assumeFalse; @@ -54,15 +48,7 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/uri-options")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{file.getName(), test.asDocument().getString("description").getValue(), - test.asDocument().getString("uri").getValue(), test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/uri-options"); } } diff --git a/driver-core/src/test/unit/com/mongodb/WriteConcernConnectionStringTest.java b/driver-core/src/test/unit/com/mongodb/WriteConcernConnectionStringTest.java index ec5815abfc9..1ddfd4cbb2b 100644 --- a/driver-core/src/test/unit/com/mongodb/WriteConcernConnectionStringTest.java +++ b/driver-core/src/test/unit/com/mongodb/WriteConcernConnectionStringTest.java @@ -28,12 +28,7 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.concurrent.TimeUnit; // See https://github.com/mongodb/specifications/tree/master/source/read-write-concern/tests/connection-string @@ -43,7 +38,8 @@ public class WriteConcernConnectionStringTest extends TestCase { private final String input; private final BsonDocument definition; - public WriteConcernConnectionStringTest(final String description, final String input, final BsonDocument definition) { + public WriteConcernConnectionStringTest(@SuppressWarnings("unused") final String fileName, final String description, + final String input, final BsonDocument definition) { this.description = description; this.input = input; this.definition = definition; @@ -89,16 +85,7 @@ private WriteConcern getExpectedWriteConcern() { } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/write-concern/connection-string")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{test.asDocument().getString("description").getValue(), - test.asDocument().getString("uri").getValue(), - test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/write-concern/connection-string"); } } diff --git a/driver-core/src/test/unit/com/mongodb/WriteConcernDocumentTest.java b/driver-core/src/test/unit/com/mongodb/WriteConcernDocumentTest.java index 1c828a42f15..e4a9b579268 100644 --- a/driver-core/src/test/unit/com/mongodb/WriteConcernDocumentTest.java +++ b/driver-core/src/test/unit/com/mongodb/WriteConcernDocumentTest.java @@ -28,12 +28,7 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.concurrent.TimeUnit; // See https://github.com/mongodb/specifications/tree/master/source/read-write-concern/tests/connection-string @@ -43,9 +38,10 @@ public class WriteConcernDocumentTest extends TestCase { private final BsonDocument writeConcernDocument; private final BsonDocument definition; - public WriteConcernDocumentTest(final String description, final BsonDocument writeConcernDocument, final BsonDocument definition) { + public WriteConcernDocumentTest(@SuppressWarnings("unused") final String fileName, final String description, + @SuppressWarnings("unused") final String uri, final BsonDocument definition) { this.description = description; - this.writeConcernDocument = writeConcernDocument; + this.writeConcernDocument = definition.getDocument("writeConcern"); this.definition = definition; } @@ -86,16 +82,7 @@ private WriteConcern getWriteConcern(final BsonDocument writeConcernDocument) { } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { - List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/write-concern/document")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - for (BsonValue test : testDocument.getArray("tests")) { - data.add(new Object[]{test.asDocument().getString("description").getValue(), - test.asDocument().getDocument("writeConcern"), - test.asDocument()}); - } - } - return data; + public static Collection data() { + return JsonPoweredTestHelper.getTestData("/write-concern/document"); } } diff --git a/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java b/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java index 9e1326f6d54..65d26722bf2 100644 --- a/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java +++ b/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java @@ -39,9 +39,6 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -75,7 +72,7 @@ public ServerSelectionSelectionTest(final String description, final BsonDocument @Test public void shouldPassAllOutcomes() { // skip this test because the driver prohibits maxStaleness or tagSets with mode of primary at a much lower level - assumeTrue(!description.equals("max-staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.json")); + assumeTrue(!description.equals("/max-staleness/server_selection/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.json")); ServerSelector serverSelector = null; List suitableServers = buildServerDescriptions(definition.getArray("suitable_servers", new BsonArray())); @@ -102,26 +99,17 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{0}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/server-selection/server_selection")) { - data.add(new Object[]{getServerSelectionTestDescription(file), JsonPoweredTestHelper.getTestDocument(file)}); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/server-selection/server_selection")) { + data.add(new Object[]{testDocument.getString("resourcePath").getValue(), testDocument}); } - for (File file : JsonPoweredTestHelper.getTestFiles("/max-staleness/server_selection")) { - data.add(new Object[]{getMaxStalenessTestDescription(file), JsonPoweredTestHelper.getTestDocument(file)}); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/max-staleness/server_selection")) { + data.add(new Object[]{testDocument.getString("resourcePath").getValue(), testDocument}); } return data; } - private static String getServerSelectionTestDescription(final File file) { - return "server-selection" + "/" + file.getParentFile().getParentFile().getName() + "/" + file.getParentFile().getName() + "/" - + file.getName(); - } - - private static String getMaxStalenessTestDescription(final File file) { - return "max-staleness" + "/" + file.getParentFile().getName() + "/" + file.getName(); - } - public static ClusterDescription buildClusterDescription(final BsonDocument topologyDescription, @Nullable final ServerSettings serverSettings) { ClusterType clusterType = getClusterType(topologyDescription.getString("type").getValue()); diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java index 5b2cb1ab5f6..6a54fcce406 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java @@ -60,9 +60,6 @@ import org.mockito.Mockito; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -85,8 +82,8 @@ import static com.mongodb.assertions.Assertions.assertFalse; import static com.mongodb.internal.thread.InterruptionUtil.interruptAndCreateMongoInterruptedException; import static java.lang.String.format; -import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.Arrays.asList; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -566,16 +563,12 @@ protected ConnectionPool getPool() { } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/connection-monitoring-and-pooling/cmap-format")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - data.add(new Object[]{ - file.getName(), + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/connection-monitoring-and-pooling/cmap-format")) { + data.add(new Object[]{testDocument.getString("fileName").getValue(), testDocument.getString("description").getValue(), - testDocument, - JsonTestServerVersionChecker.skipTest(testDocument, BsonDocument.parse("{}")) - }); + testDocument, JsonTestServerVersionChecker.skipTest(testDocument, BsonDocument.parse("{}"))}); } return data; } diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java index 6fe76d0198a..50c78c0ffae 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java @@ -35,9 +35,7 @@ import org.bson.BsonInt32; import util.JsonPoweredTestHelper; -import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -60,11 +58,11 @@ public AbstractServerDiscoveryAndMonitoringTest(final BsonDocument definition) { this.definition = definition; } - public static Collection data(final String root) throws URISyntaxException, IOException { + public static Collection data(final String resourcePath) { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles(root)) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); - data.add(new Object[]{file.getName() + ": " + testDocument.getString("description").getValue(), testDocument}); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments(resourcePath)) { + data.add(new Object[]{testDocument.getString("fileName").getValue() + + ": " + testDocument.getString("description").getValue(), testDocument}); } return data; } diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy index 50f78639168..a509779d09f 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy @@ -37,7 +37,7 @@ import com.mongodb.internal.selector.ServerAddressSelector import com.mongodb.internal.selector.WritableServerSelector import com.mongodb.internal.time.Timeout import spock.lang.Specification -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.CountDownLatch diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy index fe251d34311..b3e78d2dc54 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy @@ -34,7 +34,7 @@ import com.mongodb.logging.TestLoggingInterceptor import org.bson.types.ObjectId import spock.lang.Specification import spock.lang.Subject -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.CompletableFuture import java.util.concurrent.CountDownLatch diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringMonitoringTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringMonitoringTest.java index c542fb29b1f..1aac97daaa9 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringMonitoringTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringMonitoringTest.java @@ -34,8 +34,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -78,7 +76,7 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{0}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { return data("/server-discovery-and-monitoring-monitoring"); } diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java index 4a2e94c19a5..701e28d3664 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java @@ -27,8 +27,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; import static com.mongodb.ClusterFixture.OPERATION_CONTEXT; @@ -78,7 +76,7 @@ private void assertTopology(final BsonDocument outcome) { } @Parameterized.Parameters(name = "{0}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { return data("/server-discovery-and-monitoring"); } diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionRttTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionRttTest.java index 9a7a8492563..11d91cfb327 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionRttTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionRttTest.java @@ -23,9 +23,6 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -57,10 +54,10 @@ public void shouldPassAllOutcomes() { } @Parameterized.Parameters(name = "{0}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/server-selection/rtt")) { - data.add(new Object[]{file.getName(), JsonPoweredTestHelper.getTestDocument(file)}); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/server-selection/rtt")) { + data.add(new Object[]{testDocument.getString("fileName").getValue(), testDocument}); } return data; } diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java index 878876d74bd..31086a699b9 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java @@ -31,10 +31,11 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.Mockito; +import util.JsonPoweredTestHelper; import java.math.BigDecimal; import java.math.RoundingMode; -import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -44,12 +45,9 @@ import static com.mongodb.ClusterFixture.createOperationContext; import static com.mongodb.connection.ServerSelectionSelectionTest.buildClusterDescription; import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; -import static util.JsonPoweredTestHelper.testDir; -import static util.JsonPoweredTestHelper.testDocs; /** * A runner for @@ -64,7 +62,7 @@ public class ServerSelectionWithinLatencyWindowTest { private final Outcome outcome; public ServerSelectionWithinLatencyWindowTest( - @SuppressWarnings("unused") final Path fileName, + @SuppressWarnings("unused") final String fileName, @SuppressWarnings("unused") final String description, final BsonDocument definition) { clusterDescription = buildClusterDescription(definition.getDocument("topology_description"), null); @@ -93,14 +91,13 @@ public void shouldPassAllOutcomes() { @Parameterized.Parameters(name = "{0}: {1}") public static Collection data() { - return testDocs(testDir("/server-selection/in_window")) - .entrySet() - .stream() - .map(entry -> new Object[] { - entry.getKey().getFileName(), - entry.getValue().getString("description").getValue(), - entry.getValue()}) - .collect(toList()); + List data = new ArrayList<>(); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/server-selection/in_window")) { + data.add(new Object[]{testDocument.getString("fileName").getValue(), + testDocument.getString("description").getValue(), + testDocument}); + } + return data; } private static Cluster.ServersSnapshot serverCatalog(final BsonArray mockedTopologyState) { diff --git a/driver-core/src/test/unit/com/mongodb/spock/Slow.java b/driver-core/src/test/unit/com/mongodb/spock/Slow.java new file mode 100644 index 00000000000..fba0029931d --- /dev/null +++ b/driver-core/src/test/unit/com/mongodb/spock/Slow.java @@ -0,0 +1,26 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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.mongodb.spock; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Slow { +} diff --git a/driver-kotlin-coroutine/build.gradle.kts b/driver-kotlin-coroutine/build.gradle.kts index 59ef13952f2..d28ba244bb6 100644 --- a/driver-kotlin-coroutine/build.gradle.kts +++ b/driver-kotlin-coroutine/build.gradle.kts @@ -13,176 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import io.gitlab.arturbosch.detekt.Detekt -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication plugins { - id("org.jetbrains.kotlin.jvm") - id("java-library") - - // Test based plugins - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.detekt) -} - -repositories { - mavenCentral() - google() + id("project.kotlin") + id("conventions.test-artifacts") } base.archivesName.set("mongodb-driver-kotlin-coroutine") -description = "The MongoDB Kotlin Coroutine Driver" - -ext.set("pomName", "MongoDB Kotlin Coroutine Driver") - -sourceSets { - create("integrationTest") { - kotlin.srcDir("$projectDir/src/integration/kotlin") - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - compileClasspath += project(":driver-sync").sourceSets.test.get().output - runtimeClasspath += project(":driver-sync").sourceSets.test.get().output - compileClasspath += project(":driver-core").sourceSets.test.get().output - runtimeClasspath += project(":driver-core").sourceSets.test.get().output - compileClasspath += project(":bson").sourceSets.test.get().output - runtimeClasspath += project(":bson").sourceSets.test.get().output - } -} - -val integrationTestImplementation: Configuration by - configurations.getting { extendsFrom(configurations.testImplementation.get()) } - dependencies { - // Align versions of all Kotlin components - implementation(platform(libs.kotlin.bom)) - implementation(libs.kotlin.stdlib.jdk8) + api(project(path = ":bson", configuration = "default")) + api(project(path = ":driver-reactive-streams", configuration = "default")) implementation(platform(libs.kotlinx.coroutines.bom)) api(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.reactive) - - api(project(path = ":bson", configuration = "default")) - api(project(path = ":driver-reactive-streams", configuration = "default")) implementation(project(path = ":bson-kotlin", configuration = "default")) - testImplementation(libs.kotlin.reflect) - testImplementation(libs.junit.kotlin) - testImplementation(libs.bundles.mockito.kotlin) - testImplementation(libs.assertj) - testImplementation(libs.classgraph) - - integrationTestImplementation(libs.junit.kotlin) integrationTestImplementation(libs.kotlinx.coroutines.test) - integrationTestImplementation(project(path = ":driver-sync")) - integrationTestImplementation(project(path = ":driver-core")) - integrationTestImplementation(project(path = ":bson")) -} - -kotlin { explicitApi() } - -tasks.withType { kotlinOptions.jvmTarget = "1.8" } - -// =========================== -// Code Quality checks -// =========================== -spotless { - kotlinGradle { - ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") - } - - kotlin { - target("**/*.kt") - ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license")) - } - - format("extraneous") { - target("*.xml", "*.yml", "*.md") - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } -} - -tasks.named("check") { dependsOn("spotlessApply") } - -detekt { - allRules = true // fail build on any finding - buildUponDefaultConfig = true // preconfigure defaults - config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, - // overwriting default behavior - baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt - source = - files( - file("src/main/kotlin"), - file("src/test/kotlin"), - file("src/integrationTest/kotlin"), - ) + integrationTestImplementation(project(path = ":driver-sync", configuration = "default")) + integrationTestImplementation(project(path = ":bson", configuration = "testArtifacts")) + integrationTestImplementation(project(path = ":driver-sync", configuration = "testArtifacts")) + integrationTestImplementation(project(path = ":driver-core", configuration = "testArtifacts")) } -tasks.withType().configureEach { - reports { - html.required.set(true) // observe findings in your browser with structure and code snippets - xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins - txt.required.set(false) // similar to the console output, contains issue signature to manually edit +configureMavenPublication { + pom { + name.set("MongoDB Kotlin Coroutine Driver") + description.set("The MongoDB Kotlin Coroutine Driver") } } -spotbugs { - showProgress.set(true) - - tasks.getByName("spotbugsIntegrationTest") { enabled = false } +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.coroutine" + attributes["Bundle-SymbolicName"] = "org.mongodb.mongodb-driver-kotlin-coroutine" } - -// =========================== -// Test Configuration -// =========================== -val integrationTest = - tasks.create("integrationTest", Test::class) { - description = "Runs the integration tests." - group = "verification" - - testClassesDirs = sourceSets["integrationTest"].output.classesDirs - classpath = sourceSets["integrationTest"].runtimeClasspath - } - -tasks.test { useJUnitPlatform() } - -// =========================== -// Dokka Configuration -// =========================== -val dokkaOutputDir = "${rootProject.buildDir}/docs/${base.archivesName.get()}" - -tasks.dokkaHtml.configure { - outputDirectory.set(file(dokkaOutputDir)) - moduleName.set(base.archivesName.get()) -} - -val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } - -project.parent?.tasks?.named("docs") { - dependsOn(tasks.dokkaHtml) - mustRunAfter(cleanDokka) -} - -tasks.javadocJar.configure { - dependsOn(cleanDokka, tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(dokkaOutputDir) -} - -// =========================== -// Sources publishing configuration -// =========================== -tasks.sourcesJar { from(project.sourceSets.main.map { it.kotlin }) } - -afterEvaluate { tasks.jar { manifest { attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.coroutine" } } } diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/SmokeTests.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/SmokeTests.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/SmokeTests.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/SmokeTests.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedCrudTest.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedCrudTest.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedCrudTest.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedCrudTest.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedTest.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedTest.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedTest.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/UnifiedTest.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncAggregateIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncAggregateIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncAggregateIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncAggregateIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncChangeStreamIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncChangeStreamIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncChangeStreamIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncChangeStreamIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncClientSession.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncClientSession.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncClientSession.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncClientSession.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncFindIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncFindIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncFindIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncFindIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionNamesIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionNamesIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionNamesIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionNamesIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionsIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionsIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionsIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListCollectionsIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListDatabasesIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListDatabasesIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListDatabasesIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListDatabasesIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListIndexesIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListIndexesIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListIndexesIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListIndexesIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListSearchIndexesIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListSearchIndexesIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListSearchIndexesIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncListSearchIndexesIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMapReduceIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMapReduceIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMapReduceIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMapReduceIterable.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoChangeStreamCursor.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoChangeStreamCursor.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoChangeStreamCursor.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoChangeStreamCursor.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoClient.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoClient.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoClient.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoClient.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCollection.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCollection.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCollection.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCollection.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCursor.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCursor.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCursor.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCursor.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoDatabase.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoDatabase.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoDatabase.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoDatabase.kt diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoIterable.kt b/driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoIterable.kt similarity index 100% rename from driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoIterable.kt rename to driver-kotlin-coroutine/src/integrationTest/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoIterable.kt diff --git a/driver-kotlin-extensions/build.gradle.kts b/driver-kotlin-extensions/build.gradle.kts index fc0e134749a..0bd9405f27e 100644 --- a/driver-kotlin-extensions/build.gradle.kts +++ b/driver-kotlin-extensions/build.gradle.kts @@ -13,56 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import io.gitlab.arturbosch.detekt.Detekt +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -plugins { - id("org.jetbrains.kotlin.jvm") - id("java-library") - - // Test based plugins - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.detekt) -} - -repositories { - mavenCentral() - google() -} +plugins { id("project.kotlin") } base.archivesName.set("mongodb-driver-kotlin-extensions") -description = "The MongoDB Kotlin Driver Extensions" - -ext.set("pomName", "MongoDB Kotlin Driver Extensions") - -java { registerFeature("kotlinDrivers") { usingSourceSet(sourceSets["main"]) } } - dependencies { - // Align versions of all Kotlin components - implementation(platform(libs.kotlin.bom)) - implementation(libs.kotlin.stdlib.jdk8) - api(project(path = ":driver-core", configuration = "default")) // Some extensions require higher API like MongoCollection which are defined in the sync & // coroutine Kotlin driver - "kotlinDriversImplementation"(project(path = ":driver-kotlin-sync", configuration = "default")) - "kotlinDriversImplementation"(project(path = ":driver-kotlin-coroutine", configuration = "default")) + optionalImplementation(project(path = ":driver-kotlin-sync", configuration = "default")) + optionalImplementation(project(path = ":driver-kotlin-coroutine", configuration = "default")) - testImplementation(libs.kotlin.reflect) - testImplementation(libs.junit.kotlin) - testImplementation(libs.bundles.mockito.kotlin) - testImplementation(libs.assertj) - testImplementation(libs.classgraph) + testImplementation(platform(libs.kotlinx.serialization)) + testImplementation(libs.kotlinx.serialization.core) +} + +configureMavenPublication { + pom { + name.set("MongoDB Kotlin Driver Extensions") + description.set("The MongoDB Kotlin Driver Extensions") + } } -kotlin { explicitApi() } +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.extensions" + attributes["Bundle-SymbolicName"] = "org.mongodb.mongodb-driver-kotlin-extensions" +} tasks.withType { kotlinOptions { - jvmTarget = "1.8" freeCompilerArgs = listOf( // Adds OnlyInputTypes support @@ -70,101 +54,3 @@ tasks.withType { ) } } - -// =========================== -// Code Quality checks -// =========================== -val customLicenseHeader = "/^(?s)(?!.*@custom-license-header).*/" - -spotless { - kotlinGradle { - ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") - } - - kotlin { - target("**/*.kt") - ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - - licenseHeaderFile(rootProject.file("config/mongodb.license")) - .named("standard") - .onlyIfContentMatches(customLicenseHeader) - } - - format("extraneous") { - target("*.xml", "*.yml", "*.md") - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } -} - -tasks.named("check") { dependsOn("spotlessApply") } - -detekt { - allRules = true // fail build on any finding - buildUponDefaultConfig = true // preconfigure defaults - config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, - // overwriting default behavior - baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt - source = files(file("src/main/kotlin"), file("src/test/kotlin")) -} - -tasks.withType().configureEach { - reports { - html.required.set(true) // observe findings in your browser with structure and code snippets - xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins - txt.required.set(false) // similar to the console output, contains issue signature to manually edit - } -} - -spotbugs { showProgress.set(true) } - -tasks.spotbugsMain { - // we need the xml report to find out the "rank" (see config/spotbugs/exclude.xml) - reports.getByName("xml") { required.set(true) } -} - -// =========================== -// Test Configuration -// =========================== - -tasks.test { useJUnitPlatform() } - -// =========================== -// Dokka Configuration -// =========================== -val dokkaOutputDir = "${rootProject.buildDir}/docs/${base.archivesName.get()}" - -tasks.dokkaHtml.configure { - outputDirectory.set(file(dokkaOutputDir)) - moduleName.set(base.archivesName.get()) -} - -val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } - -project.parent?.tasks?.named("docs") { - dependsOn(tasks.dokkaHtml) - mustRunAfter(cleanDokka) -} - -tasks.javadocJar.configure { - dependsOn(cleanDokka, tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(dokkaOutputDir) -} - -// =========================== -// Sources publishing configuration -// =========================== -tasks.sourcesJar { from(project.sourceSets.main.map { it.kotlin }) } - -afterEvaluate { - tasks.jar { manifest { attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.extensions" } } -} diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/AggregatesTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/AggregatesTest.kt index 50f369e50ec..f0fd6d7a1a4 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/AggregatesTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/AggregatesTest.kt @@ -61,11 +61,11 @@ import com.mongodb.kotlin.client.model.Aggregates.unwind import com.mongodb.kotlin.client.model.Projections.excludeId import com.mongodb.kotlin.client.model.Projections.projection import com.mongodb.kotlin.client.model.Sorts.ascending +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.conversions.Bson import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.Test import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.kotlin.doReturn diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ExtensionsApiTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ExtensionsApiTest.kt index e4455f9cfc6..5bad9104408 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ExtensionsApiTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ExtensionsApiTest.kt @@ -16,8 +16,8 @@ package com.mongodb.kotlin.client.model import io.github.classgraph.ClassGraph +import kotlin.test.Test import kotlin.test.assertTrue -import org.junit.jupiter.api.Test class ExtensionsApiTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/FiltersTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/FiltersTest.kt index da15d6ee5af..0ab3d83936a 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/FiltersTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/FiltersTest.kt @@ -58,11 +58,11 @@ import com.mongodb.kotlin.client.model.Filters.size import com.mongodb.kotlin.client.model.Filters.text import com.mongodb.kotlin.client.model.Filters.type import com.mongodb.kotlin.client.model.Filters.where +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.BsonType import org.bson.conversions.Bson -import org.junit.Test class FiltersTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/IndexesTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/IndexesTest.kt index 00a819810fe..6c4646dd7f6 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/IndexesTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/IndexesTest.kt @@ -26,10 +26,10 @@ import com.mongodb.kotlin.client.model.Indexes.geo2d import com.mongodb.kotlin.client.model.Indexes.geo2dsphere import com.mongodb.kotlin.client.model.Indexes.hashed import com.mongodb.kotlin.client.model.Indexes.text +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.conversions.Bson -import org.junit.Test class IndexesTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt index 9d27b86c7ef..0007c6251ea 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/KPropertiesTest.kt @@ -17,11 +17,11 @@ package com.mongodb.kotlin.client.model import java.util.Locale +import kotlin.test.Test import kotlin.test.assertEquals import kotlinx.serialization.SerialName import org.bson.codecs.pojo.annotations.BsonId import org.bson.codecs.pojo.annotations.BsonProperty -import org.junit.Test import org.junit.jupiter.api.assertThrows class KPropertiesTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ProjectionTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ProjectionTest.kt index b4e49ee7dda..2033713d4dc 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ProjectionTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/ProjectionTest.kt @@ -37,10 +37,10 @@ import com.mongodb.kotlin.client.model.Projections.metaVectorSearchScore import com.mongodb.kotlin.client.model.Projections.projection import com.mongodb.kotlin.client.model.Projections.projectionWith import com.mongodb.kotlin.client.model.Projections.slice +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.conversions.Bson -import org.junit.Test class ProjectionTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/SortsTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/SortsTest.kt index f3740ede352..2a8ec84530f 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/SortsTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/SortsTest.kt @@ -22,10 +22,10 @@ import com.mongodb.client.model.Sorts.orderBy import com.mongodb.kotlin.client.model.Sorts.ascending import com.mongodb.kotlin.client.model.Sorts.descending import com.mongodb.kotlin.client.model.Sorts.metaTextScore +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.conversions.Bson -import org.junit.Test class SortsTest { diff --git a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/UpdatesTest.kt b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/UpdatesTest.kt index aa51bc98921..9b07d6b8345 100644 --- a/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/UpdatesTest.kt +++ b/driver-kotlin-extensions/src/test/kotlin/com/mongodb/kotlin/client/model/UpdatesTest.kt @@ -45,6 +45,7 @@ import com.mongodb.kotlin.client.model.Updates.setOnInsert import com.mongodb.kotlin.client.model.Updates.unset import java.time.Instant import java.util.Date +import kotlin.test.Test import kotlin.test.assertEquals import org.bson.BsonDocument import org.bson.Document @@ -53,7 +54,6 @@ import org.bson.codecs.configuration.CodecRegistries.fromProviders import org.bson.codecs.configuration.CodecRegistry import org.bson.codecs.pojo.PojoCodecProvider import org.bson.conversions.Bson -import org.junit.Test class UpdatesTest { @Test diff --git a/driver-kotlin-sync/build.gradle.kts b/driver-kotlin-sync/build.gradle.kts index e0131613a97..f7a8d37840f 100644 --- a/driver-kotlin-sync/build.gradle.kts +++ b/driver-kotlin-sync/build.gradle.kts @@ -13,170 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import io.gitlab.arturbosch.detekt.Detekt -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication plugins { - id("org.jetbrains.kotlin.jvm") - id("java-library") - - // Test based plugins - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.detekt) -} - -repositories { - mavenCentral() - google() + id("project.kotlin") + id("conventions.test-artifacts") } base.archivesName.set("mongodb-driver-kotlin-sync") -description = "The MongoDB Kotlin Driver" - -ext.set("pomName", "MongoDB Kotlin Driver") - -sourceSets { - create("integrationTest") { - kotlin.srcDir("$projectDir/src/integration/kotlin") - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - compileClasspath += project(":driver-sync").sourceSets.test.get().output - runtimeClasspath += project(":driver-sync").sourceSets.test.get().output - compileClasspath += project(":driver-core").sourceSets.test.get().output - runtimeClasspath += project(":driver-core").sourceSets.test.get().output - compileClasspath += project(":bson").sourceSets.test.get().output - runtimeClasspath += project(":bson").sourceSets.test.get().output - } -} - -val integrationTestImplementation: Configuration by - configurations.getting { extendsFrom(configurations.testImplementation.get()) } - dependencies { - // Align versions of all Kotlin components - implementation(platform(libs.kotlin.bom)) - implementation(libs.kotlin.stdlib.jdk8) - api(project(path = ":bson", configuration = "default")) api(project(path = ":driver-sync", configuration = "default")) implementation(project(path = ":bson-kotlin", configuration = "default")) - testImplementation(libs.kotlin.reflect) - testImplementation(libs.junit.kotlin) - testImplementation(libs.bundles.mockito.kotlin) - testImplementation(libs.assertj) - testImplementation(libs.classgraph) - - integrationTestImplementation(libs.junit.kotlin) - integrationTestImplementation(project(path = ":driver-sync")) - integrationTestImplementation(project(path = ":driver-core")) -} - -kotlin { explicitApi() } - -tasks.withType { kotlinOptions.jvmTarget = "1.8" } - -// =========================== -// Code Quality checks -// =========================== -spotless { - kotlinGradle { - ktfmt("0.39").dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license"), "(group|plugins|import|buildscript|rootProject)") - } - - kotlin { - target("**/*.kt") - ktfmt().dropboxStyle().configure { it.setMaxWidth(120) } - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - licenseHeaderFile(rootProject.file("config/mongodb.license")) - } - - format("extraneous") { - target("*.xml", "*.yml", "*.md") - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } + integrationTestImplementation(project(path = ":bson", configuration = "testArtifacts")) + integrationTestImplementation(project(path = ":driver-sync", configuration = "testArtifacts")) + integrationTestImplementation(project(path = ":driver-core", configuration = "testArtifacts")) } -tasks.named("check") { dependsOn("spotlessApply") } - -detekt { - allRules = true // fail build on any finding - buildUponDefaultConfig = true // preconfigure defaults - config = rootProject.files("config/detekt/detekt.yml") // point to your custom config defining rules to run, - // overwriting default behavior - baseline = rootProject.file("config/detekt/baseline.xml") // a way of suppressing issues before introducing detekt - source = - files( - file("src/main/kotlin"), - file("src/test/kotlin"), - file("src/integrationTest/kotlin"), - ) -} - -tasks.withType().configureEach { - reports { - html.required.set(true) // observe findings in your browser with structure and code snippets - xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins - txt.required.set(false) // similar to the console output, contains issue signature to manually edit +configureMavenPublication { + pom { + name.set("MongoDB Kotlin Driver") + description.set("The MongoDB Kotlin Driver") } } -spotbugs { - showProgress.set(true) - - tasks.getByName("spotbugsIntegrationTest") { enabled = false } +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.sync" + attributes["Bundle-SymbolicName"] = "org.mongodb.mongodb-driver-kotlin-sync" } - -// =========================== -// Test Configuration -// =========================== -val integrationTest = - tasks.create("integrationTest", Test::class) { - description = "Runs the integration tests." - group = "verification" - - testClassesDirs = sourceSets["integrationTest"].output.classesDirs - classpath = sourceSets["integrationTest"].runtimeClasspath - } - -tasks.test { useJUnitPlatform() } - -// =========================== -// Dokka Configuration -// =========================== -val dokkaOutputDir = "${rootProject.buildDir}/docs/${base.archivesName.get()}" - -tasks.dokkaHtml.configure { - outputDirectory.set(file(dokkaOutputDir)) - moduleName.set(base.archivesName.get()) -} - -val cleanDokka by tasks.register("cleanDokka") { delete(dokkaOutputDir) } - -project.parent?.tasks?.named("docs") { - dependsOn(tasks.dokkaHtml) - mustRunAfter(cleanDokka) -} - -tasks.javadocJar.configure { - dependsOn(cleanDokka, tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(dokkaOutputDir) -} - -// =========================== -// Sources publishing configuration -// =========================== -tasks.sourcesJar { from(project.sourceSets.main.map { it.kotlin }) } - -afterEvaluate { tasks.jar { manifest { attributes["Automatic-Module-Name"] = "org.mongodb.driver.kotlin.sync" } } } diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/SmokeTests.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/SmokeTests.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/SmokeTests.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/SmokeTests.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionNamesIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionNamesIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionNamesIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionNamesIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListSearchIndexesIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListSearchIndexesIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListSearchIndexesIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListSearchIndexesIterable.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCursor.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCursor.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCursor.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCursor.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoDatabase.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoDatabase.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoDatabase.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoDatabase.kt diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoIterable.kt b/driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoIterable.kt similarity index 100% rename from driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoIterable.kt rename to driver-kotlin-sync/src/integrationTest/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoIterable.kt diff --git a/driver-lambda/build.gradle b/driver-lambda/build.gradle.kts similarity index 63% rename from driver-lambda/build.gradle rename to driver-lambda/build.gradle.kts index d1e4f624629..d5cd57cfaa9 100644 --- a/driver-lambda/build.gradle +++ b/driver-lambda/build.gradle.kts @@ -14,34 +14,29 @@ * limitations under the License. */ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - id("java") id("application") + id("java-library") + id("project.base") alias(libs.plugins.shadow) } -compileJava { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 +application { + mainClass = "com.mongodb.lambdatest.LambdaTestApp" } -mainClassName = "com.mongodb.workload.WorkloadExecutor" - sourceSets { main { - java { - srcDir 'src/main' - } - resources { - srcDir 'src/resources' - } + java { setSrcDirs(listOf("src/main")) } + resources { setSrcDirs(listOf("src/resources")) } } } dependencies { - implementation project(':driver-sync') - implementation project(':bson') + implementation(project(":driver-sync")) + implementation(project(":bson")) implementation(libs.aws.lambda.core) implementation(libs.aws.lambda.events) @@ -49,18 +44,21 @@ dependencies { implementation(libs.bundles.junit) } - -javadoc { +tasks.withType().configureEach { enabled = false } -jar { +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +tasks.withType { manifest { - attributes "Main-Class": "com.mongodb.lambdatest.LambdaTestApp" + attributes["Main-Class"] = "com.mongodb.lambdatest.LambdaTestApp" } } - -shadowJar { - archiveBaseName.set('lambdatest') - archiveVersion.set('') +tasks.withType { + archiveBaseName.set("lambdatest") + archiveVersion.set("") } diff --git a/driver-legacy/build.gradle.kts b/driver-legacy/build.gradle.kts new file mode 100644 index 00000000000..b141d1d7cb4 --- /dev/null +++ b/driver-legacy/build.gradle.kts @@ -0,0 +1,47 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.test-artifacts") + id("conventions.test-include-optionals") + id("conventions.testing-junit") + id("conventions.testing-spock-exclude-slow") +} + +base.archivesName.set("mongodb-driver-legacy") + +dependencies { + api(project(path = ":bson", configuration = "default")) + api(project(path = ":driver-core", configuration = "default")) + api(project(path = ":driver-sync", configuration = "default")) + + testImplementation(project(path = ":bson", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-core", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-sync", configuration = "testArtifacts")) +} + +configureMavenPublication { + pom { + name.set("The Legacy MongoDB Driver") + description.set("The Legacy MongoDB Driver") + } +} + +// Disable the manifest for driver-legacy as its not a valid OSGI package +configureJarManifest { attributes["-nomanifest"] = true } diff --git a/driver-legacy/src/test/functional/com/mongodb/MongoClientSessionSpecification.groovy b/driver-legacy/src/test/functional/com/mongodb/MongoClientSessionSpecification.groovy index e6929fa4020..b76872c3d81 100644 --- a/driver-legacy/src/test/functional/com/mongodb/MongoClientSessionSpecification.groovy +++ b/driver-legacy/src/test/functional/com/mongodb/MongoClientSessionSpecification.groovy @@ -28,7 +28,7 @@ import org.bson.Document import org.bson.types.ObjectId import org.junit.Assert import spock.lang.IgnoreIf -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.TimeUnit diff --git a/driver-reactive-streams/build.gradle b/driver-reactive-streams/build.gradle deleted file mode 100644 index f50a12de147..00000000000 --- a/driver-reactive-streams/build.gradle +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -description = "A Reactive Streams implementation of the MongoDB Java driver" -archivesBaseName = 'mongodb-driver-reactivestreams' - -dependencies { - api project(path: ':bson', configuration: 'default') - api project(path: ':driver-core', configuration: 'default') - - api(libs.reactive.streams) - implementation(platform(libs.project.reactor.bom)) - implementation(libs.project.reactor.core) - - testImplementation project(':bson').sourceSets.test.output - testImplementation project(':driver-sync') - testImplementation project(':driver-sync').sourceSets.test.output - testImplementation project(':driver-core').sourceSets.test.output - testImplementation(libs.reactive.streams.tck) - - testImplementation(libs.project.reactor.test) - if ('8'.equals(findProperty("javaVersion"))) { - testImplementation(libs.bundles.mockito.java8) - } else { - testImplementation(libs.bundles.mockito) - } - - testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') -} - -sourceSets { - test.groovy.srcDirs += ['src/examples'] - test.java.srcDirs += ['src/test/tck'] -} - -test { - exclude 'tour/**' -} - -// Reactive Streams TCK uses TestNG, and Gradle can't run TestNG and JUnit in the same run. -task tckTest(type: Test) { - useTestNG() - scanForTestClasses = false - - classpath = sourceSets.test.runtimeClasspath - testClassesDirs = sourceSets.test.output.classesDirs - - binaryResultsDirectory.set(file("$buildDir/$name-results/binary")) - reports { - html.destination = file("$buildDir/reports/$name") - junitXml.destination = file("$buildDir/$name-results") - } - - maxParallelForks = 1 -} - -ext { - pomName = 'The MongoDB Reactive Streams Driver' -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.driver.reactivestreams' - jar.manifest.attributes['Bundle-SymbolicName'] = 'org.mongodb.driver-reactivestreams' - jar.manifest.attributes['Import-Package'] = [ - 'com.mongodb.crypt.capi.*;resolution:=optional', - 'com.mongodb.internal.crypt.capi.*;resolution:=optional', - '*', - ].join(',') -} diff --git a/driver-reactive-streams/build.gradle.kts b/driver-reactive-streams/build.gradle.kts new file mode 100644 index 00000000000..cd100a26585 --- /dev/null +++ b/driver-reactive-streams/build.gradle.kts @@ -0,0 +1,78 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.test-artifacts") + id("conventions.test-include-optionals") + id("conventions.testing-mockito") + id("conventions.testing-junit") + id("conventions.testing-spock-exclude-slow") +} + +base.archivesName.set("mongodb-driver-reactivestreams") + +dependencies { + api(project(path = ":bson", configuration = "default")) + api(project(path = ":driver-core", configuration = "default")) + api(libs.reactive.streams) + implementation(platform(libs.project.reactor.bom)) + implementation(libs.project.reactor.core) + compileOnly(project(path = ":mongodb-crypt", configuration = "default")) + + testImplementation(libs.project.reactor.test) + testImplementation(project(path = ":driver-sync", configuration = "default")) + testImplementation(project(path = ":bson", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-core", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-sync", configuration = "testArtifacts")) + + // Reactive Streams TCK testing + testImplementation(libs.reactive.streams.tck) +} + +configureMavenPublication { + pom { + name.set("The MongoDB Reactive Streams Driver") + description.set("A Reactive Streams implementation of the MongoDB Java driver") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.reactivestreams" + attributes["Bundle-SymbolicName"] = "org.mongodb.driver-reactivestreams" + attributes["Import-Package"] = + listOf( + "com.mongodb.crypt.capi.*;resolution:=optional", + "com.mongodb.internal.crypt.capi.*;resolution:=optional", + "*" // import all that is not excluded or modified before + ) + .joinToString(",") +} + +sourceSets { test { java { setSrcDirs(listOf("src/test/tck")) } } } + +// Reactive Streams TCK uses TestNG +tasks.register("tckTest", Test::class) { + useTestNG() + maxParallelForks = 1 + isScanForTestClasses = false + + binaryResultsDirectory.set(layout.buildDirectory.dir("$name-results/binary")) + reports.html.outputLocation.set(layout.buildDirectory.dir("reports/$name")) + reports.junitXml.outputLocation.set(layout.buildDirectory.dir("reports/$name-results")) +} diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionCorpusTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionCorpusTest.java index 9a44252b938..d36942c212a 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionCorpusTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionCorpusTest.java @@ -38,7 +38,6 @@ import org.junit.runners.Parameterized; import reactor.core.publisher.Mono; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.Arrays; @@ -283,9 +282,8 @@ public void testCorpus() throws IOException, URISyntaxException { } } - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionCorpusTest.class - .getResource("/client-side-encryption-corpus/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-corpus/" + path); } @Parameterized.Parameters(name = "useLocalSchema: {0}") diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionExternalKeyVaultTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionExternalKeyVaultTest.java index bc43222239f..f3c10a87f07 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionExternalKeyVaultTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionExternalKeyVaultTest.java @@ -36,9 +36,6 @@ import org.junit.runners.Parameterized; import reactor.core.publisher.Mono; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Arrays; import java.util.Base64; import java.util.Collection; @@ -146,9 +143,8 @@ public void testExternal() { assertEquals(authExceptionThrown, withExternalKeyVault); } - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionExternalKeyVaultTest.class - .getResource("/client-side-encryption-external/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-external/" + path); } @Parameterized.Parameters(name = "withExternalKeyVault: {0}") diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionSessionTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionSessionTest.java index f6814013779..ec7c8ccf648 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionSessionTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideEncryptionSessionTest.java @@ -31,9 +31,6 @@ import org.junit.runners.Parameterized; import reactor.core.publisher.Mono; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Arrays; import java.util.Base64; import java.util.Collection; @@ -152,8 +149,7 @@ public void testWithExplicitSession() throws Throwable { assertEquals(6, encryptedDocument.getBinary("encrypted").getType()); } - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionSessionTest.class - .getResource("/client-side-encryption-external/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-external/" + path); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/MongoClientSessionSpecification.groovy b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/MongoClientSessionSpecification.groovy index 64c1386e0e7..5fda2f76319 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/MongoClientSessionSpecification.groovy +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/MongoClientSessionSpecification.groovy @@ -32,7 +32,7 @@ import org.bson.Document import org.junit.Assert import reactor.core.publisher.Mono import spock.lang.IgnoreIf -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.TimeUnit diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ReactiveInitialDnsSeedlistDiscoveryTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ReactiveInitialDnsSeedlistDiscoveryTest.java index cdc30a80cdc..834bf6ddf35 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ReactiveInitialDnsSeedlistDiscoveryTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ReactiveInitialDnsSeedlistDiscoveryTest.java @@ -24,14 +24,13 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.nio.file.Path; import java.util.List; // See https://github.com/mongodb/specifications/tree/master/source/initial-dns-seedlist-discovery/tests @RunWith(Parameterized.class) public class ReactiveInitialDnsSeedlistDiscoveryTest extends InitialDnsSeedlistDiscoveryTest { - public ReactiveInitialDnsSeedlistDiscoveryTest(final String filename, final Path parentDirectory, final String uri, + public ReactiveInitialDnsSeedlistDiscoveryTest(final String filename, final String parentDirectory, final String uri, final List seeds, final Integer numSeeds, final List hosts, final Integer numHosts, final BsonDocument options, final BsonDocument parsedOptions, final boolean isError, final boolean executePingCommand) { diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ChangeStreamsTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ChangeStreamsTest.java index 6775cc8570e..5d59779076e 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ChangeStreamsTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ChangeStreamsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ChangeStreamsTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/change-streams"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideEncryptionTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideEncryptionTest.java index 8169a300e0e..431664d224d 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideEncryptionTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideEncryptionTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ClientSideEncryptionTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/client-side-encryption"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java index a1063f05362..bb0c39e1489 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java @@ -31,8 +31,6 @@ import org.junit.jupiter.params.provider.MethodSource; import reactor.core.publisher.Hooks; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -50,7 +48,7 @@ public class ClientSideOperationTimeoutTest extends UnifiedReactiveStreamsTest { private final AtomicReference atomicReferenceThrowable = new AtomicReference<>(); - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/client-side-operation-timeout"); } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CollectionManagementTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CollectionManagementTest.java index 5e3038a06c8..f187cb360e2 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CollectionManagementTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CollectionManagementTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class CollectionManagementTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/collection-management"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandLoggingTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandLoggingTest.java index 10d563cb928..d75fceb5081 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandLoggingTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class CommandLoggingTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/command-logging"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandMonitoringTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandMonitoringTest.java index c30ca720b46..ad5dd230175 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandMonitoringTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/CommandMonitoringTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class CommandMonitoringTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/command-monitoring"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ConnectionPoolLoggingTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ConnectionPoolLoggingTest.java index 12db392686f..26d314b0f82 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ConnectionPoolLoggingTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ConnectionPoolLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ConnectionPoolLoggingTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/connection-monitoring-and-pooling/logging"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/IndexManagmentTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/IndexManagmentTest.java index 931a53dba40..346b3adfce3 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/IndexManagmentTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/IndexManagmentTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class IndexManagmentTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/index-management"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/LoadBalancerTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/LoadBalancerTest.java index f60f42139b4..317c718a45b 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/LoadBalancerTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/LoadBalancerTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class LoadBalancerTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/load-balancers"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ServerSelectionLoggingTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ServerSelectionLoggingTest.java index d78522fb75c..c89329e3940 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ServerSelectionLoggingTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ServerSelectionLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ServerSelectionLoggingTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/server-selection/logging"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/SessionsTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/SessionsTest.java index 81cd47637a0..c68d847f839 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/SessionsTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/SessionsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class SessionsTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/sessions"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedCrudTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedCrudTest.java index b8fd81ac7c7..f69c4a55c68 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedCrudTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedCrudTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedCrudTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/crud"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedGridFSTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedGridFSTest.java index eefc6839d17..4fe8015421f 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedGridFSTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedGridFSTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedGridFSTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/gridfs"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedReactiveStreamsTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedReactiveStreamsTest.java index 28c8a27f8fa..716d04a2890 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedReactiveStreamsTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedReactiveStreamsTest.java @@ -34,8 +34,6 @@ import com.mongodb.reactivestreams.client.syncadapter.SyncMongoDatabase; import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; import static com.mongodb.client.unified.UnifiedTestModifications.Modifier; @@ -102,7 +100,7 @@ protected void postCleanUp(final TestDef testDef) { } @NonNull - protected static Collection getTestData(final String directory) throws URISyntaxException, IOException { + protected static Collection getTestData(final String directory) { return getTestData(directory, true); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableReadsTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableReadsTest.java index 4f2336f4173..ac2c986e88a 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableReadsTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableReadsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedRetryableReadsTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/retryable-reads"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableWritesTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableWritesTest.java index 8fbfb43d92d..8cc66ea813b 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableWritesTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedRetryableWritesTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedRetryableWritesTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/retryable-writes"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java index e4fb6da3627..e016fc7ecdc 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedServerDiscoveryAndMonitoringTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/server-discovery-and-monitoring"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedTransactionsTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedTransactionsTest.java index c1990e5d830..43bb0fd8229 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedTransactionsTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedTransactionsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedTransactionsTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/transactions"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedWriteConcernTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedWriteConcernTest.java index 3b7fa4afb00..08a7bccabf3 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedWriteConcernTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/UnifiedWriteConcernTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedWriteConcernTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/write-concern"); } } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/VersionedApiTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/VersionedApiTest.java index 5a0d4b69dcd..8378fb00482 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/VersionedApiTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/VersionedApiTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class VersionedApiTest extends UnifiedReactiveStreamsTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("versioned-api"); } } diff --git a/driver-scala/build.gradle b/driver-scala/build.gradle deleted file mode 100644 index e9e9e15040e..00000000000 --- a/driver-scala/build.gradle +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -description = "A Scala wrapper of the MongoDB Reactive Streams Java driver" -archivesBaseName = 'mongo-scala-driver' - - -dependencies { - api project(path: ':bson-scala', configuration: 'default') - api project(path: ':driver-reactive-streams', configuration: 'default') - compileOnly 'com.google.code.findbugs:jsr305:1.3.9' - - testImplementation project(':driver-sync') - testImplementation project(':bson').sourceSets.test.output - testImplementation project(':driver-sync').sourceSets.test.output - testImplementation project(':driver-core').sourceSets.test.output - testImplementation project(':driver-reactive-streams').sourceSets.test.output - testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') -} - -sourceSets { - integrationTest { - scala.srcDir file('src/integration/scala') - scala { - compileClasspath += main.output - runtimeClasspath += main.output - } - } -} - -test { - maxParallelForks = 1 -} - -tasks.withType(Test) { - doFirst { - println("Running Test task using scala version: $scalaVersion") - } -} - -tasks.withType(ScalaCompile) { - if(scalaVersion.startsWith("2.11")) { - // Better support SAM style closures in scala 2.11 - scalaCompileOptions.additionalParameters.addAll([ - // Better support SAM style closures in scala 2.11 - "-Xexperimental" - ]) - } -} - -task integrationTest(type: Test) { - delete 'build/test-integration' - testClassesDirs = sourceSets.integrationTest.output.classesDirs - classpath = sourceSets.integrationTest.runtimeClasspath - mustRunAfter test -} - -check.dependsOn integrationTest - -// =================== -// Scala checks -// =================== -tasks.register("scalaCheck") { - description = "Runs all the Scala checks" - group = "verification" - - dependsOn("clean", "compileTestScala", "compileIntegrationTestScala", "check") - tasks.findByName("check").mustRunAfter("clean") -} - - -task aggregatedScalaDoc(type: ScalaDoc) { - description('Unified Scaladoc for bson-scala and driver-scala') - group('documentation') - ext.fromProjects = [ - project(':bson-scala'), - project(':driver-scala') - ] - destinationDir = file("${rootProject.buildDir.path}/docs/${project.archivesBaseName}") - classpath = project.sourceSets.main.compileClasspath - source = fromProjects.collect { it.sourceSets.main.allSource } - - scalaDocOptions.additionalParameters = ["-doc-root-content", "${project.rootDir}/driver-scala/rootdoc.txt" as String] -} -project.parent.tasks.named("docs"){ it.dependsOn(aggregatedScalaDoc) } - -configurations { - integrationTestImplementation { - extendsFrom testImplementation - canBeResolved = true - } -} - -idea { - module { - testSourceDirs += sourceSets.integrationTest.scala.srcDirs - testResourceDirs += sourceSets.integrationTest.resources.srcDirs - scopes.TEST.plus += [ configurations.integrationTestImplementation ] - } -} - - -ext { - pomName = 'Mongo Scala Driver' -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.driver.scala' - jar.manifest.attributes['Import-Package'] = [ - '!scala.*', - '*' - ].join(',') -} diff --git a/driver-scala/build.gradle.kts b/driver-scala/build.gradle.kts new file mode 100644 index 00000000000..96828175d29 --- /dev/null +++ b/driver-scala/build.gradle.kts @@ -0,0 +1,60 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication +import ProjectExtensions.scalaVersion + +plugins { id("project.scala") } + +base.archivesName.set("mongo-scala-driver") + +val scalaVersion: String = project.scalaVersion() + +dependencies { + api(project(path = ":bson-scala", configuration = "default")) + api(project(path = ":driver-reactive-streams", configuration = "default")) + + testImplementation(project(path = ":driver-sync", configuration = "default")) + testImplementation(project(path = ":bson", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-core", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-sync", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-reactive-streams", configuration = "testArtifacts")) + + // Encryption testing + integrationTestImplementation(project(path = ":mongodb-crypt", configuration = "default")) +} + +configureMavenPublication { + pom { + name.set("Mongo Scala Driver") + description.set("A Scala wrapper of the MongoDB Reactive Streams Java driver") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.scala" + attributes["Bundle-SymbolicName"] = "org.mongodb.scala.mongo-scala-driver" + attributes["Import-Package"] = "!scala.*,*" +} + +// =================== +// Scala docs +// =================== +tasks.withType().forEach { + // Include bson-scala source for main scaladoc + project(":bson-scala").tasks.withType().forEach { bsonScala -> it.source += bsonScala.source } + it.scalaDocOptions.additionalParameters = listOf("-doc-root-content", "${project.rootDir}/driver-scala/rootdoc.txt") +} diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/BaseSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/BaseSpec.scala similarity index 88% rename from driver-scala/src/integration/scala/org/mongodb/scala/BaseSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/BaseSpec.scala index 98ce89a88fe..9d59b8f55e6 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/BaseSpec.scala +++ b/driver-scala/src/integrationTest/scala/org/mongodb/scala/BaseSpec.scala @@ -15,10 +15,7 @@ */ package org.mongodb.scala -import org.junit.runner.RunWith import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -import org.scalatestplus.junit.JUnitRunner -@RunWith(classOf[JUnitRunner]) abstract class BaseSpec extends AnyFlatSpec with Matchers {} diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/ClientSideEncryptionBypassAutoEncryptionSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/ClientSideEncryptionBypassAutoEncryptionSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/ClientSideEncryptionBypassAutoEncryptionSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/ClientSideEncryptionBypassAutoEncryptionSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/ClientSideEncryptionTest.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/ClientSideEncryptionTest.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/ClientSideEncryptionTest.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/ClientSideEncryptionTest.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/FuturesSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/FuturesSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/FuturesSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/FuturesSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/MongoCollectionCaseClassSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/MongoCollectionCaseClassSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/MongoCollectionCaseClassSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/MongoCollectionCaseClassSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/RequiresMongoDBISpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/RequiresMongoDBISpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/RequiresMongoDBISpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/RequiresMongoDBISpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/TestMongoClientHelper.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/TestMongoClientHelper.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/TestMongoClientHelper.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/TestMongoClientHelper.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala similarity index 98% rename from driver-scala/src/integration/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala index 55f943a9402..e6ca96183e6 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala +++ b/driver-scala/src/integrationTest/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala @@ -20,7 +20,6 @@ import java.io.ByteArrayOutputStream import java.nio.ByteBuffer import java.nio.channels.Channels import java.util.UUID - import org.bson.UuidRepresentation import org.bson.codecs.UuidCodec import org.bson.codecs.configuration.CodecRegistries @@ -31,6 +30,7 @@ import org.scalatest.BeforeAndAfterEach import org.scalatest.exceptions.TestFailedException import scala.annotation.tailrec +import scala.concurrent.Await class GridFSObservableSpec extends RequiresMongoDBISpec with FuturesSpec with BeforeAndAfterEach { private val filesCollectionName = "fs.files" @@ -45,13 +45,13 @@ class GridFSObservableSpec extends RequiresMongoDBISpec with FuturesSpec with Be val mongoDatabase = mongoClient().getDatabase(databaseName) _filesCollection = Some(mongoDatabase.getCollection[GridFSFile](filesCollectionName)) _chunksCollection = Some(mongoDatabase.getCollection(chunksCollectionName)) - _filesCollection.map(_.drop()) - _chunksCollection.map(_.drop()) + _filesCollection.foreach(coll => Await.result(coll.drop().toFuture(), WAIT_DURATION)) + _chunksCollection.foreach(coll => Await.result(coll.drop().toFuture(), WAIT_DURATION)) _gridFSBucket = Some(GridFSBucket(mongoDatabase)) } override def afterEach(): Unit = { - withDatabase(db => db.drop()) + withDatabase(db => Await.result(db.drop().toFuture(), WAIT_DURATION)) } private def gridFSBucket = _gridFSBucket.get diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoClient.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoClient.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoClient.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoClient.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/package.scala b/driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/package.scala similarity index 100% rename from driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/package.scala rename to driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/package.scala diff --git a/driver-scala/src/integration/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala b/driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala rename to driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala diff --git a/driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala b/driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala rename to driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala diff --git a/driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala b/driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala rename to driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala diff --git a/driver-scala/src/integration/scala/tour/ClientSideEncryptionSimpleTour.scala b/driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionSimpleTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/ClientSideEncryptionSimpleTour.scala rename to driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionSimpleTour.scala diff --git a/driver-scala/src/integration/scala/tour/GridFSTour.scala b/driver-scala/src/integrationTest/scala/tour/GridFSTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/GridFSTour.scala rename to driver-scala/src/integrationTest/scala/tour/GridFSTour.scala diff --git a/driver-scala/src/integration/scala/tour/Helpers.scala b/driver-scala/src/integrationTest/scala/tour/Helpers.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/Helpers.scala rename to driver-scala/src/integrationTest/scala/tour/Helpers.scala diff --git a/driver-scala/src/integration/scala/tour/QuickTour.scala b/driver-scala/src/integrationTest/scala/tour/QuickTour.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/QuickTour.scala rename to driver-scala/src/integrationTest/scala/tour/QuickTour.scala diff --git a/driver-scala/src/integration/scala/tour/QuickTourCaseClass.scala b/driver-scala/src/integrationTest/scala/tour/QuickTourCaseClass.scala similarity index 100% rename from driver-scala/src/integration/scala/tour/QuickTourCaseClass.scala rename to driver-scala/src/integrationTest/scala/tour/QuickTourCaseClass.scala diff --git a/driver-scala/src/test/scala/org/mongodb/scala/ApiAliasAndCompanionSpec.scala b/driver-scala/src/test/scala/org/mongodb/scala/ApiAliasAndCompanionSpec.scala index 2e21d30526a..a5b76965651 100644 --- a/driver-scala/src/test/scala/org/mongodb/scala/ApiAliasAndCompanionSpec.scala +++ b/driver-scala/src/test/scala/org/mongodb/scala/ApiAliasAndCompanionSpec.scala @@ -73,6 +73,7 @@ class ApiAliasAndCompanionSpec extends BaseSpec { "ServerSession", "SessionContext", "SingleResultCallback", + "Slow", "SubjectProvider", "TransactionExample", "UnixServerAddress", diff --git a/driver-scala/src/test/scala/org/mongodb/scala/BaseSpec.scala b/driver-scala/src/test/scala/org/mongodb/scala/BaseSpec.scala index 98ce89a88fe..9d59b8f55e6 100644 --- a/driver-scala/src/test/scala/org/mongodb/scala/BaseSpec.scala +++ b/driver-scala/src/test/scala/org/mongodb/scala/BaseSpec.scala @@ -15,10 +15,7 @@ */ package org.mongodb.scala -import org.junit.runner.RunWith import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -import org.scalatestplus.junit.JUnitRunner -@RunWith(classOf[JUnitRunner]) abstract class BaseSpec extends AnyFlatSpec with Matchers {} diff --git a/driver-sync/build.gradle b/driver-sync/build.gradle deleted file mode 100644 index 2ea76dbd829..00000000000 --- a/driver-sync/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -archivesBaseName = 'mongodb-driver-sync' -description = 'The MongoDB Synchronous Driver' -ext { - pomName = 'MongoDB Driver' -} - -dependencies { - api project(path: ':bson', configuration: 'default') - api project(path: ':driver-core', configuration: 'default') - - testImplementation project(':bson').sourceSets.test.output - testImplementation project(':driver-core').sourceSets.test.output - testRuntimeOnly project(path: ':driver-core', configuration: 'consumableTestRuntimeOnly') - - testImplementation(libs.aws.lambda.core) -} - -sourceSets { - test.groovy.srcDirs += ['src/examples'] -} - -test { - exclude 'tour/**' -} - -tasks.withType(Checkstyle) { - // needed so the Javadoc checks can find the code in other modules - classpath = files(project(':driver-core').sourceSets.main.output, sourceSets.main.output) -} - -afterEvaluate { - jar.manifest.attributes['Automatic-Module-Name'] = 'org.mongodb.driver.sync.client' - jar.manifest.attributes['Bundle-SymbolicName'] = 'org.mongodb.driver-sync' - jar.manifest.attributes['Import-Package'] = [ - 'com.mongodb.crypt.capi.*;resolution:=optional', - 'com.mongodb.internal.crypt.capi.*;resolution:=optional', - '*', - ].join(',') -} diff --git a/driver-sync/build.gradle.kts b/driver-sync/build.gradle.kts new file mode 100644 index 00000000000..efbef9b2832 --- /dev/null +++ b/driver-sync/build.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication + +plugins { + id("project.java") + id("conventions.test-artifacts") + id("conventions.test-include-optionals") + id("conventions.testing-mockito") + id("conventions.testing-junit") + id("conventions.testing-spock-exclude-slow") +} + +base.archivesName.set("mongodb-driver-sync") + +dependencies { + api(project(path = ":bson", configuration = "default")) + api(project(path = ":driver-core", configuration = "default")) + compileOnly(project(path = ":mongodb-crypt", configuration = "default")) + + testImplementation(project(path = ":bson", configuration = "testArtifacts")) + testImplementation(project(path = ":driver-core", configuration = "testArtifacts")) + + // lambda testing + testImplementation(libs.aws.lambda.core) +} + +configureMavenPublication { + pom { + name.set("MongoDB Driver") + description.set("The MongoDB Synchronous Driver") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "org.mongodb.driver.sync.client" + attributes["Bundle-SymbolicName"] = "org.mongodb.driver-sync" + attributes["Import-Package"] = + listOf( + "com.mongodb.crypt.capi.*;resolution:=optional", + "com.mongodb.internal.crypt.capi.*;resolution:=optional", + "*", + ) + .joinToString(",") +} diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionDeadlockTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionDeadlockTest.java index 2a83b328298..c7a8893ada0 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionDeadlockTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionDeadlockTest.java @@ -44,7 +44,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.HashSet; @@ -225,9 +224,8 @@ private static MongoClientSettings getClientSettings(final int maxPoolSize, .build(); } - private static BsonDocument bsonDocumentFromPath(final String path) throws URISyntaxException, IOException { - return getTestDocument(new File(ClientSideEncryptionExternalKeyVaultTest.class - .getResource("/client-side-encryption-external/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-external/" + path); } private static final class ExpectedEvent { diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionExplicitEncryptionTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionExplicitEncryptionTest.java index 068a9079dad..3979f63cf93 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionExplicitEncryptionTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionExplicitEncryptionTest.java @@ -37,7 +37,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -54,7 +53,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static util.JsonPoweredTestHelper.getTestDocument; @@ -207,12 +205,6 @@ public void canRoundtripEncryptedUnindexed() { } private static BsonDocument bsonDocumentFromPath(final String path) { - try { - return getTestDocument(new File(AbstractClientSideEncryptionExplicitEncryptionTest.class - .getResource("/client-side-encryption-data/" + path).toURI())); - } catch (Exception e) { - fail("Unable to load resource", e); - return null; - } + return getTestDocument("/client-side-encryption-data/" + path); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionNotSpawnMongocryptdTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionNotSpawnMongocryptdTest.java index 3ec814ba704..13acc41cf2e 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionNotSpawnMongocryptdTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionNotSpawnMongocryptdTest.java @@ -23,7 +23,6 @@ import com.mongodb.MongoTimeoutException; import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; -import com.mongodb.assertions.Assertions; import com.mongodb.lang.Nullable; import org.bson.BsonDocument; import org.bson.Document; @@ -31,7 +30,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.File; import java.net.InetAddress; import java.net.InetSocketAddress; import java.time.Duration; @@ -43,6 +41,7 @@ import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.stream.Stream; + import static com.mongodb.ClusterFixture.serverVersionAtLeast; import static com.mongodb.client.AbstractClientSideEncryptionNotCreateMongocryptdClientTest.findAvailableMongocryptdLoopbackPort; import static com.mongodb.client.AbstractClientSideEncryptionTest.cryptSharedLibPathSysPropValue; @@ -216,21 +215,11 @@ private void assertMongocryptdNotSpawned() { } private static BsonDocument externalSchema() { - try { - return getTestDocument(new File(Assertions.assertNotNull(AbstractClientSideEncryptionNotSpawnMongocryptdTest.class - .getResource("/client-side-encryption-external/external-schema.json")).toURI())); - } catch (Exception e) { - throw new RuntimeException(e); - } + return getTestDocument("/client-side-encryption-external/external-schema.json"); } private static BsonDocument externalKey() { - try { - return getTestDocument(new File(Assertions.assertNotNull(AbstractClientSideEncryptionNotSpawnMongocryptdTest.class - .getResource("/client-side-encryption-external/external-key.json")).toURI())); - } catch (Exception e) { - throw new RuntimeException(e); - } + return getTestDocument("/client-side-encryption-external/external-key.json"); } @SafeVarargs diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionRangeExplicitEncryptionTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionRangeExplicitEncryptionTest.java index be667c9b64c..df3affc9df0 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionRangeExplicitEncryptionTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionRangeExplicitEncryptionTest.java @@ -51,7 +51,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -70,7 +69,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static util.JsonPoweredTestHelper.getTestDocument; @@ -96,8 +94,8 @@ public void setUp(final Type type) { assumeFalse(isServerlessTest()); MongoNamespace dataKeysNamespace = new MongoNamespace("keyvault.datakeys"); - BsonDocument encryptedFields = bsonDocumentFromPath("range-encryptedFields-" + type.value + ".json"); - BsonDocument key1Document = bsonDocumentFromPath("keys/key1-document.json"); + BsonDocument encryptedFields = getTestDocument("/client-side-encryption-data/range-encryptedFields-" + type.value + ".json"); + BsonDocument key1Document = getTestDocument("/client-side-encryption-data/keys/key1-document.json"); key1Id = key1Document.getBinary("_id"); MongoDatabase explicitEncryptionDatabase = getDefaultDatabase(); @@ -354,15 +352,4 @@ BsonValue convertNumber(final int number) { } } } - - private static BsonDocument bsonDocumentFromPath(final String path) { - try { - return getTestDocument(new File(AbstractClientSideEncryptionRangeExplicitEncryptionTest.class - .getResource("/client-side-encryption-data/" + path).toURI())); - } catch (Exception e) { - fail("Unable to load resource", e); - return null; - } - } - } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionTest.java index dca25078b7c..f130e004cca 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideEncryptionTest.java @@ -44,9 +44,6 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -403,14 +400,15 @@ private void assertBsonValue(final String message, final BsonValue expectedResul } @Parameterized.Parameters(name = "{0}: {1}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/client-side-encryption/legacy")) { - BsonDocument specDocument = JsonPoweredTestHelper.getTestDocument(file); + for (BsonDocument specDocument : JsonPoweredTestHelper.getTestDocuments("/client-side-encryption/legacy")) { for (BsonValue test : specDocument.getArray("tests")) { - data.add(new Object[]{file.getName(), test.asDocument().getString("description").getValue(), specDocument, - specDocument.getArray("data", new BsonArray()), test.asDocument(), - skipTest(specDocument, test.asDocument())}); + BsonDocument testDocument = test.asDocument(); + data.add(new Object[]{specDocument.getString("fileName").getValue(), + testDocument.getString("description").getValue(), specDocument, + specDocument.getArray("data", new BsonArray()), testDocument, + skipTest(specDocument, testDocument)}); } } return data; diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryption25LookupProseTests.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryption25LookupProseTests.java index f7c672b289b..a6da323e715 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryption25LookupProseTests.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryption25LookupProseTests.java @@ -37,7 +37,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import java.io.File; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -52,7 +51,6 @@ import static com.mongodb.testing.MongoAssertions.assertCause; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static util.JsonPoweredTestHelper.getTestDocument; @@ -244,12 +242,6 @@ void testCase9() { } public static BsonDocument bsonDocumentFromPath(final String path) { - try { - return getTestDocument(new File(ClientSideEncryption25LookupProseTests.class - .getResource("/client-side-encryption-data/lookup/" + path).toURI())); - } catch (Exception e) { - fail("Unable to load resource", e); - return null; - } + return getTestDocument("/client-side-encryption-data/lookup/" + path); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionCorpusTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionCorpusTest.java index a812e174047..94e527544e5 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionCorpusTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionCorpusTest.java @@ -38,7 +38,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.Base64; @@ -261,9 +260,8 @@ public void testCorpus() throws IOException, URISyntaxException { } } - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionTest.class - .getResource("/client-side-encryption-corpus/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-corpus/" + path); } @Parameterized.Parameters(name = "useLocalSchema: {0}") diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionExternalKeyVaultTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionExternalKeyVaultTest.java index da513bb2a9e..4e056b93209 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionExternalKeyVaultTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionExternalKeyVaultTest.java @@ -37,7 +37,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.Arrays; @@ -146,9 +145,8 @@ public void testExternal() { assertEquals(authExceptionThrown, withExternalKeyVault); } - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionExternalKeyVaultTest.class - .getResource("/client-side-encryption-external/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-external/" + path); } @Parameterized.Parameters(name = "withExternalKeyVault: {0}") diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionSessionTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionSessionTest.java index f2c51988bd7..7d8cc943d22 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionSessionTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideEncryptionSessionTest.java @@ -30,7 +30,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.Arrays; @@ -143,9 +142,7 @@ public void testWithExplicitSession() { assertEquals(6, encryptedDocument.getBinary("encrypted").getType()); } - - private static BsonDocument bsonDocumentFromPath(final String path) throws IOException, URISyntaxException { - return getTestDocument(new File(ClientSideEncryptionSessionTest.class - .getResource("/client-side-encryption-external/" + path).toURI())); + private static BsonDocument bsonDocumentFromPath(final String path) { + return getTestDocument("/client-side-encryption-external/" + path); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java index c4068375f9f..b39920682cc 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java @@ -20,8 +20,6 @@ import com.mongodb.client.unified.UnifiedSyncTest; import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; import static org.junit.jupiter.api.Assumptions.assumeFalse; @@ -30,7 +28,7 @@ // See https://github.com/mongodb/specifications/tree/master/source/client-side-operation-timeout/tests public class ClientSideOperationTimeoutTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/client-side-operation-timeout"); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/InitialDnsSeedlistDiscoveryTest.java b/driver-sync/src/test/functional/com/mongodb/client/InitialDnsSeedlistDiscoveryTest.java index a51f6e3624d..091d876201c 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/InitialDnsSeedlistDiscoveryTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/InitialDnsSeedlistDiscoveryTest.java @@ -41,10 +41,6 @@ import org.junit.runners.Parameterized; import util.JsonPoweredTestHelper; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -69,7 +65,7 @@ // See https://github.com/mongodb/specifications/tree/master/source/initial-dns-seedlist-discovery/tests @RunWith(Parameterized.class) public abstract class InitialDnsSeedlistDiscoveryTest { - private final Path parentDirectory; + private final String parentDirectory; private final String uri; @Nullable private final List seeds; @@ -84,7 +80,7 @@ public abstract class InitialDnsSeedlistDiscoveryTest { private final boolean isError; private final boolean executePingCommand; - public InitialDnsSeedlistDiscoveryTest(@SuppressWarnings("unused") final String filename, final Path parentDirectory, final String uri, + public InitialDnsSeedlistDiscoveryTest(@SuppressWarnings("unused") final String filename, final String parentDirectory, final String uri, @Nullable final List seeds, @Nullable final Integer numSeeds, @Nullable final List hosts, @Nullable final Integer numHosts, final BsonDocument options, final BsonDocument parsedOptions, @@ -306,13 +302,13 @@ private void assertParsedOptions(final ConnectionString connectionString) { @Parameterized.Parameters(name = "{0}") - public static Collection data() throws URISyntaxException, IOException { + public static Collection data() { List data = new ArrayList<>(); - for (File file : JsonPoweredTestHelper.getTestFiles("/initial-dns-seedlist-discovery")) { - BsonDocument testDocument = JsonPoweredTestHelper.getTestDocument(file); + for (BsonDocument testDocument : JsonPoweredTestHelper.getTestDocuments("/initial-dns-seedlist-discovery")) { + String resourcePath = testDocument.getString("resourcePath").getValue(); data.add(new Object[]{ - file.getName(), - file.toPath().getParent(), + testDocument.getString("fileName").getValue(), + resourcePath.substring(0, resourcePath.lastIndexOf("/")), testDocument.getString("uri").getValue(), toStringList(testDocument.getArray("seeds", null)), toInteger(testDocument.getNumber("numSeeds", null)), @@ -323,7 +319,6 @@ public static Collection data() throws URISyntaxException, IOException testDocument.getBoolean("error", BsonBoolean.FALSE).getValue(), testDocument.getBoolean("ping", BsonBoolean.TRUE).getValue() }); - } return data; } diff --git a/driver-sync/src/test/functional/com/mongodb/client/MongoClientSessionSpecification.groovy b/driver-sync/src/test/functional/com/mongodb/client/MongoClientSessionSpecification.groovy index fc688fec5df..a8596536e8e 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/MongoClientSessionSpecification.groovy +++ b/driver-sync/src/test/functional/com/mongodb/client/MongoClientSessionSpecification.groovy @@ -35,7 +35,7 @@ import org.bson.Document import org.bson.types.ObjectId import org.junit.Assert import spock.lang.IgnoreIf -import util.spock.annotations.Slow +import com.mongodb.spock.Slow import java.util.concurrent.TimeUnit diff --git a/driver-sync/src/test/functional/com/mongodb/client/SyncInitialDnsSeedlistDiscoveryTest.java b/driver-sync/src/test/functional/com/mongodb/client/SyncInitialDnsSeedlistDiscoveryTest.java index d3750434ea6..afe31d41d27 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/SyncInitialDnsSeedlistDiscoveryTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/SyncInitialDnsSeedlistDiscoveryTest.java @@ -19,11 +19,10 @@ import com.mongodb.MongoClientSettings; import org.bson.BsonDocument; -import java.nio.file.Path; import java.util.List; public class SyncInitialDnsSeedlistDiscoveryTest extends InitialDnsSeedlistDiscoveryTest { - public SyncInitialDnsSeedlistDiscoveryTest(final String filename, final Path parentDirectory, final String uri, + public SyncInitialDnsSeedlistDiscoveryTest(final String filename, final String parentDirectory, final String uri, final List seeds, final Integer numSeeds, final List hosts, final Integer numHosts, final BsonDocument options, final BsonDocument parsedOptions, final boolean isError, final boolean executePingCommand) { diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ChangeStreamsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ChangeStreamsTest.java index d07429fa479..db719bca0d7 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ChangeStreamsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ChangeStreamsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ChangeStreamsTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/change-streams"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ClientSideEncryptionTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ClientSideEncryptionTest.java index bbb232386dd..151f237afec 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ClientSideEncryptionTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ClientSideEncryptionTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ClientSideEncryptionTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/client-side-encryption"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/CollectionManagementTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/CollectionManagementTest.java index 1830fa24c9d..74df339951c 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/CollectionManagementTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/CollectionManagementTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class CollectionManagementTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/collection-management"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/CommandLoggingTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/CommandLoggingTest.java index 23302ebdd52..cbcab69f1c6 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/CommandLoggingTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/CommandLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class CommandLoggingTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/command-logging"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/CommandMonitoringTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/CommandMonitoringTest.java index c6148aaaef4..0d93cb47b7f 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/CommandMonitoringTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/CommandMonitoringTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public final class CommandMonitoringTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/command-monitoring"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ConnectionPoolLoggingTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ConnectionPoolLoggingTest.java index 6079f1931b7..b6ec522106d 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ConnectionPoolLoggingTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ConnectionPoolLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ConnectionPoolLoggingTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/connection-monitoring-and-pooling/logging"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/IndexManagmentTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/IndexManagmentTest.java index 382c5edb3a4..a8bcd07b782 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/IndexManagmentTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/IndexManagmentTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class IndexManagmentTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/index-management"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/LoadBalancerTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/LoadBalancerTest.java index eb70f5da4cf..4c00290e8b2 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/LoadBalancerTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/LoadBalancerTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class LoadBalancerTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/load-balancers"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ServerSelectionLoggingTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ServerSelectionLoggingTest.java index 2e932ba975f..7ef28e20609 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ServerSelectionLoggingTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ServerSelectionLoggingTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class ServerSelectionLoggingTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/server-selection/logging"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/SessionsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/SessionsTest.java index 33d851a38c9..49884fcf3fb 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/SessionsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/SessionsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class SessionsTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/sessions"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAtlasDataLakeTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAtlasDataLakeTest.java index 009a78d3d3f..82df14c7a62 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAtlasDataLakeTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAtlasDataLakeTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedAtlasDataLakeTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/atlas-data-lake-testing"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAuthTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAuthTest.java index 0471a9600c6..5f31133cc1b 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAuthTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedAuthTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedAuthTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/auth"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudTest.java index eaf7546bece..b6a250ed00c 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public final class UnifiedCrudTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/crud"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedGridFSTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedGridFSTest.java index baac34f4959..c35223c0dc1 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedGridFSTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedGridFSTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedGridFSTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/gridfs"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableReadsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableReadsTest.java index 9859bcc782e..a8b4ea08b19 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableReadsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableReadsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public final class UnifiedRetryableReadsTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/retryable-reads"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableWritesTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableWritesTest.java index 2397aeb8b0d..017f58f0b68 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableWritesTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedRetryableWritesTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public final class UnifiedRetryableWritesTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/retryable-writes"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java index a88fe334525..e6ddac1266b 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedServerDiscoveryAndMonitoringTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public final class UnifiedServerDiscoveryAndMonitoringTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/server-discovery-and-monitoring"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedSyncTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedSyncTest.java index afcc8e4f1a3..e206dcc138a 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedSyncTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedSyncTest.java @@ -28,8 +28,6 @@ import com.mongodb.lang.NonNull; import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; public abstract class UnifiedSyncTest extends UnifiedTest { @@ -52,7 +50,7 @@ protected ClientEncryption createClientEncryption(final MongoClient keyVaultClie } @NonNull - protected static Collection getTestData(final String directory) throws URISyntaxException, IOException { + protected static Collection getTestData(final String directory) { return getTestData(directory, false); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java index a437084ac1d..6f20c0b22a8 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java @@ -59,9 +59,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.opentest4j.TestAbortedException; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; @@ -98,8 +95,7 @@ import static org.junit.jupiter.api.Assumptions.abort; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static util.JsonPoweredTestHelper.getTestDocument; -import static util.JsonPoweredTestHelper.getTestFiles; +import static util.JsonPoweredTestHelper.getTestDocuments; @ExtendWith(AfterBeforeParameterResolver.class) public abstract class UnifiedTest { @@ -165,11 +161,9 @@ public Entities getEntities() { } @NonNull - protected static Collection getTestData(final String directory, final boolean isReactive) - throws URISyntaxException, IOException { + protected static Collection getTestData(final String directory, final boolean isReactive) { List data = new ArrayList<>(); - for (File file : getTestFiles("/" + directory + "/")) { - BsonDocument fileDocument = getTestDocument(file); + for (BsonDocument fileDocument : getTestDocuments("/" + directory + "/")) { for (BsonValue cur : fileDocument.getArray("tests")) { final BsonDocument testDocument = cur.asDocument(); diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestFailureValidator.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestFailureValidator.java index 0472ef8e6ce..9a6e307cfa3 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestFailureValidator.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestFailureValidator.java @@ -24,8 +24,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -101,7 +99,7 @@ public void shouldPassAllOutcomes( assertNotNull(exception, "Expected exception but not was thrown"); } - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/valid-fail"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestValidator.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestValidator.java index 414d161677d..13822b7a57f 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestValidator.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTestValidator.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedTestValidator extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/valid-pass"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java index cf95ba9795a..5fd5fe6c8c2 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedTransactionsTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/transactions"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedWriteConcernTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedWriteConcernTest.java index 4d1a5a2f854..124958b23d8 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedWriteConcernTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedWriteConcernTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class UnifiedWriteConcernTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/write-concern"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/VersionedApiTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/VersionedApiTest.java index e9ccd4d1cd4..95b23da9ce7 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/VersionedApiTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/VersionedApiTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class VersionedApiTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("versioned-api"); } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/WithTransactionHelperTransactionsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/WithTransactionHelperTransactionsTest.java index d9fb4c9b4df..012e935d333 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/WithTransactionHelperTransactionsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/WithTransactionHelperTransactionsTest.java @@ -18,12 +18,10 @@ import org.junit.jupiter.params.provider.Arguments; -import java.io.IOException; -import java.net.URISyntaxException; import java.util.Collection; final class WithTransactionHelperTransactionsTest extends UnifiedSyncTest { - private static Collection data() throws URISyntaxException, IOException { + private static Collection data() { return getTestData("unified-test-format/transactions-convenient-api"); } } diff --git a/driver-workload-executor/build.gradle b/driver-workload-executor/build.gradle.kts similarity index 53% rename from driver-workload-executor/build.gradle rename to driver-workload-executor/build.gradle.kts index 8885e1fd59c..2cb5f2e1073 100644 --- a/driver-workload-executor/build.gradle +++ b/driver-workload-executor/build.gradle.kts @@ -15,38 +15,43 @@ */ plugins { - id("java") id("application") - alias(libs.plugins.shadow) + id("java-library") + id("project.base") + id("conventions.test-artifacts") } -mainClassName = "com.mongodb.workload.WorkloadExecutor" +application { + mainClass = "com.mongodb.workload.WorkloadExecutor" +} sourceSets { main { - java { - srcDir 'src/main' - } - resources { - srcDir 'src/resources' - } + java { setSrcDirs(listOf("src/main")) } + resources { setSrcDirs(listOf("src/resources")) } } } dependencies { - implementation project(':driver-sync') - implementation project(':driver-core').sourceSets.test.output - implementation project(':driver-sync').sourceSets.test.output + implementation(project(":driver-sync")) + implementation(project(path = ":driver-core", configuration = "testArtifacts")) + implementation(project(path = ":driver-sync", configuration = "testArtifacts")) implementation(platform(libs.junit.bom)) implementation(libs.bundles.junit.vintage) } -javadoc { +tasks.withType().configureEach { enabled = false } -jar { +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + + +tasks.withType { manifest { - attributes "Main-Class": "com.mongodb.workload.WorkloadExecutor" + attributes["Main-Class"] = "com.mongodb.workload.WorkloadExecutor" } } diff --git a/graalvm-native-image-app/build.gradle b/graalvm-native-image-app/build.gradle deleted file mode 100644 index e9a2c0433bb..00000000000 --- a/graalvm-native-image-app/build.gradle +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -// Note requires a Gradle project flag `-PincludeGraalvm` (see settings.gradle). - -plugins { - id("application") - alias(libs.plugins.graalvm.buildtools) -} - -application { - mainClass = 'com.mongodb.internal.graalvm.NativeImageApp' -} - -def systemPropertiesForRunningNativeApp = System.getProperties().findAll { it.key.toString().startsWith("org.mongodb.") } -tasks.matching { it.name == 'run' }.configureEach { - systemProperties(systemPropertiesForRunningNativeApp) -} - -// see https://graalvm.github.io/native-build-tools/latest/gradle-plugin.html -graalvmNative { - metadataRepository { - enabled = false - } - agent { - // Executing the `run` Gradle task with the tracing agent - // https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/ - // requires running Gradle with GraalVM despite the toolchain for the task already being GraalVM. - // The same is true about executing the `metadataCopy` Gradle task. - // This may be a manifestation of an issue with the `org.graalvm.buildtools.native` plugin. - enabled = false - defaultMode = 'direct' - def taskExecutedWithAgentAttached = 'run' - modes { - direct { - // see https://www.graalvm.org/latest/reference-manual/native-image/metadata/ExperimentalAgentOptions - options.add("config-output-dir=$buildDir/native/agent-output/$taskExecutedWithAgentAttached") - // `experimental-configuration-with-origins` produces - // `graalvm-native-image-app/build/native/agent-output/run/reflect-origins.txt` - // and similar files that explain the origin of each of the reachability metadata piece. - // However, for some reason, the actual reachability metadata is not generated when this option is enabled, - // so enable it manually if you need an explanation for a specific reachability metadata entry, - // and expect the build to fail. - // options.add('experimental-configuration-with-origins') - - // `experimental-class-define-support` does not seem to do what it is supposed to do. - // We need this option to work if we want to support `UnixServerAddress` in native image. - // Unfortunately, the tracing agent neither generates the metadata in - // `graalvm-native-image-app/src/main/resources/META-INF/native-image/proxy-config.json`, - // nor does it extract the bytecode of the generated classes to - // `graalvm-native-image-app/src/main/resources/META-INF/native-image/agent-extracted-predefined-classes`. - options.add('experimental-class-define-support') - } - } - metadataCopy { - inputTaskNames.add(taskExecutedWithAgentAttached) - outputDirectories.add('src/main/resources/META-INF/native-image') - mergeWithExisting = false - } - } - binaries { - configureEach { - buildArgs.add('--strict-image-heap') - buildArgs.add('-H:+UnlockExperimentalVMOptions') - // see class initialization and other reports in `graalvm/build/native/nativeCompile/reports` - buildArgs.add('--diagnostics-mode') - // see the "registerResource" entries in the `native-image` built-time output, - // informing us on the resources included in the native image being built - buildArgs.add('-H:Log=registerResource:5') - } - main { - sharedLibrary = false - def mainClassName = application.mainClass.get() - imageName = mainClassName.substring(mainClassName.lastIndexOf('.') + 1, mainClassName.length()) - runtimeArgs.addAll(systemPropertiesForRunningNativeApp.entrySet() - .stream() - .map {"-D${it.getKey()}=${it.getValue()}" } - .toList()) - quickBuild = true - // See the "Apply" entries in the `native-image` built-time output, informing us on - // the build configuration files (https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildConfiguration/) - // and the reachability metadata files (https://www.graalvm.org/latest/reference-manual/native-image/metadata/) - // which are applied at build time. - verbose = true - } - } -} - -dependencies { - // we intentionally depend here on the driver artifacts instead of depending on compiled classes - implementation project(path:':bson', configuration:'archives') - implementation project(path:':driver-core', configuration:'archives') - implementation project(path:':driver-sync', configuration:'archives') - implementation project(path:':driver-reactive-streams', configuration:'archives') - implementation project(path:':driver-legacy', configuration:'archives') - implementation project(path: ':mongodb-crypt', configuration: 'archives') - implementation project(path: ':mongodb-crypt', configuration: 'runtimeElements') - // note that as a result of these `sourceSets` dependencies, `driver-sync/src/test/resources/logback-test.xml` is used - implementation project(':driver-core').sourceSets.test.output - implementation project(':driver-sync').sourceSets.test.output - implementation project(':driver-legacy').sourceSets.test.output - implementation project(':driver-reactive-streams').sourceSets.test.output - - implementation(libs.slf4j) - implementation(libs.logback) - implementation(platform(libs.reactor.bom)) - implementation(libs.reactor.core) - implementation(libs.graal.sdk.native) -} diff --git a/graalvm-native-image-app/build.gradle.kts b/graalvm-native-image-app/build.gradle.kts new file mode 100644 index 00000000000..464c7711f20 --- /dev/null +++ b/graalvm-native-image-app/build.gradle.kts @@ -0,0 +1,185 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ + +// Note requires a Gradle project flag `-PincludeGraalvm` (see settings.gradle.kts). + +plugins { + id("application") + id("java-library") + id("project.base") + id("conventions.test-artifacts") + alias(libs.plugins.graalvm.buildtools) +} + +application { + mainClass = "com.mongodb.internal.graalvm.NativeImageApp" +} + +sourceSets { + main { + java { setSrcDirs(listOf("src/main")) } + resources { setSrcDirs(listOf("src/main/resources")) } + } +} + +dependencies { + // we intentionally depend here on the driver artifacts instead of depending on compiled classes + implementation(project(path = ":bson", configuration = "archives")) + implementation(project(path = ":driver-core", configuration = "archives")) + implementation(project(path = ":driver-sync", configuration = "archives")) + implementation(project(path = ":driver-legacy", configuration = "archives")) + implementation(project(path = ":driver-reactive-streams", configuration = "archives")) + implementation(project(path = ":mongodb-crypt", configuration = "archives")) + implementation(project(path = ":mongodb-crypt", configuration = "runtimeElements")) + + implementation(project(path = ":driver-core", configuration = "testArtifacts")) + implementation(project(path = ":driver-sync", configuration = "testArtifacts")) + implementation(project(path = ":driver-legacy", configuration = "testArtifacts")) + implementation(project(path = ":driver-reactive-streams", configuration = "testArtifacts")) + + implementation(libs.slf4j) + implementation(libs.jna) + implementation(libs.graal.sdk.nativeimage) + implementation(libs.jetbrains.annotations) + implementation(libs.logback.classic) + implementation(platform(libs.project.reactor.bom)) + implementation(libs.project.reactor.core) +} + +tasks.withType().configureEach { + enabled = false +} + + +@Suppress("UNCHECKED_CAST") +val systemPropertiesForRunningNativeApp: Map = (System.getProperties().toMap() as Map) + .filterKeys { it.startsWith("org.mongodb.") } +tasks.named("run") { systemProperties = systemPropertiesForRunningNativeApp } + +// see https://graalvm.github.io/native-build-tools/latest/gradle-plugin.html +graalvmNative { + metadataRepository { + enabled.set(false) + } + agent { + // Executing the `run` Gradle task with the tracing agent + // https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/ + // requires running Gradle with GraalVM despite the toolchain for the task already being GraalVM. + // The same is true about executing the `metadataCopy` Gradle task. + // This may be a manifestation of an issue with the `org.graalvm.buildtools.native` plugin. + enabled.set(false) + defaultMode.set("direct") + val taskExecutedWithAgentAttached = "run" + modes { + direct { + // see https://www.graalvm.org/latest/reference-manual/native-image/metadata/ExperimentalAgentOptions + options.add("config-output-dir=${rootProject.file("build/native/agent-output/$taskExecutedWithAgentAttached").path}") + // `experimental-configuration-with-origins` produces + // `graalvm-native-image-app/build/native/agent-output/run/reflect-origins.txt` + // and similar files that explain the origin of each of the reachability metadata piece. + // However, for some reason, the actual reachability metadata is not generated when this option is enabled, + // so enable it manually if you need an explanation for a specific reachability metadata entry, + // and expect the build to fail. + // options.add("experimental-configuration-with-origins") + + // `experimental-class-define-support` does not seem to do what it is supposed to do. + // We need this option to work if we want to support `UnixServerAddress` in native image. + // Unfortunately, the tracing agent neither generates the metadata in + // `graalvm-native-image-app/src/main/resources/META-INF/native-image/proxy-config.json`, + // nor does it extract the bytecode of the generated classes to + // `graalvm-native-image-app/src/main/resources/META-INF/native-image/agent-extracted-predefined-classes`. + options.add("experimental-class-define-support") + } + } + metadataCopy { + inputTaskNames.add(taskExecutedWithAgentAttached) + outputDirectories.add("src/main/resources/META-INF/native-image") + mergeWithExisting.set(false) + } + } + binaries { + configureEach { + buildArgs.add("--strict-image-heap") + buildArgs.add("-H:+UnlockExperimentalVMOptions") + // see class initialization and other reports in `graalvm/build/native/nativeCompile/reports` + buildArgs.add("--diagnostics-mode") + // see the "registerResource" entries in the `native-image` built-time output, + // informing us on the resources included in the native image being built + buildArgs.add("-H:Log=registerResource:5") + } + named("main") { + val mainClassName = application.mainClass.get() + imageName = mainClassName.substring(mainClassName.lastIndexOf('.') + 1) + sharedLibrary.set(false) + runtimeArgs.addAll(systemPropertiesForRunningNativeApp.entries + .stream() + .map {"-D${it.key}=${it.value}" } + .toList()) + quickBuild.set(true) + // See the "Apply" entries in the `native-image` built-time output, informing us on + // the build configuration files (https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildConfiguration/) + // and the reachability metadata files (https://www.graalvm.org/latest/reference-manual/native-image/metadata/) + // which are applied at build time. + verbose.set(true) + } + } +} + +// By configuring the toolchains for the `org.graalvm.buildtools.native` plugin +// conditionally, we avoid Gradle errors caused by it failing to locate an installed GraalVM +// for Java SE older than 21. One situation when this is relevant is building from an IDE, +// where the `DEFAULT_JDK_VERSION` is likely used. +val minRequiredGraalVMJavaVersion = 21 +val graalJavaVersion: Int = findProperty("javaVersion")?.toString()?.toInt() ?: minRequiredGraalVMJavaVersion +val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(graalJavaVersion) + +if (graalJavaVersion >= minRequiredGraalVMJavaVersion) { + // `JvmVendorSpec.GRAAL_VM` matches only GraalVM Community (https://github.com/graalvm/graalvm-ce-builds/releases), + // and does not match any other GraalVM distribution. + // That is, Gradle fails to locate any other installed distribution of GraalVM. + // Furthermore, there is no other way to express via the Gradle toolchain functionality + // that GraalVM must be used. The documentation of the `org.graalvm.buildtools.native` plugin + // says the following about this limitation: + // "be aware that the toolchain detection cannot distinguish between GraalVM JDKs + // and standard JDKs without Native Image support: + // if you have both installed on the machine, Gradle may randomly pick one or the other". + // Fortunately, `JvmVendorSpec.GRAAL_VM` makes things less hideous than that. + // + // The documentation of the `org.graalvm.buildtools.native` plugin mentions + // the environment variable `GRAALVM_HOME` as an alternative to Gradle toolchain functionality. + // I was unable to find a way to stop relying on the toolchain specification requiring `JvmVendorSpec.GRAAL_VM` + // even with `GRAALVM_HOME`. + val graalVendor = JvmVendorSpec.GRAAL_VM + graalvmNative { + agent { + java { + toolchain { + // TODO - errors saying its immutable. + // languageVersion.set(javaLanguageVersion) + // vendor.set(graalVendor) + } + } + } + binaries { + configureEach { + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(javaLanguageVersion) + vendor.set(graalVendor) + }) + } + } + } +} diff --git a/graalvm-native-image-app/src/main/com/mongodb/internal/graalvm/NativeImageApp.java b/graalvm-native-image-app/src/main/com/mongodb/internal/graalvm/NativeImageApp.java index 59778d7686f..400a1131108 100644 --- a/graalvm-native-image-app/src/main/com/mongodb/internal/graalvm/NativeImageApp.java +++ b/graalvm-native-image-app/src/main/com/mongodb/internal/graalvm/NativeImageApp.java @@ -18,7 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; import java.util.Objects; diff --git a/graalvm-native-image-app/src/main/resources/META-INF/native-image/resource-config.json b/graalvm-native-image-app/src/main/resources/META-INF/native-image/resource-config.json index d4bf7ea12ff..3727b46aaff 100644 --- a/graalvm-native-image-app/src/main/resources/META-INF/native-image/resource-config.json +++ b/graalvm-native-image-app/src/main/resources/META-INF/native-image/resource-config.json @@ -44,12 +44,6 @@ "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" - }, { - "pattern":"\\Qlogback-test.scmo\\E" - }, { - "pattern":"\\Qlogback-test.xml\\E" - }, { - "pattern":"\\Qlogback.scmo\\E" }, { "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E" }]}, diff --git a/gradle.properties b/gradle.properties index d3514e32f68..566ffaf4efd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,11 +14,13 @@ # limitations under the License. # +version=5.4.0-SNAPSHOT + org.gradle.daemon=true -org.gradle.jvmargs=-Duser.country=US -Duser.language=en +org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en ## NOTE: This property is also used to generate scala compile versions in BOM. -scalaVersions=2.11.12,2.12.20,2.13.15 -defaultScalaVersions=2.13.15 +supportedScalaVersions=2.13,2.12,2.11 +defaultScalaVersion=2.13 runOnceTasks=clean,release org.gradle.java.installations.auto-download=false org.gradle.java.installations.fromEnv=JDK8,JDK11,JDK17,JDK21,JDK21_GRAALVM diff --git a/gradle/deploy.gradle b/gradle/deploy.gradle deleted file mode 100644 index c34f7bf9b71..00000000000 --- a/gradle/deploy.gradle +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -def utilProjects = project(":util").allprojects -def deployedProjects = subprojects - utilProjects - -configure(deployedProjects) { - - def isScala = project.name.contains('scala') - def hasAllScalaVersions = project.hasProperty('allScalaVersions') - def isInvalidScalaProject = false // isScala && !hasAllScalaVersions // TODO JAVA-3564 - - task publishSnapshots { - group = 'publishing' - description = 'Publishes snapshots to Sonatype' - - if ( version.endsWith('-SNAPSHOT')) { - if (isInvalidScalaProject) { - doFirst { - def cause = """ - | Not publishing all Scala versions: - | ================================= - | - | You must set the -PallScalaVersions flag when publishing - |""".stripMargin() - throw new GradleException(cause) - } - } else { - dependsOn tasks.withType(PublishToMavenRepository) - } - } - } - - task publishArchives { - group = 'publishing' - description = 'Publishes a release and uploads to Sonatype / Maven Central' - - def gitVersionMatch = project.gitVersion == version - - doFirst { - if (!gitVersionMatch) { - def cause = """ - | Version mismatch: - | ================= - | - | $version != $gitVersion - | - | The project version does not match the git tag. - |""".stripMargin() - throw new GradleException(cause) - } else if (isInvalidScalaProject) { - def cause = """ - | Not publishing all Scala versions: - | ================================= - | - | You must set the -PallScalaVersions flag when publishing - |""".stripMargin() - throw new GradleException(cause) - } else { - println("Publishing: ${project.name} : ${project.gitVersion}") - } - } - if (gitVersionMatch && !isInvalidScalaProject) { - dependsOn tasks.withType(PublishToMavenRepository) - } - } -} diff --git a/gradle/javaToolchain.gradle b/gradle/javaToolchain.gradle deleted file mode 100644 index f1c779dab33..00000000000 --- a/gradle/javaToolchain.gradle +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ -final Integer DEFAULT_JDK_VERSION = 17 - -def javaMainProjects = subprojects - project(":util:taglets") - -allprojects { - - def javaVersion = (findProperty("javaVersion") ?: DEFAULT_JDK_VERSION.toString()).toInteger() - project.pluginManager.withPlugin("java") { - if (!project.pluginManager.hasPlugin("scala")) { - logger.info("Compiling ${project.name} using JDK${DEFAULT_JDK_VERSION}") - java { - toolchain { - languageVersion = JavaLanguageVersion.of(DEFAULT_JDK_VERSION) - } - } - } - } - project.pluginManager.withPlugin('org.graalvm.buildtools.native') { - def minRequiredGraalVMJavaVersion = 21 - // By configuring the toolchains for the `org.graalvm.buildtools.native` plugin - // conditionally, we avoid Gradle errors caused by it failing to locate an installed GraalVM - // for Java SE older than 21. One situation when this is relevant is building from an IDE, - // where the `DEFAULT_JDK_VERSION` is likely used. - if (javaVersion >= minRequiredGraalVMJavaVersion) { - def javaLanguageVersion = JavaLanguageVersion.of(javaVersion) - // `JvmVendorSpec.GRAAL_VM` matches only GraalVM Community (https://github.com/graalvm/graalvm-ce-builds/releases), - // and does not match any other GraalVM distribution. - // That is, Gradle fails to locate any other installed distribution of GraalVM. - // Furthermore, there is no other way to express via the Gradle toolchain functionality - // that GraalVM must be used. The documentation of the `org.graalvm.buildtools.native` plugin - // says the following about this limitation: - // "be aware that the toolchain detection cannot distinguish between GraalVM JDKs - // and standard JDKs without Native Image support: - // if you have both installed on the machine, Gradle may randomly pick one or the other". - // Fortunately, `JvmVendorSpec.GRAAL_VM` makes things less hideous than that. - // - // The documentation of the `org.graalvm.buildtools.native` plugin mentions - // the environment variable `GRAALVM_HOME` as an alternative to Gradle toolchain functionality. - // I was unable to find a way to stop relying on the toolchain specification requiring `JvmVendorSpec.GRAAL_VM` - // even with `GRAALVM_HOME`. - def graalVendor = JvmVendorSpec.GRAAL_VM - graalvmNative { - agent { - java { - toolchain { - languageVersion = javaLanguageVersion - vendor = graalVendor - } - } - } - binaries { - configureEach { - javaLauncher = javaToolchains.launcherFor { - languageVersion = javaLanguageVersion - vendor = graalVendor - } - } - } - } - } - } - - if (project == project(":bson-record-codec")) { - tasks.withType(JavaCompile) { - options.encoding = "UTF-8" - options.release.set(17) - } - } else if (project.name == 'graalvm-native-image-app') { - tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' - options.release.set(DEFAULT_JDK_VERSION) - } - } else if (project in javaMainProjects) { - tasks.withType(JavaCompile) { - options.encoding = "UTF-8" - options.release.set(8) - } - - // Work around for: https://github.com/gradle/gradle/issues/15703 - tasks.withType(GroovyCompile) { - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - } - } - - tasks.withType(Test) { - javaLauncher.set(javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(javaVersion) - }) - } - -} diff --git a/gradle/javadoc.gradle b/gradle/javadoc.gradle deleted file mode 100644 index b986747c647..00000000000 --- a/gradle/javadoc.gradle +++ /dev/null @@ -1,120 +0,0 @@ -import static org.gradle.util.CollectionUtils.single - -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - - -def projectNamesThatDoNotPublishJavaDocs =["driver-benchmarks", "driver-lambda", "driver-workload-executor", "graalvm-native-image-app", "util", - "spock", "taglets"] -def javaMainProjects = subprojects.findAll { !projectNamesThatDoNotPublishJavaDocs.contains(it.name) } - -task docs { - dependsOn javaMainProjects.collect { it.tasks.withType(Javadoc) + it.tasks.withType(ScalaDoc) } -} - -def buildDocsUrl(String version, String packageName) { - def docVersion = version.split('-').head() - def (major, minor, patch) = docVersion.split('\\.') - - docVersion = "${major}.${minor}" - if (version.contains("-SNAPSHOT") && patch == 0) { - // If a snapshot of the next minor version, set the version to the previous released version - docVersion = minor > 0 ? "${major}.${minor - 1}" : '4.0' - } - - ["http://mongodb.github.io/mongo-java-driver/${docVersion}/apidocs/${packageName}/", "${rootProject.buildDir.path}/docs/${packageName}"] -} - -def tagletsProject = project(':util:taglets') -subprojects { project -> - if (project in javaMainProjects) { - - tasks.withType(Javadoc) { - dependsOn tagletsProject.compileJava //We need taglets to be compiled - exclude "**/com/mongodb/**/benchmark/**" - exclude "**/com/mongodb/**/assertions/**" - exclude "**/com/mongodb/**/internal/**" - exclude "**/org/bson/**/internal/**" - options { - author = true - version = true - links = ['https://docs.oracle.com/en/java/javase/11/docs/api/', - 'https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/'] - tagletPath tagletsProject.sourceSets.main.output.classesDirs.head() - taglets 'AtlasManualTaglet' - taglets 'ManualTaglet' - taglets 'DochubTaglet' - taglets 'ServerReleaseTaglet' - encoding = 'UTF-8' - charSet 'UTF-8' - docEncoding 'UTF-8' - addBooleanOption("html5", true) - addBooleanOption("-allow-script-in-comments", true) - header = ''' - | '''.stripMargin() - } - - afterEvaluate { - destinationDir = new File(rootDir, "build/docs/${project.archivesBaseName}") - def version = project.version as String - if (project.name != 'bson') { - options.linksOffline(*buildDocsUrl(version, 'bson')) - if (project.name != 'driver-core') options.linksOffline(*buildDocsUrl(version, 'mongodb-driver-core')) - if (project.name == 'driver-legacy') { - dependsOn javaMainProjects.find({ it.name == 'driver-sync' }).javadoc - options.linksOffline(*buildDocsUrl(version, 'mongodb-driver-sync')) - } - } - } - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 35b5c93a17b..8dac391dcd5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,13 +23,16 @@ project-reactor-bom = "2022.0.0" reactive-streams = "1.0.4" snappy = "1.1.10.3" zstd = "1.5.5-3" +jetbrains-annotations = "26.0.2" kotlin = "1.8.10" kotlinx-coroutines-bom = "1.6.4" kotlinx-datetime = "0.4.0" kotlinx-serialization = "1.5.0" -scala = "%scala-version%" # Handled by the scala multiversion plugin +scala-v2-v13 = "2.13.16" +scala-v2-v12 = "2.12.20" +scala-v2-v11 = "2.11.12" # Test assertj = "3.24.2" @@ -48,10 +51,10 @@ mockito-java8 = "4.6.1" mockito-kotlin = "4.1.0" objenesis = "1.3" reflections = "0.9.10" -scalatest = "3.2.9" -scalatest-plus = "3.2.10.0" slf4j = "1.7.6" spock-bom = "2.1-groovy-3.0" +scala-test = "3.2.18" +scala-test-plus = "3.2.18.0" # Plugins plugin-bnd = "5.1.2" @@ -61,11 +64,10 @@ plugin-dokka = "1.8.10" plugin-download = "5.6.0" plugin-graalvm = "0.9.23" plugin-optional-base = "7.0.0" -plugin-scala-multiversion = "2.0.4" -plugin-shadow = "6.1.0" +plugin-shadow = "8.3.6" plugin-spotbugs = "6.0.15" plugin-spotless = "6.14.0" -plugin-test-logger = "2.1.0" +plugin-test-logger = "4.0.0" [libraries] aws-java-sdk-v1-core = { module = "com.amazonaws:aws-java-sdk-core", version.ref = "aws-sdk-v1" } @@ -74,7 +76,9 @@ aws-java-sdk-v2-auth = { module = "software.amazon.awssdk:auth", version.ref = " aws-java-sdk-v2-sts = { module = "software.amazon.awssdk:sts", version.ref = "aws-sdk-v2" } jna = { module = "net.java.dev.jna:jna", version.ref = "jna" } +jna-platform = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" } jnr-unixsocket = { module = "com.github.jnr:jnr-unixsocket", version.ref = "jnr-unixsocket" } +jetbrains-annotations = {module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" } netty-bom = { module = "io.netty:netty-bom", version.ref = "netty-bom" } netty-buffer = { module = "io.netty:netty-buffer" } @@ -90,7 +94,7 @@ snappy-java = { module = "org.xerial.snappy:snappy-java", version.ref = "snappy" zstd-jni = { module = "com.github.luben:zstd-jni", version.ref = "zstd" } graal-sdk = { module = "org.graalvm.sdk:graal-sdk", version.ref = "graal-sdk" } -graal-sdk-native = { module = "org.graalvm.sdk:native", version.ref = "graal-sdk" } +graal-sdk-nativeimage = { module = "org.graalvm.sdk:nativeimage", version.ref = "graal-sdk" } kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom" } kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } @@ -103,8 +107,14 @@ kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serializa kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } kotlinx-serialization-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } -scala-library = {module = "org.scala-lang:scala-library", version.ref = "scala" } -scala-reflect = {module = "org.scala-lang:scala-reflect", version.ref = "scala" } +scala-library-v2-v13 = { module = "org.scala-lang:scala-library", version.ref = "scala-v2-v13" } +scala-reflect-v2-v13 = { module = "org.scala-lang:scala-reflect", version.ref = "scala-v2-v13" } + +scala-library-v2-v12 = { module = "org.scala-lang:scala-library", version.ref = "scala-v2-v12" } +scala-reflect-v2-v12 = { module = "org.scala-lang:scala-reflect", version.ref = "scala-v2-v12" } + +scala-library-v2-v11 = { module = "org.scala-lang:scala-library", version.ref = "scala-v2-v11" } +scala-reflect-v2-v11 = { module = "org.scala-lang:scala-reflect", version.ref = "scala-v2-v11" } # Test jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh"} @@ -115,7 +125,7 @@ junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params" } junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" } junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine" } -junit-kotlin = { module = "org.jetbrains.kotlin:kotlin-test-junit" } +junit-kotlin = { module = "org.jetbrains.kotlin:kotlin-test-junit5" } spock-bom = { module = "org.spockframework:spock-bom", version.ref = "spock-bom" } spock-core = { module = "org.spockframework:spock-core" } @@ -128,10 +138,21 @@ mockito-core-java8 = { module = "org.mockito:mockito-core", version.ref = "mocki mockito-inline-java8 = { module = "org.mockito:mockito-inline", version.ref = "mockito-java8" } mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockito-kotlin" } -scalatest-flatspec = { module = "org.scalatest:scalatest-flatspec_%%", version.ref = "scalatest" } -scalatest-should-matchers = { module = "org.scalatest:scalatest-shouldmatchers_%%", version.ref = "scalatest" } -scalatest-plus-junit4 = { module = "org.scalatestplus:junit-4-13_%%", version.ref = "scalatest-plus" } -scalatest-plus-mockito = { module = "org.scalatestplus:mockito-3-12_%%", version.ref = "scalatest-plus" } + +scala-test-flatspec-v2-v13 = { module = "org.scalatest:scalatest-flatspec_2.13", version.ref = "scala-test" } +scala-test-shouldmatchers-v2-v13 = { module = "org.scalatest:scalatest-shouldmatchers_2.13", version.ref = "scala-test" } +scala-test-mockito-v2-v13 = { module = "org.scalatestplus:mockito-4-11_2.13", version.ref = "scala-test-plus" } +scala-test-junit-runner-v2-v13 = { module = "org.scalatestplus:junit-5-10_2.13", version.ref = "scala-test-plus" } + +scala-test-flatspec-v2-v12 = { module = "org.scalatest:scalatest-flatspec_2.12", version.ref = "scala-test" } +scala-test-shouldmatchers-v2-v12 = { module = "org.scalatest:scalatest-shouldmatchers_2.12", version.ref = "scala-test" } +scala-test-mockito-v2-v12 = { module = "org.scalatestplus:mockito-4-11_2.12", version.ref = "scala-test-plus" } +scala-test-junit-runner-v2-v12 = { module = "org.scalatestplus:junit-5-10_2.12", version.ref = "scala-test-plus" } + +scala-test-flatspec-v2-v11 = { module = "org.scalatest:scalatest-flatspec_2.11", version.ref = "scala-test" } +scala-test-shouldmatchers-v2-v11 = { module = "org.scalatest:scalatest-shouldmatchers_2.11", version.ref = "scala-test" } +scala-test-mockito-v2-v11 = { module = "org.scalatestplus:mockito-4-11_2.11", version.ref = "scala-test-plus" } +scala-test-junit-runner-v2-v11 = { module = "org.scalatestplus:junit-5-10_2.11", version.ref = "scala-test-plus" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test" } @@ -144,28 +165,40 @@ findbugs-jsr = { module = "com.google.code.findbugs:jsr305", version.ref = "find groovy = { module = "org.codehaus.groovy:groovy-all", version.ref = "groovy" } hamcrest-all = { module = "org.hamcrest:hamcrest-all", version.ref = "hamcrest" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } -netty-boringssl = { module = "io.netty:netty-tcnative-boringssl-static" } +netty-tcnative-boringssl = { module = "io.netty:netty-tcnative-boringssl-static" } objenesis = { module = "org.objenesis:objenesis", version.ref = "objenesis" } project-reactor-test = { module = "io.projectreactor:reactor-test" } reactive-streams-tck = { module = " org.reactivestreams:reactive-streams-tck", version.ref = "reactive-streams" } reflections = { module = "org.reflections:reflections", version.ref = "reflections" } + [bundles] aws-java-sdk-v1 = ["aws-java-sdk-v1-core", "aws-java-sdk-v1-sts"] aws-java-sdk-v2 = ["aws-java-sdk-v2-auth", "aws-java-sdk-v2-sts"] netty = ["netty-buffer", "netty-handler", "netty-transport"] +scala-v2-v13 = ["scala-library-v2-v13", "scala-reflect-v2-v13"] +scala-v2-v12 = ["scala-library-v2-v12", "scala-reflect-v2-v12"] +scala-v2-v11 = ["scala-library-v2-v11", "scala-reflect-v2-v11"] + # Test -junit = ["junit-jupiter", "junit-jupiter-params", "junit-jupiter-engine", "junit-jupiter", "logback-classic", "hamcrest-all"] -junit-vintage = ["junit-vintage-engine", "junit-jupiter-params", "junit-jupiter-engine", "junit-jupiter", "logback-classic", "hamcrest-all"] -scalatest = ["scalatest-flatspec", "scalatest-should-matchers", "scalatest-plus-junit4", "scalatest-plus-mockito"] +junit = ["junit-jupiter", "junit-jupiter-params", "junit-jupiter-engine", "logback-classic", "hamcrest-all"] +junit-vintage = ["junit-vintage-engine", "junit-jupiter-params", "junit-jupiter-engine", "logback-classic", "hamcrest-all"] spock = ["spock-core", "spock-junit4"] mockito = ["mockito-junit-jupiter", "mockito-core"] mockito-java8 = ["mockito-junit-jupiter-java8", "mockito-core-java8", "mockito-inline-java8"] mockito-kotlin = ["mockito-kotlin", "mockito-junit-jupiter-java8"] +scala-test-v2-v13 = ["scala-test-flatspec-v2-v13", "scala-test-shouldmatchers-v2-v13", "scala-test-mockito-v2-v13", + "scala-test-junit-runner-v2-v13", "reflections"] +scala-test-v2-v12 = ["scala-test-flatspec-v2-v12", "scala-test-shouldmatchers-v2-v12", "scala-test-mockito-v2-v12", + "scala-test-junit-runner-v2-v12", "reflections"] +scala-test-v2-v11 = ["scala-test-flatspec-v2-v11", "scala-test-shouldmatchers-v2-v11", "scala-test-mockito-v2-v11", + "scala-test-junit-runner-v2-v11", "reflections"] + [plugins] +kotlin-gradle = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } bnd = { id = "biz.aQute.bnd", version.ref = "plugin-bnd" } build-config = { id = "com.github.gmazzo.buildconfig", version.ref = "plugin-build-config" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "plugin-detekt" } @@ -175,8 +208,7 @@ graalvm-buildtools = { id = "org.graalvm.buildtools.native", version.ref = "plug kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } optional = { id = "nebula.optional-base", version.ref = "plugin-optional-base" } -scala-multiversion = { id = "com.adtran.scala-multiversion-plugin", version.ref = "plugin-scala-multiversion" } -shadow = { id = "com.github.johnrengelman.shadow", version.ref = "plugin-shadow" } +shadow = { id = "com.gradleup.shadow", version.ref = "plugin-shadow" } spotbugs = { id = "com.github.spotbugs", version.ref = "plugin-spotbugs" } spotless = { id = "com.diffplug.spotless", version.ref = "plugin-spotless" } test-logger = { id = "com.adarshr.test-logger", version.ref = "plugin-test-logger" } diff --git a/gradle/publish.gradle b/gradle/publish.gradle deleted file mode 100644 index fa56f09f138..00000000000 --- a/gradle/publish.gradle +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -/** - * Configures publishing of the main java projects - */ - -// Publishing helpers -ext { - configurePom = { project -> - { -> - name = project.hasProperty('pomName') ? project.getProperty('pomName') : project.name - description = project.description - url = project.hasProperty('pomURL') ? project.getProperty('pomURL') : 'https://www.mongodb.com/' - licenses { - license { - name = 'The Apache License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - scm { - url = 'https://github.com/mongodb/mongo-java-driver' - connection = 'scm:https://github.com/mongodb/mongo-java-driver.git' - developerConnection = 'scm:git@github.com:mongodb/mongo-java-driver.git' - } - developers { - developer { - name = 'Various' - organization = 'MongoDB' - } - } - } - } - configureMavenRepositories = { project -> - { -> - def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' - def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - maven { - url = project.version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username project.hasProperty('nexusUsername') ? project.getProperty('nexusUsername') : '' - password project.hasProperty('nexusPassword') ? project.getProperty('nexusPassword') : '' - } - } - - maven { - url = "$rootDir/build/repo" - } - } - } - configureJarManifestAttributes = { project -> - { -> - manifest.attributes['-exportcontents'] = "*;-noimport:=true" - manifest.attributes['Build-Version'] = project.gitVersion - manifest.attributes['Bundle-Version'] = project.version - manifest.attributes['Bundle-Name'] = project.archivesBaseName - manifest.attributes['Bundle-SymbolicName'] = project.group + '.' + project.archivesBaseName - } - } -} - - -def projectNamesNotToBePublished = ["driver-benchmarks", "driver-lambda", "driver-workload-executor", "graalvm-native-image-app", "util", - "spock", "taglets"] -def publishedProjects = subprojects.findAll { !projectNamesNotToBePublished.contains(it.name) } -def bomProjects = project(":bom") -def scalaProjects = publishedProjects.findAll { it.name.contains('scala') } - bomProjects -def javaProjects = publishedProjects - scalaProjects - bomProjects -def projectsWithManifest = publishedProjects.findAll {it.name != 'driver-legacy' } - bomProjects - -configure(javaProjects) { project -> - apply plugin: 'maven-publish' - apply plugin: 'signing' - - task sourcesJar(type: Jar) { - from project.sourceSets.main.allJava - classifier = 'sources' - } - - task javadocJar(type: Jar) { - from javadoc - classifier = 'javadoc' - } - - publishing { - publications { - mavenJava(MavenPublication) { - artifactId = project.archivesBaseName - from project.components.java - artifact sourcesJar - artifact javadocJar - - suppressPomMetadataWarningsFor("dateTimeSupportApiElements") - suppressPomMetadataWarningsFor("dateTimeSupportRuntimeElements") - - suppressPomMetadataWarningsFor("jsonSupportApiElements") - suppressPomMetadataWarningsFor("jsonSupportRuntimeElements") - - suppressPomMetadataWarningsFor("mongoCryptSupportApiElements") - suppressPomMetadataWarningsFor("mongoCryptSupportRuntimeElements") - } - } - - repositories configureMavenRepositories(project) - } - - afterEvaluate { - publishing.publications.mavenJava.artifactId = project.archivesBaseName - publishing.publications.mavenJava.pom configurePom(project) - signing { - useInMemoryPgpKeys(findProperty("signingKey"), findProperty("signingPassword")) - sign publishing.publications.mavenJava - } - } -} - -configure(scalaProjects) { project -> - apply plugin: 'maven-publish' - apply plugin: 'signing' - - task sourcesJar(type: Jar) { - from project.sourceSets.main.allScala - classifier = 'sources' - } - - task scaladocJar(type: Jar) { - from scaladoc - classifier = 'javadoc' - } - - publishing { - publications { - mavenJava(MavenPublication) { - artifactId = project.archivesBaseName.contains('bson') ? 'mongo-scala-bson' : 'mongo-scala-driver' - from project.components.java - artifact sourcesJar - artifact scaladocJar - } - } - - repositories configureMavenRepositories(project) - } - - afterEvaluate { - publishing.publications.mavenJava.pom configurePom(project) - signing { - useInMemoryPgpKeys(findProperty("signingKey"), findProperty("signingPassword")) - sign publishing.publications.mavenJava - } - } -} - - -configure(projectsWithManifest) { project -> - apply plugin: 'biz.aQute.bnd.builder' - afterEvaluate { - jar configureJarManifestAttributes(project) - } -} - -configure(bomProjects) { project -> - apply plugin: 'maven-publish' - apply plugin: 'signing' - apply plugin: 'java-platform' - - // Get the Scala versions from the project property. Only major.minor versions. - def scalaVersions = project.findProperty("scalaVersions")?.split(",") - ?.collect { it.split("\\.")[0] + "." + it.split("\\.")[1] } - - assert scalaVersions != null && !scalaVersions.isEmpty() : "Scala versions must be provided as a comma-separated list" + - " in the 'scalaVersions' project property" - - publishing { - publications { - mavenJava(MavenPublication) { - artifactId = "bom".equals(project.archivesBaseName) ? "mongodb-driver-bom" : project.archivesBaseName - from components.javaPlatform - - // Modify the generated POM to add multiple compile versions of driver-scala or bson-scala. - // Scala multi-version support generates only one for BOM. - pom.withXml { - def pomXml = asNode() - - def dependencyManagementNode = pomXml.get("dependencyManagement")?.getAt(0) - assert dependencyManagementNode : " node not found in the generated BOM POM" - - def dependenciesNode = dependencyManagementNode.get("dependencies")?.getAt(0) - assert dependenciesNode : " node not found inside " - - // Check if scala dependencies are present in the BOM. - def existingScalaDeps = dependenciesNode.children().findAll { - it.artifactId.text().contains("scala") - } - - existingScalaDeps.each { existingDep -> - String groupId = existingDep.groupId.text() - String originalArtifactId = existingDep.artifactId.text() - String artifactVersion = existingDep.version.text() - - // Add multiple versions with Scala suffixes for each Scala-related dependency. - scalaVersions.each { scalaVersion -> - // Remove existing Scala version suffix (_2.12, _2.13, etc.) - String baseArtifactId = originalArtifactId.replaceAll("_\\d+\\.\\d+(\\.\\d+)?\$", "") - String newArtifactId = "${baseArtifactId}_${scalaVersion}" - - // Skip if Scala dependency with this scalaVersion already exists in BOM. - if(newArtifactId != originalArtifactId) { - def dependencyNode = dependenciesNode.appendNode("dependency") - dependencyNode.appendNode("groupId", groupId) - dependencyNode.appendNode("artifactId", newArtifactId) - dependencyNode.appendNode("version", artifactVersion) - } - } - } - } - } - } - - repositories configureMavenRepositories(project) - } - - afterEvaluate { - publishing.publications.mavenJava.pom configurePom(project) - signing { - useInMemoryPgpKeys(findProperty("signingKey"), findProperty("signingPassword")) - sign publishing.publications.mavenJava - } - } - - tasks.withType(GenerateModuleMetadata) { - enabled = false - } - - tasks.withType(GenerateMavenPom).configureEach { - doLast { - def xml = file(destination).text - def root = new groovy.xml.XmlSlurper().parseText(xml) - - def dependencies = root.dependencyManagement.dependencies.children() - assert dependencies.children().size() > 1 : "BOM must contain more then one element:\n$destination" - - dependencies.each { dependency -> - def groupId = dependency.groupId.text() - assert groupId.startsWith('org.mongodb') : "BOM must contain only 'org.mongodb' dependencies, but found '$groupId':\n$destination" - /* The and tags should be omitted in BOM dependencies. - This ensures that consuming projects have the flexibility to decide whether a - dependency is optional in their context. The BOM's role is to provide version information, - not to dictate inclusion or exclusion of dependencies. */ - assert dependency.scope.size() == 0 : "BOM must not contain elements in dependency:\n$destination" - assert dependency.optional.size() == 0 : "BOM must not contain elements in dependency:\n$destination" - } - } - } -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..afba109285af78dbd2a1d187e33ac4f87c76e392 100644 GIT binary patch delta 36947 zcmaI7V{m3&)UKP3ZQHh;j&0kvlMbFZ9ox38C$?>O+_CN5->$u@&U@#maG;|KYYE%vB)D3H-6K@WbA^zz3=0 zIXC&q$Fs58dCdXPdwBZi`}5g%7D>qa+7E;?>JiqUeBWiOSY$Zr@Xn;YORQg3T}{df z!T?aZdj#w7bb#UCr2=YDvcK#VL)7+is{>J|s!WA)e)G%w1rnoepA(|3O6xFar+i=D ztI6ygv%O25(NWbI>JMX@=gX~v(4Ufhg)ZIDJ|FZh&Hi__>i&0i_FXVo!SX`o#ttw~ z8t&uKZQ9IR5)7gd$-`C2qr`+sAQ77XRuP~O^?Bm6I5KXpEAri`HxlZ`86&Tc3WL9V zSCv-h)*6FrpUvM_1C{@9bP!gMN=S$asW*Qg#kT?0aG(g5Fe%+Il^*5`wud&YuHuEa zr(i$pB{j&g>h~@mXjJFh1}|xjB$5Q*d#uOv)j9u$PkwKiXYWs9mmGf`$B6Usy;MNC z{cz$SANb$4tnuU;s!P#d{PxfxGGlza@0-6!a|n0@AGMRK5TD$hj`Jts@+rhH_)N#s zyJhp~x7?)qRvi$Pb>zuY*`LbLMiHtEg$TKd6aVHD3Ki?Jw9kV2JxS41)H9ms3^EL+ z3ZirAjL`eJE!FFEWM3M4wkgI@SSJIR`V9lc_sB{p`4-%5(?8AxVj-63kLlcG^EZZn zXE6AfItQ067p0Di@>vv(q^L8rUEIXaeU5$9oN#F6%mq)pEyG3(W^u<&0V3f@5*KKw;8_fUxDUKk5BJxoiyGSJBAT>xrFK+5I{Dx5WewhfQgX z@L)}uI0ZzvG_2Vl@A~w}sxW{2B`5S%Tka?}+}H#79A;e{n-@X_>_NJNeT(R{U>>tQNDmTC|q64ZS9ttIYS^_q^K!$J09NQNf|I)qVm(UiK zY5Gis83zH50b-jM1plgCPh9^vAuH~PV;k-m76fO0#eO1=4;aA84c14B{-C;1bftdz zt|RVOEIF?Lfa!iiM@@26cXzD@(G`JxV%2oIyu{Jp>DMMa>^(d;umC~JIam26+ z+zt$FT?7Rwb$yk-BBeYZyV=|r_yG=XvN*R4AXFh;gZexPxlHaP#GFzj82|U^V={`3 zUY5<4T6}W%XdN4*y*xd}WHIn4QmY^$Wgk>LguMZFwdrz7?=n-1VFF`5KZ3)AVNtbO zRji0|0CkN#DU==%q^Mn>V!?)Y)Ev#fYV{hMw9QV)HHt{7NU5FCt-5F}542_^YZ#bf z?Ot+qn(Zs(T79+{G>(iuso=Eb&S6e`va39L(NK`5qCDP64AZoU&W1Re@iVGj@j|@d zXDw5$w?)G9_`1+y<=~T%1SWPHLtkWwM$H@ycr+GOSTOctUpvM;ooU^p_=b^A}KW!_0M=u>DD$ zt*)cy49($|>Ay;FlwnU32)l^+H**d)aE_+D2<~_ptWIM=hMo8)o$zmE%oS0t=5F}! zalvA@~YCgf6?+MDhC zF|oNLb?v6;c_1SbyGG>8=71|qE7j~sd%^-8$D&f%cW3FMRaQ}O#D;N)W8t#uL>aaU zokgBK&B!_nhe9supnIHee>)bJ;FkOql~ z#?pYtXMhqymtHFC>}35uLb@)VB;%+E#(rlbfqfMAMtA1GA2T6hK1K;?Ulp-lOS*bkDY6 zmvq}uF!()dJr1lNV8G1Y6z(9~-{K~>ASr-M#Whnj>Zt0x07s&biF&AjVhh>D{v z3R*;ai&xkJ`Vryz_qK!-0%MYYSdszCf5;(O#Hy>D$SAUn*kk(#m?f}jz+i@)2+${@ z?@E25NqTSyd@(7;E-@z*2h55cMoX}VX-cQ`t%%(t6Iuw?L9KJ|8B*jUv0u|}+X5YI z2-lFcgb?4{$Ox`LR*rv^5~yFs>jm=aMJ)g3mI%}1jQ!=*qrfXMQFjoVQ0WU8wHS7o z{%e8}+%x{^SxZgkbI;m1af>~+Zx<`Bi|N>~lw_y#@;%Te9ypC-hch}nd{O9qfqA@k z8s<*ZcW{a&ZNoaeQ|HzE$6w>aQf_Jnv7T3t%3p2PEU9(W<=`X<*=X&ppsL zznX_Pu+{mZz1JJ`@;P60SC1S}werW=EytC6l{nxM7%e>?s_;wptTomcY_cXS6w_#a zx#=*KO?f~rWilOK|3RAzP2}v))Xj4I6^<9B=VNi#kJ-Yf?dCH`N^mHwq$7oNg8tVf~Nfr$J zUlj=r4FUop46-@G=*;x*i7hGIQvh!%kaaQ&6%JM<$}NfwHA+Pl7%6iv!|JMP-`+Iq zd4>Xh@?zba)E%J&(B-aYP^u*UgF+|5lpF-DrS#)ShZ;I@x3@(9Tx6YMQ`{FKZ$Pt8 zELg_mqwF>#+Ihwya7CpR8}&PTaw^-ghlh{N$N%f=4&x_LDmgo;hN5U)2;~s@(EPEu z(3La1(-u}H2@L)qJ`%SCx!0{yP>3Xc9M1^0&9tVC;M(LIAYm!Sj^1`GBO6urcxf%9 zr-i~cqqveLsxd(`8eBWBJkv(dEd9)d^Luju)iUw|b-M~a7e=6nnH{EoU}mMmqTQ8M1ka-IgtBlK`mN(c`R#^?;Ju3awoc!W<*S3<`|<9*X=cnrn#-B#-6wBdY z9(gWbhrMrdVhXL{8Y`@`;u+n{S`qnR&Cqm;;&~(r0KxLTDatsgKuSvAPk%CoY=Xa3 z&>UpGkUDH{tvK!6fO(zMkUknz*FzinOOrrAFr^;gSX2C4Bg4o8RM{HC5uyfyr5GFX zt74=wV*H7_l@3qFS}q0M&yopu!ta=#mjlL*Y=Vs^N8|2wSBc5o8h{ZxZ=ZG=Tk+RK zO}%gcAOo&8qdjbPLVtx_@rXcSPngSq=}fP(Lkn|xDc$`Sf1&|+s;1lJs{Yt*Gw;v6 z<0$==3#n)2^nGqZYAGzv_c@n!vO4?WKVNHg6ejD&G^d#0vDoancmWqGG=Kps`LyS+ z=!2zWWrxno8HLLU#UxvpVpda3=A$=&(Wj#f*df6gbicDG>M6ns3I97k2L%-DM|+LN z#p)^WAbBGQ1iNWrwmuWFBYO0KieEw8)rXU`I*%fx#eJf043hX6&>+sHYbcebjDeuhwcO}yhW0&khl`~DH30_!o=JOYo=O^!MzokOCV`Tm%k>b zlR)Qx7+I9nm(c>NeH*2oz7_Evqk}B~l)L9{w=cHTz>{{E^Ias{s|~nWosZy#B>AK1 zOioOw>s-iaVBs9?qnBR9bDHo4^54@4bT`UNGLDf4w3ZVKYJvySIR!+Lj)>imkYmWt zNhllAUn(os`dIi-`-AsJF_9}vv)_Wf6ht?zHf1*-_N7yHvNbjJW~}FIetkS%LIvP# zG3T2O{lqQWCXYF##+5P|=p&~mP~|PfVa2F3I4;z237KZrx-*-uls0g;uiEEbA!Eez zaCcq>Smu(rFQUW(qKv)R|M*o;#p^v(g3r2kHKT8t|9Gf39 zdyi5l#iw;{OUP{QO{?Hx7;S0WTgAf&6~&MNycXEMvRv3`8Q#3#MUIWl@#wNBJ@eY>p43DR&<5uHYF*G}`1nrmn{lvWW4%;16>_U$Jk{brT@ z=6C+GRnSh623OXYrUa0kaT$#4lW~Hv=y67odHva-KSXO@GF1dj3BuJ zp5WQS9TDDq4-`|3i!UXfJL^QUi3YxfHajR}|G9&~HF0 z+4@z=cgGD0o;bkz_75%SoDyws>xei2gGQvC5&yuP4txwf73c_vLU=S(b8sQqGr_o} z_&pmc?O?5?i*Oiv`HH)Y8D+@H%AQz@$ifx+5 zB$BcMsRw1Y^w7ZJbrG;bY~cu~^W}*zqsA#JC{R-4uD*W4aIB z6aT78KVDnz<4;3CjFp`t%?)u!@BEinD7s$qPcRS=cQ_Cb{-pd0@+6OaJixHVxyq&n z@>eVacPu^X0VL|i0`C&|4Fs5U-&zPbbUQj!nY)PXLKZ!`W`8PMHb(s%2)WsU{;<((ue32{Ax#Pdlv?28UdWr?&>P3D)zffkSmCO>tE~ya~ zLV<&$hhT!U%3T{Z4Le$?1n49Y9pN3F261rSN_B=Jn!xUZlvI$w&cgSO^@0C1YhF_Wrs?qWIim+dji;cs9+-^CKLbPve z5yt<+Y)u$yF_Tvr%R=6XQf4C$}aF&EYk7kKmFkj#^E!Mgfke{a93Ru_u| zkJPG^;`qkRn59P`48Sf}@wl#3%#NE>Hd^x|^FAUNs7~_fv1Btz#~8#HZBFxncPUt@ zXP>}Hh#w^2T@3PpIA$p{!anA{Vk1`^ssMic?8g+`dr=cc*@Q=762#yivV@Py%_U6l zw79HTr(l~UaxdNm9RaUo!r7PP(`uNAsdU&lpJngPfWpe81dvVROKV6m?Nb_=nRE%V zOe6Ekt@xfc)UM+j(kLmT5^{t=%*J!ZLR$gf1M6jnO}=_D!VN&$88ve&Q~w~Iln1vb z^?Lj=`*ZrsZXYNEk0+pBY(SJ!ZIfwGC%MS>0Azf;$t}|}MA$4ZF30{oFh`kRsj*@o z7FEN%E$8jt22gkVZKO<$eGSpi33ZEOXZpP9P~8={u&7h-bHx6@i%NT(oT;8-rF{`} zzjrG~kbG6Z=o#88)Fo~E4d<2i{vFjZBwbA^(!Ge>qDPO8I-I59|02c!HMrT_DeogR zEkplB=G)+9g7kH5eLcv>o{MQ|N9bqwLpXJ$lN_&<4X`juy&l$7s3XG~hUC;>{mA6> zFkgKoN;`sPhvb*lK(y-<_%$T!MC30@Oco>6Yr2Aw_lCIVH#W>|AI!3#nR{)Tk1fdX z8O5B^AMi%l4z5d@uE{cy$}&<*(qBt9sZqh8=b3Nl zAx!X76TlKE9Yn98+I&YMB~*cpYUYa06+gtzQ9?r{wX-wkB84B=M1maHG_7=BOgBG8 zaJ5F_`8mMcxz8QjP74*w)6#d0KZ>7*|1@;QTFY%{`KO^F;Mv+hJfO!YY~Y?m<{n7? zb_l<}gg6VWS^y%J*9AEbVd;cbm^ZUaHXc4}jr}E(_zm%2p}4WXL6uFaO4bH6eQK5K zRzOr1LX*n$niVjOG+QrGQp%r6stmk06P)cfZcaHw0EWNkund`R`(G{`Nl$XNELd88my8HeIRD;Vp#t z=dt;QXIO-eS_iia2uRMGGE}l`x|E3pJPpq?e#q6?7TXcW#bRSGn{@(yT=xQoB^yp; zxBooEiVKy`TFBU=#fjeNRlK`jcHJ7s8NVCO!AI%yxOp?L{1ekm3w){3uOlr}4X31X zR(;3nxBZf(1z5IA5BG#n_*(6?PjdhOMF;KyW4%7(7J5o*;8;eeaismofG8=j3IZ=X6-ie=!$hz2A@+!1PAp3h@ zw6I+mN@Hr#M7sL5hB7qYk#mv<O z6E|1)1?Ina=@$85Ehg!unFGq3#cMF>7~#j`5sTT}Ef#{_dzi|9uOKLaE2}B#Rs(a2 z2)X#bFmexecK6DkXXF+r0-JsBCVd>QI^W+C4ZmOS@IaMJ z3U3=D(zuym4BRBP=}B;e^T0(%NbM4o!)knG#ODkl(J;vn#>z+ZKLFOUPUdPR%t0hL zEOto^1fKWP0;~>w-O*l#;LmJ_fvj7 z)vek|wqYq2_v#T}$O4eH++bDm!s;jY5Bm7YbAJzki;&Vd>rF3H@XIdsz;44MThUja zgZpZ@E6J9uPu#^aY~-&bd&H=zhVKF0G&k(Y<)`I0hrDi+&r`lUW!RGB1GgEb97>FF z9isYrHgJB`)R)2XSy+s$K0=3VRD)}KLKeA|ymOsC$#0aR3j=6*tAVL!^LD|#U`At? zY-8#vw(_=P4=tI8pR#at@p;MoRJs;bIdaeErF2g2_O(9e7PuR~Q;#$gCKZe@Nk-Z{ zY`_BDn|LrYFFj5-^;E=-tS_U@XB5t^{?$=!#lY4pjalwOe5uom5>%!mYFCCf#kN(5 zl0tZ|y(!-%hN^iUh zju@)z4td=NZtEvh1B*uwS}%xBaE;c?%0EK84zr0BqM1dAYb*H)b7*H4lNtw9DBIL~ z>JW9tTEb8p7+tX~uz&h=U>srf)aEvG!VZ)eUtdKip=yi_47krfFr6=k+CTT%_UW)zxv0}28yhpfdrrIm9yv3Vu%^5^}@34rCk3_qJ(gx3y;{7BZ zFOn}>15}_k1^dcQ*plFkg44OwbNtgbxnk^8NY%y?_QLu8lpG970^J(o_Fi2R8~WQT zdXuGrhQNFXo6`A>j~QWvv=!#z4#T1^AM0G{MnHk7jqtqFI2-Zbqb!jr{*o-|w%Md* z1p&a_WI&$|DN86XS(t?|M9l9MwF%q_1sL3l#J%eMHvw~D;e(C? zdV^LIn#bMNjG5%F+-w^)g|Io(sO;47q<;l-&rS6N&I%P?#zVYwbf-3DXd#u?xBAk` z5ugX8s3VR*DHd`!v+}?!v(HgOrN~-wO-g0H-s1$-vAORb|PEGF7VqXHa zf|qUKO6h#Pl3}z$4wA6;tCu6arkSD)R(HfuKpcse>f~I;2aD;+U`372|EfRXIeMP4#3F;RU6MIs==>Ry(j9;AtWs>S>}M z)rDrOdy%8HgS_3gm-(|(fIPIJqp&F6a5Tu2`n*O-#L!g3(fPqOq_em0qKNxo6R<`- z!M5t^Qg^C{iYF?LvVvCB9v)%ZU@4B_4Q3)l?i|1_^xNk4ht3d5b5tBZ9IfA}He5$N z>}sMz)hWKnyf@rw7vyDNE1tk*AO*Q1?r_Fn`fTFp7!USHwQ2c#o z1(D@eK>QJEi^hK_{so3_corM8caH9q%a{9~I#B6`82$q4LK=B|GXC!@D+$ zHRb-^Yj+TnKh7N}I2Hr}J*se%bRLFAo#J$`Q_lNim@iuwk+wN2$jP3vG}$h`sNpT_ zwV()DvJ~7dt?Xx1T#7u80S*_GI9U-DH7?G1aAAUTlqS3H*>DYc5i}luPg_C1t0*=L zcX`=6MzbOIelIP4^MWT=6H}a0BA-<7H-htxo75N5e^XnPz>oc6P!Ny@$p8C`)q8*k z$Vt&xTr@%-{kFv0Uctbj{aq&~whq@A2n}sh_=0*Mh6YdR_1KrGy(mCoZ+SR^=lIa+ zMG_&hA4=4RWX`Xs`!|3h*j(CkX3^FExaBghx7Qymy+1J)9hP^2x>TE%#$81cl52TA zIdMW-j*3NeE}LP;#SFC#I+zLUHN{B)u&DnS>WCU`sgils$iP4Q0NtcMT9bBOTfT1L zz1TW2sZc~>R%0X0_JAh@s=ZI`$zc8Z40Hc#020a}VzOT0EC@E?RI8Cq zOuZ?xGFjC#=^z{GE}{o?PuWSx3h|dD{8{b!(=Fg>RMfwh0#ZBlV*e_~jACUPEp<5O}A_P1qZ zbGTN+1KKTthN&GQXIxWRxZquZDw^es9XI=^b}F(Itn3G0cmi|>ws4CHz#1#Uks){F zS$NYPzh-#ei4Y4E(NTKHd*+r0>;Vfv+!NKaaLCwv9qyC|s>jG~xA#Vto#>WoLT@-? z1>S>2k*;Ah!{Uwo*3K~M2AAn@ls>o&%|Ud666xxD-|N@mQpO}TzY1a*5=O!Zmpjk` zefOK;z5I4xqt!C*Nwd|WjmLU(8&@*cz{dET+#niV>lTSgN@b&*CbtC zS;;wv#K1jM-eEN|)t)sPlR$ZP8KRD3O0UKEDA#2#vt?N*og(b_^McFbE8z*E-g|!h ziTPw}7au$lRnT7lU6MJZ`ErGFBh2ZV6$f3Z*9aZL9Xxsttz&X~eeorL4LT4buK~-x>&t6ep0?vPg%UGCK;jjO3678dRv?4#Ed_ zZ>d~z4nEv+Kc9;uEb+;Y3pa5A269>DK4tCIx6HATa_=APd}51Ieddl5^83qbZ*?yF z@f2@Z9h;|my6>43`5}VS7gFHG2GGq#~O)|etAZw}bzDl)$c&tC997;IglK}hlL5L}xWlD~;SI+J6Lt<{?Vl96CuQ4jAdz~9u#?v55r07R^&p^?>T{x`YfLl$jwo4ng33qgkd7rR{m3xzq zU)ZeAk7T=Yo_XXE-

h3Y5Ua5>0<>`e@0qkQ+|8VA&>!KrR0;1 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 GO8pnEgtf;2 delta 35088 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/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd32c4e..93e3f59f135 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/mongodb-crypt/build.gradle.kts b/mongodb-crypt/build.gradle.kts index c3025544800..464c32c16a8 100644 --- a/mongodb-crypt/build.gradle.kts +++ b/mongodb-crypt/build.gradle.kts @@ -12,39 +12,44 @@ * 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. - * */ - +import ProjectExtensions.configureJarManifest +import ProjectExtensions.configureMavenPublication import de.undercouch.gradle.tasks.download.Download plugins { + id("project.java") alias(libs.plugins.download) } -group = "org.mongodb" -base.archivesName.set("mongodb-crypt") -description = "MongoDB client-side crypto support" -ext.set("pomName", "MongoCrypt") - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - dependencies { api(project(path = ":bson", configuration = "default")) api(libs.jna) +} - // Tests - testImplementation(libs.bundles.junit) +configureMavenPublication { + pom { + name.set("MongoCrypt") + description.set("MongoDB client-side crypto support") + } +} + +configureJarManifest { + attributes["Automatic-Module-Name"] = "com.mongodb.crypt.capi" + attributes["Bundle-Name"] = "MongoCrypt" + attributes["Bundle-SymbolicName"] = "com.mongodb.crypt.capi" + attributes["Import-Package"] = "org.slf4j.*;resolution:=optional,org.bson.*" + attributes["-exportcontents"] = "com.mongodb.*;-noimport:=true" + attributes["Private-Package"] = "" } /* * Jna copy or download resources */ -val jnaDownloadsDir = "$buildDir/jnaLibs/downloads/" -val jnaResourcesDir = "$buildDir/jnaLibs/resources/" -val jnaLibPlatform: String = if (com.sun.jna.Platform.RESOURCE_PREFIX.startsWith("darwin")) "darwin" else com.sun.jna.Platform.RESOURCE_PREFIX +val jnaDownloadsDir = rootProject.file("build/jnaLibs/downloads/").path +val jnaResourcesDir = rootProject.file("build/jnaLibs/resources/").path +val jnaLibPlatform: String = + if (com.sun.jna.Platform.RESOURCE_PREFIX.startsWith("darwin")) "darwin" else com.sun.jna.Platform.RESOURCE_PREFIX val jnaLibsPath: String = System.getProperty("jnaLibsPath", "${jnaResourcesDir}${jnaLibPlatform}") val jnaResources: String = System.getProperty("jna.library.path", jnaLibsPath) @@ -59,26 +64,19 @@ val binariesArchiveName = "libmongocrypt-java.tar.gz" */ val localBinariesArchiveName = "libmongocrypt-java-$downloadRevision.tar.gz" -val downloadUrl: String = "https://mciuploads.s3.amazonaws.com/libmongocrypt/java/$downloadRevision/$binariesArchiveName" - -val jnaMapping: Map = mapOf( - "rhel-62-64-bit" to "linux-x86-64", - "rhel72-zseries-test" to "linux-s390x", - "rhel-71-ppc64el" to "linux-ppc64le", - "ubuntu1604-arm64" to "linux-aarch64", - "windows-test" to "win32-x86-64", - "macos" to "darwin" -) - -sourceSets { - main { - java { - resources { - srcDirs(jnaResourcesDir) - } - } - } -} +val downloadUrl: String = + "https://mciuploads.s3.amazonaws.com/libmongocrypt/java/$downloadRevision/$binariesArchiveName" + +val jnaMapping: Map = + mapOf( + "rhel-62-64-bit" to "linux-x86-64", + "rhel72-zseries-test" to "linux-s390x", + "rhel-71-ppc64el" to "linux-ppc64le", + "ubuntu1604-arm64" to "linux-aarch64", + "windows-test" to "win32-x86-64", + "macos" to "darwin") + +sourceSets { main { java { resources { srcDirs(jnaResourcesDir) } } } } tasks.register("downloadJava") { src(downloadUrl) @@ -90,57 +88,49 @@ tasks.register("downloadJava") { tasks.register("unzipJava") { /* - Clean up the directory first if the task is not UP-TO-DATE. - This can happen if the download revision has been changed and the archive is downloaded again. - */ + Clean up the directory first if the task is not UP-TO-DATE. + This can happen if the download revision has been changed and the archive is downloaded again. + */ doFirst { println("Cleaning up $jnaResourcesDir") delete(jnaResourcesDir) } from(tarTree(resources.gzip("${jnaDownloadsDir}/$localBinariesArchiveName"))) - include(jnaMapping.keys.flatMap { - listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/lib/**/libmongocrypt.dylib", "${it}/bin/**/mongocrypt.dll" ) - }) - eachFile { - path = "${jnaMapping[path.substringBefore("/")]}/${name}" - } + include( + jnaMapping.keys.flatMap { + listOf( + "${it}/nocrypto/**/libmongocrypt.so", "${it}/lib/**/libmongocrypt.dylib", "${it}/bin/**/mongocrypt.dll") + }) + eachFile { path = "${jnaMapping[path.substringBefore("/")]}/${name}" } into(jnaResourcesDir) dependsOn("downloadJava") - doLast { - println("jna.library.path contents: \n ${fileTree(jnaResourcesDir).files.joinToString(",\n ")}") - } + doLast { println("jna.library.path contents: \n ${fileTree(jnaResourcesDir).files.joinToString(",\n ")}") } } -// The `processResources` task (defined by the `java-library` plug-in) consumes files in the main source set. +// The `processResources` task (defined by the `java-library` plug-in) consumes files in the main +// source set. // Add a dependency on `unzipJava`. `unzipJava` adds libmongocrypt libraries to the main source set. -tasks.processResources { - mustRunAfter(tasks.named("unzipJava")) -} +tasks.processResources { mustRunAfter(tasks.named("unzipJava")) } -tasks.register("downloadJnaLibs") { - dependsOn("downloadJava", "unzipJava") -} +tasks.register("downloadJnaLibs") { dependsOn("downloadJava", "unzipJava") } tasks.test { systemProperty("jna.debug_load", "true") systemProperty("jna.library.path", jnaResources) useJUnitPlatform() - testLogging { - events("passed", "skipped", "failed") - } + testLogging { events("passed", "skipped", "failed") } doFirst { println("jna.library.path contents:") - println(fileTree(jnaResources) { - this.setIncludes(listOf("*.*")) - }.files.joinToString(",\n ", " ")) + println(fileTree(jnaResources) { this.setIncludes(listOf("*.*")) }.files.joinToString(",\n ", " ")) } dependsOn("downloadJnaLibs", "downloadJava", "unzipJava") } tasks.withType { - description = """$description + description = + """$description | System properties: | ================= | @@ -149,28 +139,7 @@ tasks.withType { """.trimMargin() } -tasks.jar { - //NOTE this enables depending on the mongocrypt from driver-core - dependsOn("downloadJnaLibs") -} - -tasks.javadoc { - if (JavaVersion.current().isJava9Compatible) { - (options as StandardJavadocDocletOptions).addBooleanOption("html5", true) - } -} - -afterEvaluate { - tasks.jar { - manifest { - attributes( - "-exportcontents" to "com.mongodb.*;-noimport:=true", - "Automatic-Module-Name" to "com.mongodb.crypt.capi", - "Import-Package" to "org.slf4j.*;resolution:=optional,org.bson.*", - "Bundle-Name" to "MongoCrypt", - "Bundle-SymbolicName" to "com.mongodb.crypt.capi", - "Private-Package" to "" - ) - } - } +tasks.withType { + // NOTE this enables depending on the mongocrypt from driver-core + dependsOn("downloadJnaLibs") } diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index e390791d5d5..00000000000 --- a/settings.gradle +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * 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. - */ - -include ':bson' -include ':bson-record-codec' -include ':driver-benchmarks' -include ':driver-workload-executor' -include ':driver-lambda' -include ':driver-core' -include ':driver-legacy' -include ':driver-sync' -include ':driver-reactive-streams' -include ':bson-kotlin' -include ':bson-kotlinx' -include ':driver-kotlin-extensions' -include ':driver-kotlin-sync' -include ':driver-kotlin-coroutine' -include ':bson-scala' -include ':driver-scala' -include ':mongodb-crypt' -include 'util:spock' -include 'util:taglets' -include ':bom' - -if(hasProperty("includeGraalvm")) { - include ':graalvm-native-image-app' -} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000000..019d3b8290d --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,49 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ + +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} + +include(":bom") + +include(":bson") +include(":bson-kotlin") +include(":bson-kotlinx") +include(":bson-record-codec") +include(":bson-scala") + +include(":driver-core") +include(":driver-sync") +include(":driver-legacy") +include(":driver-reactive-streams") +include(":mongodb-crypt") + +include(":driver-kotlin-coroutine") +include(":driver-kotlin-extensions") +include(":driver-kotlin-sync") +include(":driver-scala") + +include(":driver-benchmarks") +include(":driver-lambda") +include(":driver-workload-executor") +if (providers.gradleProperty("includeGraalvm").isPresent) { + include(":graalvm-native-image-app") +} diff --git a/util/spock/src/main/util/spock/annotations/Slow.java b/util/spock/src/main/util/spock/annotations/Slow.java deleted file mode 100644 index c3611cbb22b..00000000000 --- a/util/spock/src/main/util/spock/annotations/Slow.java +++ /dev/null @@ -1,11 +0,0 @@ -package util.spock.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface Slow { -} From 6bd5998ae5e27afe4a4a5425c6305bb77d1474fd Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Tue, 25 Mar 2025 10:13:16 +0000 Subject: [PATCH 4/4] Update test runtime classpath dependencies for netty openssl testing --- ...-artifacts-runtime-dependencies.gradle.kts | 27 +++++++++++++++++++ driver-core/build.gradle.kts | 4 +-- driver-kotlin-coroutine/build.gradle.kts | 1 + driver-kotlin-sync/build.gradle.kts | 1 + driver-legacy/build.gradle.kts | 1 + driver-reactive-streams/build.gradle.kts | 1 + driver-sync/build.gradle.kts | 1 + gradle/libs.versions.toml | 2 +- 8 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 buildSrc/src/main/kotlin/conventions/test-artifacts-runtime-dependencies.gradle.kts diff --git a/buildSrc/src/main/kotlin/conventions/test-artifacts-runtime-dependencies.gradle.kts b/buildSrc/src/main/kotlin/conventions/test-artifacts-runtime-dependencies.gradle.kts new file mode 100644 index 00000000000..73b2b891faa --- /dev/null +++ b/buildSrc/src/main/kotlin/conventions/test-artifacts-runtime-dependencies.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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 conventions + +plugins { id("java-library") } + +// Also include test runtime dependencies +dependencies { + testRuntimeClasspath(platform(libs.netty.bom)) + testRuntimeClasspath(libs.netty.tcnative.boringssl.static) + listOf("linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64").forEach { arch -> + testRuntimeClasspath(variantOf(libs.netty.tcnative.boringssl.static) { classifier(arch) }) + } +} diff --git a/driver-core/build.gradle.kts b/driver-core/build.gradle.kts index 4c1c63c53ea..4f06805a6ea 100644 --- a/driver-core/build.gradle.kts +++ b/driver-core/build.gradle.kts @@ -57,9 +57,9 @@ dependencies { testImplementation(project(path = ":bson", configuration = "testArtifacts")) testImplementation(libs.reflections) - testRuntimeOnly(libs.netty.tcnative.boringssl) + testImplementation(libs.netty.tcnative.boringssl.static) listOf("linux-x86_64", "linux-aarch_64", "osx-x86_64", "osx-aarch_64", "windows-x86_64").forEach { arch -> - testRuntimeOnly(variantOf(libs.netty.tcnative.boringssl) { classifier(arch) }) + testImplementation("${libs.netty.tcnative.boringssl.static.get()}::$arch") } } diff --git a/driver-kotlin-coroutine/build.gradle.kts b/driver-kotlin-coroutine/build.gradle.kts index d28ba244bb6..02a2bf047aa 100644 --- a/driver-kotlin-coroutine/build.gradle.kts +++ b/driver-kotlin-coroutine/build.gradle.kts @@ -19,6 +19,7 @@ import ProjectExtensions.configureMavenPublication plugins { id("project.kotlin") id("conventions.test-artifacts") + id("conventions.test-artifacts-runtime-dependencies") } base.archivesName.set("mongodb-driver-kotlin-coroutine") diff --git a/driver-kotlin-sync/build.gradle.kts b/driver-kotlin-sync/build.gradle.kts index f7a8d37840f..5da1a5eec26 100644 --- a/driver-kotlin-sync/build.gradle.kts +++ b/driver-kotlin-sync/build.gradle.kts @@ -19,6 +19,7 @@ import ProjectExtensions.configureMavenPublication plugins { id("project.kotlin") id("conventions.test-artifacts") + id("conventions.test-artifacts-runtime-dependencies") } base.archivesName.set("mongodb-driver-kotlin-sync") diff --git a/driver-legacy/build.gradle.kts b/driver-legacy/build.gradle.kts index b141d1d7cb4..2855bce4cdf 100644 --- a/driver-legacy/build.gradle.kts +++ b/driver-legacy/build.gradle.kts @@ -19,6 +19,7 @@ import ProjectExtensions.configureMavenPublication plugins { id("project.java") id("conventions.test-artifacts") + id("conventions.test-artifacts-runtime-dependencies") id("conventions.test-include-optionals") id("conventions.testing-junit") id("conventions.testing-spock-exclude-slow") diff --git a/driver-reactive-streams/build.gradle.kts b/driver-reactive-streams/build.gradle.kts index cd100a26585..f1c758b31da 100644 --- a/driver-reactive-streams/build.gradle.kts +++ b/driver-reactive-streams/build.gradle.kts @@ -19,6 +19,7 @@ import ProjectExtensions.configureMavenPublication plugins { id("project.java") id("conventions.test-artifacts") + id("conventions.test-artifacts-runtime-dependencies") id("conventions.test-include-optionals") id("conventions.testing-mockito") id("conventions.testing-junit") diff --git a/driver-sync/build.gradle.kts b/driver-sync/build.gradle.kts index efbef9b2832..95cd0979973 100644 --- a/driver-sync/build.gradle.kts +++ b/driver-sync/build.gradle.kts @@ -19,6 +19,7 @@ import ProjectExtensions.configureMavenPublication plugins { id("project.java") id("conventions.test-artifacts") + id("conventions.test-artifacts-runtime-dependencies") id("conventions.test-include-optionals") id("conventions.testing-mockito") id("conventions.testing-junit") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8dac391dcd5..eab637a8b41 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -165,7 +165,7 @@ findbugs-jsr = { module = "com.google.code.findbugs:jsr305", version.ref = "find groovy = { module = "org.codehaus.groovy:groovy-all", version.ref = "groovy" } hamcrest-all = { module = "org.hamcrest:hamcrest-all", version.ref = "hamcrest" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } -netty-tcnative-boringssl = { module = "io.netty:netty-tcnative-boringssl-static" } +netty-tcnative-boringssl-static = { module = "io.netty:netty-tcnative-boringssl-static" } objenesis = { module = "org.objenesis:objenesis", version.ref = "objenesis" } project-reactor-test = { module = "io.projectreactor:reactor-test" } reactive-streams-tck = { module = " org.reactivestreams:reactive-streams-tck", version.ref = "reactive-streams" }