diff --git a/.evergreen/.evg.yml b/.evergreen/.evg.yml
index 40c104ddbf2..9187ff62edb 100644
--- a/.evergreen/.evg.yml
+++ b/.evergreen/.evg.yml
@@ -289,6 +289,16 @@ functions:
${PREPARE_SHELL}
SCALA="${SCALA}" AUTH="${AUTH}" SSL="${SSL}" MONGODB_URI="${MONGODB_URI}" SAFE_FOR_MULTI_MONGOS="${SAFE_FOR_MULTI_MONGOS}" TOPOLOGY="${TOPOLOGY}" JAVA_VERSION="${JAVA_VERSION}" .evergreen/run-scala-tests.sh
+ "run kotlin tests":
+ - command: shell.exec
+ type: test
+ params:
+ working_dir: "src"
+ script: |
+ ${PREPARE_SHELL}
+ AUTH="${AUTH}" SSL="${SSL}" MONGODB_URI="${MONGODB_URI}" SAFE_FOR_MULTI_MONGOS="${SAFE_FOR_MULTI_MONGOS}" TOPOLOGY="${TOPOLOGY}" JAVA_VERSION="${JAVA_VERSION}" .evergreen/run-kotlin-tests.sh
+
+
"run socket tests":
- command: shell.exec
type: test
@@ -904,6 +914,11 @@ tasks:
- func: "bootstrap mongo-orchestration"
- func: "run scala tests"
+ - name: "kotlin-tests"
+ commands:
+ - func: "bootstrap mongo-orchestration"
+ - func: "run kotlin tests"
+
- name: "reactive-streams-tck-test"
commands:
- func: "bootstrap mongo-orchestration"
@@ -1437,6 +1452,8 @@ tasks:
name: "plain-auth-test"
- variant: ".test-scala-variant"
name: "scala-tests"
+ - variant: ".test-kotlin-variant"
+ name: "kotlin-tests"
- variant: ".tests-netty-variant"
name: "netty-test"
commands:
@@ -2052,6 +2069,13 @@ buildvariants:
tasks:
- name: "scala-tests"
+- matrix_name: "kotlin-tests"
+ matrix_spec: { auth: "noauth", ssl: "nossl", jdk: ["jdk8", "jdk17"], version: ["6.0"], topology: "replicaset", os: "ubuntu" }
+ display_name: "Kotlin: ${jdk} ${version} ${topology} ${os}"
+ tags: ["test-kotlin-variant"]
+ tasks:
+ - name: "kotlin-tests"
+
- name: publish-snapshot
display_name: "Publish Snapshot"
run_on: ubuntu1804-test
diff --git a/.evergreen/run-kotlin-tests.sh b/.evergreen/run-kotlin-tests.sh
new file mode 100755
index 00000000000..836a48516b7
--- /dev/null
+++ b/.evergreen/run-kotlin-tests.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+set -o xtrace # Write all commands first to stderr
+set -o errexit # Exit the script with error if any of the commands fail
+
+
+AUTH=${AUTH:-noauth}
+SSL=${SSL:-nossl}
+MONGODB_URI=${MONGODB_URI:-}
+TOPOLOGY=${TOPOLOGY:-standalone}
+SAFE_FOR_MULTI_MONGOS=${SAFE_FOR_MULTI_MONGOS:-}
+
+############################################
+# Main Program #
+############################################
+RELATIVE_DIR_PATH="$(dirname "${BASH_SOURCE:-$0}")"
+. "${RELATIVE_DIR_PATH}/javaConfig.bash"
+
+
+if [ "$SSL" != "nossl" ]; then
+ echo -e "\nSSL support not configured for Kotlin tests"
+ exit 1
+fi
+
+if [ "$AUTH" != "noauth" ]; then
+ echo -e "\nAuth support not configured for Kotlin tests"
+ exit 1
+fi
+
+if [ "$SAFE_FOR_MULTI_MONGOS" == "true" ]; then
+ export MULTI_MONGOS_URI_SYSTEM_PROPERTY="-Dorg.mongodb.test.multi.mongos.uri=${MONGODB_URI}"
+fi
+
+echo "Running Kotlin tests"
+
+./gradlew -version
+./gradlew :driver-kotlin-sync:kCheck -Dorg.mongodb.test.uri=${MONGODB_URI} ${MULTI_MONGOS_URI_SYSTEM_PROPERTY}
diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml
new file mode 100644
index 00000000000..2297ba60044
--- /dev/null
+++ b/config/detekt/baseline.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ IteratorNotThrowingNoSuchElementException:MongoCursor.kt$MongoCursor<T : Any> : IteratorCloseable
+ LargeClass:MongoCollectionTest.kt$MongoCollectionTest
+ LongMethod:FindIterableTest.kt$FindIterableTest$@Suppress("DEPRECATION") @Test fun shouldCallTheUnderlyingMethods()
+ MaxLineLength:MapReduceIterable.kt$MapReduceIterable$*
+ SwallowedException:MockitoHelper.kt$MockitoHelper.DeepReflectionEqMatcher$e: Throwable
+ TooManyFunctions:ClientSession.kt$ClientSession : jClientSession
+ TooManyFunctions:FindIterable.kt$FindIterable<T : Any> : MongoIterable
+ TooManyFunctions:MongoCollection.kt$MongoCollection<T : Any>
+ TooManyFunctions:MongoDatabase.kt$MongoDatabase
+
+
diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml
new file mode 100644
index 00000000000..4c083b0bce5
--- /dev/null
+++ b/config/detekt/detekt.yml
@@ -0,0 +1,712 @@
+build:
+ maxIssues: 0
+ excludeCorrectable: false
+ weights:
+ # complexity: 2
+ # LongParameterList: 1
+ # style: 1
+ # comments: 1
+
+config:
+ validation: true
+ warningsAsErrors: false
+ # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
+ excludes: ''
+
+processors:
+ active: true
+ exclude:
+ - 'DetektProgressListener'
+ # - 'KtFileCountProcessor'
+ # - 'PackageCountProcessor'
+ # - 'ClassCountProcessor'
+ # - 'FunctionCountProcessor'
+ # - 'PropertyCountProcessor'
+ # - 'ProjectComplexityProcessor'
+ # - 'ProjectCognitiveComplexityProcessor'
+ # - 'ProjectLLOCProcessor'
+ # - 'ProjectCLOCProcessor'
+ # - 'ProjectLOCProcessor'
+ # - 'ProjectSLOCProcessor'
+ # - 'LicenseHeaderLoaderExtension'
+
+console-reports:
+ active: true
+ exclude:
+ - 'ProjectStatisticsReport'
+ - 'ComplexityReport'
+ - 'NotificationReport'
+ - 'FindingsReport'
+ - 'FileBasedFindingsReport'
+ # - 'LiteFindingsReport'
+
+output-reports:
+ active: true
+ exclude:
+ # - 'TxtOutputReport'
+ # - 'XmlOutputReport'
+ # - 'HtmlOutputReport'
+ # - 'MdOutputReport'
+
+comments:
+ active: true
+ AbsentOrWrongFileLicense:
+ active: false
+ licenseTemplateFile: 'license.template'
+ licenseTemplateIsRegex: false
+ CommentOverPrivateFunction:
+ active: false
+ CommentOverPrivateProperty:
+ active: false
+ DeprecatedBlockTag:
+ active: false
+ EndOfSentenceFormat:
+ active: false
+ endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
+ KDocReferencesNonPublicProperty:
+ active: false
+ excludes: ['**/test/**']
+ OutdatedDocumentation:
+ active: false
+ matchTypeParameters: true
+ matchDeclarationsOrder: true
+ allowParamOnConstructorProperties: false
+ UndocumentedPublicClass:
+ active: false
+ excludes: ['**/test/**']
+ searchInNestedClass: true
+ searchInInnerClass: true
+ searchInInnerObject: true
+ searchInInnerInterface: true
+ UndocumentedPublicFunction:
+ active: false
+ excludes: ['**/test/**']
+ UndocumentedPublicProperty:
+ active: false
+ excludes: ['**/test/**']
+
+complexity:
+ active: true
+ ComplexCondition:
+ active: true
+ threshold: 4
+ ComplexInterface:
+ active: false
+ threshold: 10
+ includeStaticDeclarations: false
+ includePrivateDeclarations: false
+ ComplexMethod:
+ active: true
+ threshold: 15
+ ignoreSingleWhenExpression: false
+ ignoreSimpleWhenEntries: false
+ ignoreNestingFunctions: false
+ nestingFunctions:
+ - 'also'
+ - 'apply'
+ - 'forEach'
+ - 'isNotNull'
+ - 'ifNull'
+ - 'let'
+ - 'run'
+ - 'use'
+ - 'with'
+ LabeledExpression:
+ active: false
+ ignoredLabels: []
+ LargeClass:
+ active: true
+ threshold: 600
+ LongMethod:
+ active: true
+ threshold: 60
+ LongParameterList:
+ active: true
+ functionThreshold: 6
+ constructorThreshold: 7
+ ignoreDefaultParameters: false
+ ignoreDataClasses: true
+ ignoreAnnotatedParameter: []
+ MethodOverloading:
+ active: false
+ threshold: 6
+ NamedArguments:
+ active: false
+ threshold: 3
+ ignoreArgumentsMatchingNames: false
+ NestedBlockDepth:
+ active: true
+ threshold: 4
+ NestedScopeFunctions:
+ active: false
+ threshold: 1
+ functions:
+ - 'kotlin.apply'
+ - 'kotlin.run'
+ - 'kotlin.with'
+ - 'kotlin.let'
+ - 'kotlin.also'
+ ReplaceSafeCallChainWithRun:
+ active: false
+ StringLiteralDuplication:
+ active: false
+ excludes: ['**/test/**']
+ threshold: 3
+ ignoreAnnotation: true
+ excludeStringsWithLessThan5Characters: true
+ ignoreStringsRegex: '$^'
+ TooManyFunctions:
+ active: true
+ excludes: ['**/test/**']
+ thresholdInFiles: 25
+ thresholdInClasses: 25
+ thresholdInInterfaces: 25
+ thresholdInObjects: 25
+ thresholdInEnums: 25
+ ignoreDeprecated: false
+ ignorePrivate: false
+ ignoreOverridden: false
+
+coroutines:
+ active: true
+ GlobalCoroutineUsage:
+ active: false
+ InjectDispatcher:
+ active: true
+ dispatcherNames:
+ - 'IO'
+ - 'Default'
+ - 'Unconfined'
+ RedundantSuspendModifier:
+ active: true
+ SleepInsteadOfDelay:
+ active: true
+ SuspendFunWithCoroutineScopeReceiver:
+ active: false
+ SuspendFunWithFlowReturnType:
+ active: true
+
+empty-blocks:
+ active: true
+ EmptyCatchBlock:
+ active: true
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ EmptyClassBlock:
+ active: true
+ EmptyDefaultConstructor:
+ active: true
+ EmptyDoWhileBlock:
+ active: true
+ EmptyElseBlock:
+ active: true
+ EmptyFinallyBlock:
+ active: true
+ EmptyForBlock:
+ active: true
+ EmptyFunctionBlock:
+ active: true
+ ignoreOverridden: false
+ EmptyIfBlock:
+ active: true
+ EmptyInitBlock:
+ active: true
+ EmptyKtFile:
+ active: true
+ EmptySecondaryConstructor:
+ active: true
+ EmptyTryBlock:
+ active: true
+ EmptyWhenBlock:
+ active: true
+ EmptyWhileBlock:
+ active: true
+
+exceptions:
+ active: true
+ ExceptionRaisedInUnexpectedLocation:
+ active: true
+ methodNames:
+ - 'equals'
+ - 'finalize'
+ - 'hashCode'
+ - 'toString'
+ InstanceOfCheckForException:
+ active: true
+ excludes: ['**/test/**']
+ NotImplementedDeclaration:
+ active: false
+ ObjectExtendsThrowable:
+ active: false
+ PrintStackTrace:
+ active: true
+ RethrowCaughtException:
+ active: true
+ ReturnFromFinally:
+ active: true
+ ignoreLabeled: false
+ SwallowedException:
+ active: true
+ ignoredExceptionTypes:
+ - 'InterruptedException'
+ - 'MalformedURLException'
+ - 'NumberFormatException'
+ - 'ParseException'
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ ThrowingExceptionFromFinally:
+ active: true
+ ThrowingExceptionInMain:
+ active: false
+ ThrowingExceptionsWithoutMessageOrCause:
+ active: true
+ excludes: ['**/test/**']
+ exceptions:
+ - 'ArrayIndexOutOfBoundsException'
+ - 'Exception'
+ - 'IllegalArgumentException'
+ - 'IllegalMonitorStateException'
+ - 'IllegalStateException'
+ - 'IndexOutOfBoundsException'
+ - 'NullPointerException'
+ - 'RuntimeException'
+ - 'Throwable'
+ ThrowingNewInstanceOfSameException:
+ active: true
+ TooGenericExceptionCaught:
+ active: true
+ excludes: ['**/test/**']
+ exceptionNames:
+ - 'ArrayIndexOutOfBoundsException'
+ - 'Error'
+ - 'Exception'
+ - 'IllegalMonitorStateException'
+ - 'IndexOutOfBoundsException'
+ - 'NullPointerException'
+ - 'RuntimeException'
+ - 'Throwable'
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ TooGenericExceptionThrown:
+ active: true
+ exceptionNames:
+ - 'Error'
+ - 'Exception'
+ - 'RuntimeException'
+ - 'Throwable'
+
+naming:
+ active: true
+ BooleanPropertyNaming:
+ active: false
+ allowedPattern: '^(is|has|are)'
+ ignoreOverridden: true
+ ClassNaming:
+ active: true
+ classPattern: '[A-Z][a-zA-Z0-9]*'
+ ConstructorParameterNaming:
+ active: true
+ parameterPattern: '[a-z][A-Za-z0-9]*'
+ privateParameterPattern: '[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+ ignoreOverridden: true
+ EnumNaming:
+ active: true
+ enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
+ ForbiddenClassName:
+ active: false
+ forbiddenName: []
+ FunctionMaxLength:
+ active: false
+ maximumFunctionNameLength: 30
+ FunctionMinLength:
+ active: false
+ minimumFunctionNameLength: 3
+ FunctionNaming:
+ active: true
+ excludes: ['**/test/**']
+ functionPattern: '[a-z][a-zA-Z0-9]*'
+ excludeClassPattern: '$^'
+ ignoreOverridden: true
+ FunctionParameterNaming:
+ active: true
+ parameterPattern: '[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+ ignoreOverridden: true
+ InvalidPackageDeclaration:
+ active: true
+ rootPackage: ''
+ requireRootInDeclaration: false
+ LambdaParameterNaming:
+ active: false
+ parameterPattern: '[a-z][A-Za-z0-9]*|_'
+ MatchingDeclarationName:
+ active: true
+ mustBeFirst: true
+ MemberNameEqualsClassName:
+ active: true
+ ignoreOverridden: true
+ NoNameShadowing:
+ active: true
+ NonBooleanPropertyPrefixedWithIs:
+ active: false
+ ObjectPropertyNaming:
+ active: true
+ constantPattern: '[A-Za-z][_A-Za-z0-9]*'
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
+ PackageNaming:
+ active: true
+ packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
+ TopLevelPropertyNaming:
+ active: true
+ constantPattern: '[A-Z][_A-Z0-9]*'
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
+ VariableMaxLength:
+ active: false
+ maximumVariableNameLength: 64
+ VariableMinLength:
+ active: false
+ minimumVariableNameLength: 1
+ VariableNaming:
+ active: true
+ variablePattern: '[a-z][A-Za-z0-9]*'
+ privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+ ignoreOverridden: true
+
+performance:
+ active: true
+ ArrayPrimitive:
+ active: true
+ CouldBeSequence:
+ active: false
+ threshold: 3
+ ForEachOnRange:
+ active: true
+ excludes: ['**/test/**']
+ SpreadOperator:
+ active: true
+ excludes: ['**/test/**']
+ UnnecessaryTemporaryInstantiation:
+ active: true
+
+potential-bugs:
+ active: true
+ AvoidReferentialEquality:
+ active: true
+ forbiddenTypePatterns:
+ - 'kotlin.String'
+ CastToNullableType:
+ active: false
+ Deprecation:
+ active: false
+ DontDowncastCollectionTypes:
+ active: false
+ DoubleMutabilityForCollection:
+ active: true
+ mutableTypes:
+ - 'kotlin.collections.MutableList'
+ - 'kotlin.collections.MutableMap'
+ - 'kotlin.collections.MutableSet'
+ - 'java.util.ArrayList'
+ - 'java.util.LinkedHashSet'
+ - 'java.util.HashSet'
+ - 'java.util.LinkedHashMap'
+ - 'java.util.HashMap'
+ DuplicateCaseInWhenExpression:
+ active: true
+ ElseCaseInsteadOfExhaustiveWhen:
+ active: false
+ EqualsAlwaysReturnsTrueOrFalse:
+ active: true
+ EqualsWithHashCodeExist:
+ active: true
+ ExitOutsideMain:
+ active: false
+ ExplicitGarbageCollectionCall:
+ active: true
+ HasPlatformType:
+ active: true
+ IgnoredReturnValue:
+ active: true
+ restrictToAnnotatedMethods: true
+ returnValueAnnotations:
+ - '*.CheckResult'
+ - '*.CheckReturnValue'
+ ignoreReturnValueAnnotations:
+ - '*.CanIgnoreReturnValue'
+ ignoreFunctionCall: []
+ ImplicitDefaultLocale:
+ active: true
+ ImplicitUnitReturnType:
+ active: false
+ allowExplicitReturnType: true
+ InvalidRange:
+ active: true
+ IteratorHasNextCallsNextMethod:
+ active: true
+ IteratorNotThrowingNoSuchElementException:
+ active: true
+ LateinitUsage:
+ active: false
+ excludes: ['**/test/**']
+ ignoreOnClassesPattern: ''
+ MapGetWithNotNullAssertionOperator:
+ active: true
+ MissingPackageDeclaration:
+ active: false
+ excludes: ['**/*.kts']
+ MissingWhenCase:
+ active: true
+ allowElseExpression: true
+ NullCheckOnMutableProperty:
+ active: false
+ NullableToStringCall:
+ active: false
+ RedundantElseInWhen:
+ active: true
+ UnconditionalJumpStatementInLoop:
+ active: false
+ UnnecessaryNotNullOperator:
+ active: true
+ UnnecessarySafeCall:
+ active: true
+ UnreachableCatchBlock:
+ active: true
+ UnreachableCode:
+ active: true
+ UnsafeCallOnNullableType:
+ active: true
+ excludes: ['**/test/**']
+ UnsafeCast:
+ active: true
+ UnusedUnaryOperator:
+ active: true
+ UselessPostfixExpression:
+ active: true
+ WrongEqualsTypeParameter:
+ active: true
+
+style:
+ active: true
+ CanBeNonNullable:
+ active: false
+ CascadingCallWrapping:
+ active: false
+ includeElvis: true
+ ClassOrdering:
+ active: false
+ CollapsibleIfStatements:
+ active: false
+ DataClassContainsFunctions:
+ active: false
+ conversionFunctionPrefix: 'to'
+ DataClassShouldBeImmutable:
+ active: false
+ DestructuringDeclarationWithTooManyEntries:
+ active: true
+ maxDestructuringEntries: 3
+ EqualsNullCall:
+ active: true
+ EqualsOnSignatureLine:
+ active: false
+ ExplicitCollectionElementAccessMethod:
+ active: false
+ ExplicitItLambdaParameter:
+ active: true
+ ExpressionBodySyntax:
+ active: false
+ includeLineWrapping: false
+ ForbiddenComment:
+ active: true
+ values:
+ - 'FIXME:'
+ - 'STOPSHIP:'
+ - 'TODO:'
+ allowedPatterns: ''
+ customMessage: ''
+ ForbiddenImport:
+ active: false
+ imports: []
+ forbiddenPatterns: ''
+ ForbiddenMethodCall:
+ active: false
+ methods:
+ - 'kotlin.io.print'
+ - 'kotlin.io.println'
+ ForbiddenPublicDataClass:
+ active: true
+ excludes: ['**']
+ ignorePackages:
+ - '*.internal'
+ - '*.internal.*'
+ ForbiddenSuppress:
+ active: false
+ rules: []
+ ForbiddenVoid:
+ active: true
+ ignoreOverridden: false
+ ignoreUsageInGenerics: false
+ FunctionOnlyReturningConstant:
+ active: true
+ ignoreOverridableFunction: true
+ ignoreActualFunction: true
+ excludedFunctions: ''
+ LibraryCodeMustSpecifyReturnType:
+ active: true
+ excludes: ['**']
+ LibraryEntitiesShouldNotBePublic:
+ active: true
+ excludes: ['**']
+ LoopWithTooManyJumpStatements:
+ active: true
+ maxJumpCount: 1
+ MagicNumber:
+ active: true
+ excludes: ['**/test/**', '**/*.kts']
+ ignoreNumbers:
+ - '-1'
+ - '0'
+ - '1'
+ - '2'
+ ignoreHashCodeFunction: true
+ ignorePropertyDeclaration: false
+ ignoreLocalVariableDeclaration: false
+ ignoreConstantDeclaration: true
+ ignoreCompanionObjectPropertyDeclaration: true
+ ignoreAnnotation: false
+ ignoreNamedArgument: true
+ ignoreEnums: true
+ ignoreRanges: false
+ ignoreExtensionFunctions: true
+ MandatoryBracesIfStatements:
+ active: false
+ MandatoryBracesLoops:
+ active: false
+ MaxChainedCallsOnSameLine:
+ active: false
+ maxChainedCalls: 5
+ MaxLineLength:
+ active: true
+ maxLineLength: 120
+ excludePackageStatements: true
+ excludeImportStatements: true
+ excludeCommentStatements: false
+ MayBeConst:
+ active: true
+ ModifierOrder:
+ active: true
+ MultilineLambdaItParameter:
+ active: false
+ NestedClassesVisibility:
+ active: true
+ NewLineAtEndOfFile:
+ active: true
+ NoTabs:
+ active: false
+ NullableBooleanCheck:
+ active: false
+ ObjectLiteralToLambda:
+ active: true
+ OptionalAbstractKeyword:
+ active: true
+ OptionalUnit:
+ active: false
+ OptionalWhenBraces:
+ active: false
+ PreferToOverPairSyntax:
+ active: false
+ ProtectedMemberInFinalClass:
+ active: true
+ RedundantExplicitType:
+ active: false
+ RedundantHigherOrderMapUsage:
+ active: true
+ RedundantVisibilityModifierRule:
+ active: false
+ ReturnCount:
+ active: true
+ max: 2
+ excludedFunctions: 'equals'
+ excludeLabeled: false
+ excludeReturnFromLambda: true
+ excludeGuardClauses: false
+ SafeCast:
+ active: true
+ SerialVersionUIDInSerializableClass:
+ active: true
+ SpacingBetweenPackageAndImports:
+ active: false
+ ThrowsCount:
+ active: true
+ max: 2
+ excludeGuardClauses: false
+ TrailingWhitespace:
+ active: false
+ UnderscoresInNumericLiterals:
+ active: false
+ acceptableLength: 4
+ allowNonStandardGrouping: false
+ UnnecessaryAbstractClass:
+ active: true
+ UnnecessaryAnnotationUseSiteTarget:
+ active: false
+ UnnecessaryApply:
+ active: true
+ UnnecessaryBackticks:
+ active: false
+ UnnecessaryFilter:
+ active: true
+ UnnecessaryInheritance:
+ active: true
+ UnnecessaryInnerClass:
+ active: false
+ UnnecessaryLet:
+ active: false
+ UnnecessaryParentheses:
+ active: false
+ UntilInsteadOfRangeTo:
+ active: false
+ UnusedImports:
+ active: false
+ UnusedPrivateClass:
+ active: true
+ UnusedPrivateMember:
+ active: true
+ allowedNames: '(_|ignored|expected|serialVersionUID)'
+ UseAnyOrNoneInsteadOfFind:
+ active: true
+ UseArrayLiteralsInAnnotations:
+ active: true
+ UseCheckNotNull:
+ active: true
+ UseCheckOrError:
+ active: true
+ UseDataClass:
+ active: false
+ allowVars: false
+ UseEmptyCounterpart:
+ active: false
+ UseIfEmptyOrIfBlank:
+ active: false
+ UseIfInsteadOfWhen:
+ active: false
+ UseIsNullOrEmpty:
+ active: true
+ UseOrEmpty:
+ active: true
+ UseRequire:
+ active: true
+ UseRequireNotNull:
+ active: true
+ UselessCallOnNotNull:
+ active: true
+ UtilityClassWithPublicConstructor:
+ active: true
+ VarCouldBeVal:
+ active: true
+ ignoreLateinitVar: false
+ WildcardImport:
+ active: true
+ excludes: ['**/test/**']
+ excludeImports:
+ - 'java.util.*'
diff --git a/config/mongodb.license b/config/mongodb.license
new file mode 100644
index 00000000000..6a2444433a7
--- /dev/null
+++ b/config/mongodb.license
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
diff --git a/config/spotbugs/exclude.xml b/config/spotbugs/exclude.xml
index 8cfa95fb4ec..5e095d213b2 100644
--- a/config/spotbugs/exclude.xml
+++ b/config/spotbugs/exclude.xml
@@ -170,6 +170,11 @@
+
+
+
+
+
diff --git a/driver-kotlin-sync/build.gradle.kts b/driver-kotlin-sync/build.gradle.kts
new file mode 100644
index 00000000000..32ace53c46f
--- /dev/null
+++ b/driver-kotlin-sync/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.
+ */
+import io.gitlab.arturbosch.detekt.Detekt
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+ id("org.jetbrains.kotlin.jvm") version "1.8.10"
+ `java-library`
+
+ // Test based plugins
+ id("com.diffplug.spotless")
+ id("org.jetbrains.dokka") version "1.7.20"
+ id("io.gitlab.arturbosch.detekt") version "1.21.0"
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+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("org.jetbrains.kotlin:kotlin-bom"))
+ implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
+
+ api(project(path = ":bson", configuration = "default"))
+ api(project(path = ":driver-sync", 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")
+
+ integrationTestImplementation("org.jetbrains.kotlin:kotlin-test-junit")
+ 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"),
+ )
+}
+
+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.getByName("spotbugsIntegrationTest") { enabled = false }
+}
+
+// ===========================
+// 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.create("kCheck") {
+ description = "Runs all the kotlin checks"
+ group = "verification"
+
+ dependsOn("clean", "check", integrationTest)
+ tasks.findByName("check")?.mustRunAfter("clean")
+ tasks.findByName("integrationTest")?.mustRunAfter("check")
+}
+
+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)
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/CrudTest.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/CrudTest.kt
new file mode 100644
index 00000000000..f7a9c88c89a
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/CrudTest.kt
@@ -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.
+ */
+package com.mongodb.kotlin.client
+
+import com.mongodb.client.AbstractCrudTest
+import com.mongodb.client.Fixture
+import com.mongodb.client.MongoDatabase
+import com.mongodb.event.CommandListener
+import com.mongodb.kotlin.client.syncadapter.SyncMongoClient
+import org.bson.BsonArray
+import org.bson.BsonDocument
+
+data class CrudTest(
+ val filename: String,
+ val description: String,
+ val databaseName: String,
+ val collectionName: String,
+ val data: BsonArray,
+ val definition: BsonDocument,
+ val skipTest: Boolean
+) : AbstractCrudTest(filename, description, databaseName, collectionName, data, definition, skipTest) {
+
+ private var mongoClient: SyncMongoClient? = null
+
+ override fun createMongoClient(commandListener: CommandListener) {
+ mongoClient =
+ SyncMongoClient(
+ MongoClient.create(Fixture.getMongoClientSettingsBuilder().addCommandListener(commandListener).build()))
+ }
+
+ override fun getDatabase(databaseName: String): MongoDatabase = mongoClient!!.getDatabase(databaseName)
+
+ override fun cleanUp() {
+ mongoClient?.close()
+ }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt
new file mode 100644
index 00000000000..4818497a1c5
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedCrudTest.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.kotlin.client
+
+import java.io.IOException
+import java.net.URISyntaxException
+import org.bson.BsonArray
+import org.bson.BsonDocument
+import org.junit.Assume.assumeFalse
+import org.junit.runners.Parameterized
+
+internal class UnifiedCrudTest(
+ fileDescription: String?,
+ testDescription: String,
+ schemaVersion: String,
+ runOnRequirements: BsonArray?,
+ entitiesArray: BsonArray,
+ initialData: BsonArray,
+ definition: BsonDocument
+) : UnifiedTest(fileDescription, schemaVersion, runOnRequirements, entitiesArray, initialData, definition) {
+
+ init {
+ assumeFalse(testDescription == "Unacknowledged findOneAndReplace with hint string on 4.4+ server")
+ assumeFalse(testDescription == "Unacknowledged findOneAndReplace with hint document on 4.4+ server")
+ assumeFalse(testDescription == "Unacknowledged findOneAndUpdate with hint string on 4.4+ server")
+ assumeFalse(testDescription == "Unacknowledged findOneAndUpdate with hint document on 4.4+ server")
+ assumeFalse(testDescription == "Unacknowledged findOneAndDelete with hint string on 4.4+ server")
+ assumeFalse(testDescription == "Unacknowledged findOneAndDelete with hint document on 4.4+ server")
+ }
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}: {1}")
+ @Throws(URISyntaxException::class, IOException::class)
+ fun data(): Collection?>? {
+ return getTestData("unified-test-format/crud")
+ }
+ }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt
new file mode 100644
index 00000000000..99a56849d7c
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/UnifiedTest.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.kotlin.client
+
+import com.mongodb.ClientEncryptionSettings
+import com.mongodb.MongoClientSettings
+import com.mongodb.client.MongoClient as JMongoClient
+import com.mongodb.client.MongoDatabase as JMongoDatabase
+import com.mongodb.client.gridfs.GridFSBucket
+import com.mongodb.client.unified.UnifiedTest as JUnifiedTest
+import com.mongodb.client.vault.ClientEncryption
+import com.mongodb.kotlin.client.syncadapter.SyncMongoClient
+import org.bson.BsonArray
+import org.bson.BsonDocument
+
+internal abstract class UnifiedTest(
+ fileDescription: String?,
+ schemaVersion: String,
+ runOnRequirements: BsonArray?,
+ entitiesArray: BsonArray,
+ initialData: BsonArray,
+ definition: BsonDocument
+) : JUnifiedTest(fileDescription, schemaVersion, runOnRequirements, entitiesArray, initialData, definition) {
+
+ override fun createMongoClient(settings: MongoClientSettings): JMongoClient =
+ SyncMongoClient(MongoClient.create(settings))
+
+ override fun createGridFSBucket(database: JMongoDatabase?): GridFSBucket {
+ TODO("Not yet implemented - JAVA-4893")
+ }
+
+ override fun createClientEncryption(
+ keyVaultClient: JMongoClient?,
+ clientEncryptionSettings: ClientEncryptionSettings?
+ ): ClientEncryption {
+ TODO("Not yet implemented - JAVA-4896")
+ }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt
new file mode 100644
index 00000000000..2640e6250d7
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncAggregateIterable.kt
@@ -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 com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.ExplainVerbosity
+import com.mongodb.client.AggregateIterable as JAggregateIterable
+import com.mongodb.client.model.Collation
+import com.mongodb.kotlin.client.AggregateIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+import org.bson.Document
+import org.bson.conversions.Bson
+
+internal class SyncAggregateIterable(val wrapped: AggregateIterable) :
+ JAggregateIterable, SyncMongoIterable(wrapped) {
+ override fun batchSize(batchSize: Int): SyncAggregateIterable = apply { wrapped.batchSize(batchSize) }
+
+ override fun toCollection() = wrapped.toCollection()
+
+ override fun allowDiskUse(allowDiskUse: Boolean?): SyncAggregateIterable = apply {
+ wrapped.allowDiskUse(allowDiskUse)
+ }
+
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncAggregateIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+
+ override fun maxAwaitTime(maxAwaitTime: Long, timeUnit: TimeUnit): SyncAggregateIterable = apply {
+ wrapped.maxAwaitTime(maxAwaitTime, timeUnit)
+ }
+
+ override fun bypassDocumentValidation(bypassDocumentValidation: Boolean?): SyncAggregateIterable = apply {
+ wrapped.bypassDocumentValidation(bypassDocumentValidation)
+ }
+
+ override fun collation(collation: Collation?): SyncAggregateIterable = apply { wrapped.collation(collation) }
+
+ override fun comment(comment: String?): SyncAggregateIterable = apply { wrapped.comment(comment) }
+
+ override fun comment(comment: BsonValue?): SyncAggregateIterable = apply { wrapped.comment(comment) }
+
+ override fun hint(hint: Bson?): SyncAggregateIterable = apply { wrapped.hint(hint) }
+
+ override fun hintString(hint: String?): SyncAggregateIterable = apply { wrapped.hintString(hint) }
+
+ override fun let(variables: Bson?): SyncAggregateIterable = apply { wrapped.let(variables) }
+
+ override fun explain(): Document = wrapped.explain()
+
+ override fun explain(verbosity: ExplainVerbosity): Document = wrapped.explain(verbosity)
+
+ override fun explain(explainResultClass: Class): E = wrapped.explain(explainResultClass)
+
+ override fun explain(explainResultClass: Class, verbosity: ExplainVerbosity): E =
+ wrapped.explain(explainResultClass, verbosity)
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt
new file mode 100644
index 00000000000..0d579e68006
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncChangeStreamIterable.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.kotlin.client.syncadapter
+
+import com.mongodb.client.ChangeStreamIterable as JChangeStreamIterable
+import com.mongodb.client.MongoIterable
+import com.mongodb.client.model.Collation
+import com.mongodb.client.model.changestream.ChangeStreamDocument
+import com.mongodb.client.model.changestream.FullDocument
+import com.mongodb.client.model.changestream.FullDocumentBeforeChange
+import com.mongodb.kotlin.client.ChangeStreamIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonDocument
+import org.bson.BsonTimestamp
+import org.bson.BsonValue
+
+internal class SyncChangeStreamIterable(val wrapped: ChangeStreamIterable) :
+ JChangeStreamIterable, SyncMongoIterable>(wrapped) {
+ override fun withDocumentClass(clazz: Class): MongoIterable =
+ SyncMongoIterable(wrapped.withDocumentClass(clazz))
+ override fun batchSize(batchSize: Int): SyncChangeStreamIterable = apply { wrapped.batchSize(batchSize) }
+ override fun collation(collation: Collation?): SyncChangeStreamIterable = apply { wrapped.collation(collation) }
+ override fun comment(comment: BsonValue?): SyncChangeStreamIterable = apply { wrapped.comment(comment) }
+ override fun comment(comment: String?): SyncChangeStreamIterable = apply { wrapped.comment(comment) }
+ override fun cursor(): SyncMongoChangeStreamCursor> =
+ SyncMongoChangeStreamCursor(wrapped.cursor())
+ override fun fullDocument(fullDocument: FullDocument): SyncChangeStreamIterable = apply {
+ wrapped.fullDocument(fullDocument)
+ }
+ override fun fullDocumentBeforeChange(
+ fullDocumentBeforeChange: FullDocumentBeforeChange
+ ): SyncChangeStreamIterable = apply { wrapped.fullDocumentBeforeChange(fullDocumentBeforeChange) }
+ override fun maxAwaitTime(maxAwaitTime: Long, timeUnit: TimeUnit): SyncChangeStreamIterable = apply {
+ wrapped.maxAwaitTime(maxAwaitTime, timeUnit)
+ }
+ override fun resumeAfter(resumeToken: BsonDocument): SyncChangeStreamIterable = apply {
+ wrapped.resumeAfter(resumeToken)
+ }
+ override fun showExpandedEvents(showExpandedEvents: Boolean): SyncChangeStreamIterable = apply {
+ wrapped.showExpandedEvents(showExpandedEvents)
+ }
+ override fun startAfter(startAfter: BsonDocument): SyncChangeStreamIterable = apply {
+ wrapped.startAfter(startAfter)
+ }
+ override fun startAtOperationTime(startAtOperationTime: BsonTimestamp): SyncChangeStreamIterable = apply {
+ wrapped.startAtOperationTime(startAtOperationTime)
+ }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt
new file mode 100644
index 00000000000..53d791bd423
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncClientSession.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.kotlin.client.syncadapter
+
+import com.mongodb.ClientSessionOptions
+import com.mongodb.ServerAddress
+import com.mongodb.TransactionOptions
+import com.mongodb.client.ClientSession as JClientSession
+import com.mongodb.client.TransactionBody
+import com.mongodb.kotlin.client.ClientSession
+import com.mongodb.session.ServerSession
+import org.bson.BsonDocument
+import org.bson.BsonTimestamp
+
+internal class SyncClientSession(internal val wrapped: ClientSession, private val originator: Any) : JClientSession {
+ private val delegate: JClientSession = wrapped.wrapped
+
+ override fun close(): Unit = delegate.close()
+
+ override fun getPinnedServerAddress(): ServerAddress? = delegate.pinnedServerAddress
+
+ override fun getTransactionContext(): Any? = delegate.transactionContext
+
+ override fun setTransactionContext(address: ServerAddress, transactionContext: Any): Unit =
+ delegate.setTransactionContext(address, transactionContext)
+
+ override fun clearTransactionContext(): Unit = delegate.clearTransactionContext()
+
+ override fun getRecoveryToken(): BsonDocument? = delegate.recoveryToken
+
+ override fun setRecoveryToken(recoveryToken: BsonDocument): Unit {
+ delegate.recoveryToken = recoveryToken
+ }
+
+ override fun getOptions(): ClientSessionOptions = delegate.options
+
+ override fun isCausallyConsistent(): Boolean = delegate.isCausallyConsistent
+
+ override fun getOriginator(): Any = originator
+
+ override fun getServerSession(): ServerSession = delegate.serverSession
+
+ override fun getOperationTime(): BsonTimestamp = delegate.operationTime
+
+ override fun advanceOperationTime(operationTime: BsonTimestamp?): Unit =
+ delegate.advanceOperationTime(operationTime)
+
+ override fun advanceClusterTime(clusterTime: BsonDocument?): Unit = delegate.advanceClusterTime(clusterTime)
+
+ override fun setSnapshotTimestamp(snapshotTimestamp: BsonTimestamp?) {
+ delegate.snapshotTimestamp = snapshotTimestamp
+ }
+
+ override fun getSnapshotTimestamp(): BsonTimestamp? = delegate.snapshotTimestamp
+
+ override fun getClusterTime(): BsonDocument = delegate.clusterTime
+
+ override fun hasActiveTransaction(): Boolean = delegate.hasActiveTransaction()
+
+ override fun notifyMessageSent(): Boolean = delegate.notifyMessageSent()
+
+ override fun notifyOperationInitiated(operation: Any): Unit = delegate.notifyOperationInitiated(operation)
+
+ override fun getTransactionOptions(): TransactionOptions = delegate.transactionOptions
+
+ override fun startTransaction(): Unit = delegate.startTransaction()
+
+ override fun startTransaction(transactionOptions: TransactionOptions): Unit =
+ delegate.startTransaction(transactionOptions)
+
+ override fun commitTransaction(): Unit = delegate.commitTransaction()
+
+ override fun abortTransaction(): Unit = delegate.abortTransaction()
+
+ override fun withTransaction(transactionBody: TransactionBody): T =
+ throw UnsupportedOperationException()
+
+ override fun withTransaction(transactionBody: TransactionBody, options: TransactionOptions): T =
+ throw UnsupportedOperationException()
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt
new file mode 100644
index 00000000000..ef580954e20
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.kotlin.client.syncadapter
+
+import com.mongodb.client.DistinctIterable as JDistinctIterable
+import com.mongodb.client.model.Collation
+import com.mongodb.kotlin.client.DistinctIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+import org.bson.conversions.Bson
+
+internal class SyncDistinctIterable(val wrapped: DistinctIterable) :
+ JDistinctIterable, SyncMongoIterable(wrapped) {
+ override fun batchSize(batchSize: Int): SyncDistinctIterable = apply { wrapped.batchSize(batchSize) }
+ override fun filter(filter: Bson?): SyncDistinctIterable = apply { wrapped.filter(filter) }
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncDistinctIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+ override fun collation(collation: Collation?): SyncDistinctIterable = apply { wrapped.collation(collation) }
+ override fun comment(comment: String?): SyncDistinctIterable = apply { wrapped.comment(comment) }
+ override fun comment(comment: BsonValue?): SyncDistinctIterable = apply { wrapped.comment(comment) }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt
new file mode 100644
index 00000000000..c52866f1243
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncFindIterable.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.kotlin.client.syncadapter
+
+import com.mongodb.CursorType
+import com.mongodb.ExplainVerbosity
+import com.mongodb.client.FindIterable as JFindIterable
+import com.mongodb.client.model.Collation
+import com.mongodb.kotlin.client.FindIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+import org.bson.Document
+import org.bson.conversions.Bson
+
+@Suppress("DEPRECATION")
+internal class SyncFindIterable(val wrapped: FindIterable) :
+ JFindIterable, SyncMongoIterable(wrapped) {
+ override fun batchSize(batchSize: Int): SyncFindIterable = apply { wrapped.batchSize(batchSize) }
+ override fun filter(filter: Bson?): SyncFindIterable = apply { wrapped.filter(filter) }
+
+ override fun limit(limit: Int): SyncFindIterable = apply { wrapped.limit(limit) }
+
+ override fun skip(skip: Int): SyncFindIterable = apply { wrapped.skip(skip) }
+
+ override fun allowDiskUse(allowDiskUse: Boolean?): SyncFindIterable = apply {
+ wrapped.allowDiskUse(allowDiskUse)
+ }
+
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncFindIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+
+ override fun maxAwaitTime(maxAwaitTime: Long, timeUnit: TimeUnit): SyncFindIterable = apply {
+ wrapped.maxAwaitTime(maxAwaitTime, timeUnit)
+ }
+
+ override fun projection(projection: Bson?): SyncFindIterable = apply { wrapped.projection(projection) }
+
+ override fun sort(sort: Bson?): SyncFindIterable = apply { wrapped.sort(sort) }
+
+ override fun noCursorTimeout(noCursorTimeout: Boolean): SyncFindIterable = apply {
+ wrapped.noCursorTimeout(noCursorTimeout)
+ }
+
+ @Suppress("OVERRIDE_DEPRECATION")
+ override fun oplogReplay(oplogReplay: Boolean): SyncFindIterable = apply { wrapped.oplogReplay(oplogReplay) }
+
+ override fun partial(partial: Boolean): SyncFindIterable = apply { wrapped.partial(partial) }
+
+ override fun cursorType(cursorType: CursorType): SyncFindIterable = apply { wrapped.cursorType(cursorType) }
+
+ override fun collation(collation: Collation?): SyncFindIterable = apply { wrapped.collation(collation) }
+
+ override fun comment(comment: String?): SyncFindIterable = apply { wrapped.comment(comment) }
+
+ override fun comment(comment: BsonValue?): SyncFindIterable = apply { wrapped.comment(comment) }
+
+ override fun hint(hint: Bson?): SyncFindIterable = apply { wrapped.hint(hint) }
+
+ override fun hintString(hint: String?): SyncFindIterable = apply { wrapped.hintString(hint) }
+
+ override fun let(variables: Bson?): SyncFindIterable = apply { wrapped.let(variables) }
+ override fun max(max: Bson?): SyncFindIterable = apply { wrapped.max(max) }
+
+ override fun min(min: Bson?): SyncFindIterable = apply { wrapped.min(min) }
+
+ override fun returnKey(returnKey: Boolean): SyncFindIterable = apply { wrapped.returnKey(returnKey) }
+
+ override fun showRecordId(showRecordId: Boolean): SyncFindIterable = apply { wrapped.showRecordId(showRecordId) }
+
+ override fun explain(): Document = wrapped.explain()
+
+ override fun explain(verbosity: ExplainVerbosity): Document = wrapped.explain(verbosity)
+
+ override fun explain(explainResultClass: Class): E = wrapped.explain(explainResultClass)
+
+ override fun explain(explainResultClass: Class, verbosity: ExplainVerbosity): E =
+ wrapped.explain(explainResultClass, verbosity)
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt
new file mode 100644
index 00000000000..74579b15a20
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListCollectionsIterable.kt
@@ -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 com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.client.ListCollectionsIterable as JListCollectionsIterable
+import com.mongodb.kotlin.client.ListCollectionsIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+import org.bson.conversions.Bson
+
+internal class SyncListCollectionsIterable(val wrapped: ListCollectionsIterable) :
+ JListCollectionsIterable, SyncMongoIterable(wrapped) {
+
+ override fun batchSize(batchSize: Int): SyncListCollectionsIterable = apply { wrapped.batchSize(batchSize) }
+
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncListCollectionsIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+
+ override fun filter(filter: Bson?): SyncListCollectionsIterable = apply { wrapped.filter(filter) }
+ override fun comment(comment: String?): SyncListCollectionsIterable = apply { wrapped.comment(comment) }
+ override fun comment(comment: BsonValue?): SyncListCollectionsIterable = apply { wrapped.comment(comment) }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt
new file mode 100644
index 00000000000..2e0e662a65d
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListDatabasesIterable.kt
@@ -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 com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.client.ListDatabasesIterable as JListDatabasesIterable
+import com.mongodb.kotlin.client.ListDatabasesIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+import org.bson.conversions.Bson
+
+internal class SyncListDatabasesIterable(val wrapped: ListDatabasesIterable) :
+ JListDatabasesIterable, SyncMongoIterable(wrapped) {
+
+ override fun batchSize(batchSize: Int): SyncListDatabasesIterable = apply { wrapped.batchSize(batchSize) }
+
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncListDatabasesIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+
+ override fun filter(filter: Bson?): SyncListDatabasesIterable = apply { wrapped.filter(filter) }
+
+ override fun nameOnly(nameOnly: Boolean?): SyncListDatabasesIterable = apply { wrapped.nameOnly(nameOnly) }
+
+ override fun authorizedDatabasesOnly(authorizedDatabasesOnly: Boolean?): SyncListDatabasesIterable = apply {
+ wrapped.authorizedDatabasesOnly(authorizedDatabasesOnly)
+ }
+
+ override fun comment(comment: String?): SyncListDatabasesIterable = apply { wrapped.comment(comment) }
+
+ override fun comment(comment: BsonValue?): SyncListDatabasesIterable = apply { wrapped.comment(comment) }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt
new file mode 100644
index 00000000000..b9133970cb3
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncListIndexesIterable.kt
@@ -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 com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.client.ListIndexesIterable as JListIndexesIterable
+import com.mongodb.kotlin.client.ListIndexesIterable
+import java.util.concurrent.TimeUnit
+import org.bson.BsonValue
+
+internal class SyncListIndexesIterable(val wrapped: ListIndexesIterable) :
+ JListIndexesIterable, SyncMongoIterable(wrapped) {
+ override fun batchSize(batchSize: Int): SyncListIndexesIterable = apply { wrapped.batchSize(batchSize) }
+ override fun maxTime(maxTime: Long, timeUnit: TimeUnit): SyncListIndexesIterable = apply {
+ wrapped.maxTime(maxTime, timeUnit)
+ }
+ override fun comment(comment: String?): SyncListIndexesIterable = apply { wrapped.comment(comment) }
+ override fun comment(comment: BsonValue?): SyncListIndexesIterable = apply { wrapped.comment(comment) }
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt
new file mode 100644
index 00000000000..1ddfe72a866
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoChangeStreamCursor.kt
@@ -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 com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.client.MongoChangeStreamCursor as JMongoChangeStreamCursor
+import com.mongodb.kotlin.client.MongoChangeStreamCursor
+import org.bson.BsonDocument
+
+internal class SyncMongoChangeStreamCursor(val wrapped: MongoChangeStreamCursor) :
+ JMongoChangeStreamCursor, SyncMongoCursor(wrapped) {
+ override fun getResumeToken(): BsonDocument? = wrapped.resumeToken
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt
new file mode 100644
index 00000000000..9c3af8af290
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoClient.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.kotlin.client.syncadapter
+
+import com.mongodb.ClientSessionOptions
+import com.mongodb.client.ChangeStreamIterable
+import com.mongodb.client.ClientSession
+import com.mongodb.client.ListDatabasesIterable
+import com.mongodb.client.MongoClient as JMongoClient
+import com.mongodb.client.MongoDatabase
+import com.mongodb.client.MongoIterable
+import com.mongodb.connection.ClusterDescription
+import com.mongodb.kotlin.client.MongoClient
+import org.bson.Document
+import org.bson.conversions.Bson
+
+internal class SyncMongoClient(val wrapped: MongoClient) : JMongoClient {
+ override fun close(): Unit = wrapped.close()
+
+ override fun getDatabase(databaseName: String): MongoDatabase = SyncMongoDatabase(wrapped.getDatabase(databaseName))
+
+ override fun startSession(): ClientSession = SyncClientSession(wrapped.startSession(), this)
+
+ override fun startSession(options: ClientSessionOptions): ClientSession =
+ SyncClientSession(wrapped.startSession(options), this)
+
+ override fun listDatabaseNames(): MongoIterable = SyncMongoIterable(wrapped.listDatabaseNames())
+
+ override fun listDatabaseNames(clientSession: ClientSession): MongoIterable =
+ SyncMongoIterable(wrapped.listDatabaseNames(clientSession.unwrapped()))
+
+ override fun listDatabases(): ListDatabasesIterable = SyncListDatabasesIterable(wrapped.listDatabases())
+
+ override fun listDatabases(clientSession: ClientSession): ListDatabasesIterable =
+ SyncListDatabasesIterable(wrapped.listDatabases(clientSession.unwrapped()))
+
+ override fun listDatabases(resultClass: Class): ListDatabasesIterable =
+ SyncListDatabasesIterable(wrapped.listDatabases(resultClass))
+
+ override fun listDatabases(
+ clientSession: ClientSession,
+ resultClass: Class
+ ): ListDatabasesIterable =
+ SyncListDatabasesIterable(wrapped.listDatabases(clientSession.unwrapped(), resultClass))
+
+ override fun watch(): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch())
+
+ override fun watch(resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(resultClass = resultClass))
+
+ override fun watch(pipeline: MutableList): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(pipeline))
+
+ override fun watch(pipeline: MutableList, resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(pipeline, resultClass))
+
+ override fun watch(clientSession: ClientSession): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped()))
+
+ override fun watch(clientSession: ClientSession, resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), resultClass = resultClass))
+
+ override fun watch(clientSession: ClientSession, pipeline: MutableList): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline))
+
+ override fun watch(
+ clientSession: ClientSession,
+ pipeline: MutableList,
+ resultClass: Class
+ ): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass))
+
+ override fun getClusterDescription(): ClusterDescription = wrapped.clusterDescription
+
+ private fun ClientSession.unwrapped() = (this as SyncClientSession).wrapped
+}
diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt
new file mode 100644
index 00000000000..23a18872afc
--- /dev/null
+++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCollection.kt
@@ -0,0 +1,505 @@
+/*
+ * 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.
+ */
+@file:Suppress("DEPRECATION")
+
+package com.mongodb.kotlin.client.syncadapter
+
+import com.mongodb.MongoNamespace
+import com.mongodb.ReadConcern
+import com.mongodb.ReadPreference
+import com.mongodb.WriteConcern
+import com.mongodb.bulk.BulkWriteResult
+import com.mongodb.client.AggregateIterable
+import com.mongodb.client.ChangeStreamIterable
+import com.mongodb.client.ClientSession
+import com.mongodb.client.DistinctIterable
+import com.mongodb.client.FindIterable
+import com.mongodb.client.ListIndexesIterable
+import com.mongodb.client.MapReduceIterable
+import com.mongodb.client.MongoCollection as JMongoCollection
+import com.mongodb.client.model.BulkWriteOptions
+import com.mongodb.client.model.CountOptions
+import com.mongodb.client.model.CreateIndexOptions
+import com.mongodb.client.model.DeleteOptions
+import com.mongodb.client.model.DropCollectionOptions
+import com.mongodb.client.model.DropIndexOptions
+import com.mongodb.client.model.EstimatedDocumentCountOptions
+import com.mongodb.client.model.FindOneAndDeleteOptions
+import com.mongodb.client.model.FindOneAndReplaceOptions
+import com.mongodb.client.model.FindOneAndUpdateOptions
+import com.mongodb.client.model.IndexModel
+import com.mongodb.client.model.IndexOptions
+import com.mongodb.client.model.InsertManyOptions
+import com.mongodb.client.model.InsertOneOptions
+import com.mongodb.client.model.RenameCollectionOptions
+import com.mongodb.client.model.ReplaceOptions
+import com.mongodb.client.model.UpdateOptions
+import com.mongodb.client.model.WriteModel
+import com.mongodb.client.result.DeleteResult
+import com.mongodb.client.result.InsertManyResult
+import com.mongodb.client.result.InsertOneResult
+import com.mongodb.client.result.UpdateResult
+import com.mongodb.kotlin.client.MongoCollection
+import java.lang.UnsupportedOperationException
+import org.bson.Document
+import org.bson.codecs.configuration.CodecRegistry
+import org.bson.conversions.Bson
+
+@Suppress("OVERRIDE_DEPRECATION")
+internal class SyncMongoCollection(val wrapped: MongoCollection) : JMongoCollection {
+ override fun getNamespace(): MongoNamespace = wrapped.namespace
+
+ override fun getDocumentClass(): Class = wrapped.documentClass
+
+ override fun getCodecRegistry(): CodecRegistry = wrapped.codecRegistry
+
+ override fun getReadPreference(): ReadPreference = wrapped.readPreference
+
+ override fun getWriteConcern(): WriteConcern = wrapped.writeConcern
+
+ override fun getReadConcern(): ReadConcern = wrapped.readConcern
+
+ override fun withDocumentClass(clazz: Class): SyncMongoCollection =
+ SyncMongoCollection(wrapped.withDocumentClass(clazz))
+
+ override fun withCodecRegistry(codecRegistry: CodecRegistry): SyncMongoCollection =
+ SyncMongoCollection(wrapped.withCodecRegistry(codecRegistry))
+
+ override fun withReadPreference(readPreference: ReadPreference): SyncMongoCollection =
+ SyncMongoCollection(wrapped.withReadPreference(readPreference))
+
+ override fun withWriteConcern(writeConcern: WriteConcern): SyncMongoCollection =
+ SyncMongoCollection(wrapped.withWriteConcern(writeConcern))
+
+ override fun withReadConcern(readConcern: ReadConcern): SyncMongoCollection =
+ SyncMongoCollection(wrapped.withReadConcern(readConcern))
+
+ override fun countDocuments(): Long = wrapped.countDocuments()
+
+ override fun countDocuments(filter: Bson): Long = wrapped.countDocuments(filter)
+
+ override fun countDocuments(filter: Bson, options: CountOptions): Long = wrapped.countDocuments(filter, options)
+
+ override fun countDocuments(clientSession: ClientSession): Long = wrapped.countDocuments(clientSession.unwrapped())
+
+ override fun countDocuments(clientSession: ClientSession, filter: Bson): Long =
+ wrapped.countDocuments(clientSession.unwrapped(), filter)
+
+ override fun countDocuments(clientSession: ClientSession, filter: Bson, options: CountOptions): Long =
+ wrapped.countDocuments(clientSession.unwrapped(), filter, options)
+
+ override fun estimatedDocumentCount(): Long = wrapped.estimatedDocumentCount()
+
+ override fun estimatedDocumentCount(options: EstimatedDocumentCountOptions): Long =
+ wrapped.estimatedDocumentCount(options)
+
+ override fun distinct(fieldName: String, resultClass: Class): DistinctIterable =
+ SyncDistinctIterable(wrapped.distinct(fieldName, resultClass = resultClass))
+
+ override fun distinct(fieldName: String, filter: Bson, resultClass: Class): DistinctIterable =
+ SyncDistinctIterable(wrapped.distinct(fieldName, filter, resultClass = resultClass))
+
+ override fun distinct(
+ clientSession: ClientSession,
+ fieldName: String,
+ resultClass: Class
+ ): DistinctIterable =
+ SyncDistinctIterable(wrapped.distinct(clientSession.unwrapped(), fieldName, resultClass = resultClass))
+
+ override fun distinct(
+ clientSession: ClientSession,
+ fieldName: String,
+ filter: Bson,
+ resultClass: Class
+ ): DistinctIterable =
+ SyncDistinctIterable(wrapped.distinct(clientSession.unwrapped(), fieldName, filter, resultClass))
+
+ override fun find(): FindIterable = SyncFindIterable(wrapped.find())
+
+ override fun find(resultClass: Class): FindIterable =
+ SyncFindIterable(wrapped.find(resultClass = resultClass))
+
+ override fun find(filter: Bson): FindIterable = SyncFindIterable(wrapped.find(filter))
+
+ override fun find(filter: Bson, resultClass: Class): FindIterable =
+ SyncFindIterable(wrapped.find(filter, resultClass))
+
+ override fun find(clientSession: ClientSession): FindIterable =
+ SyncFindIterable(wrapped.find(clientSession.unwrapped()))
+
+ override fun find(clientSession: ClientSession, resultClass: Class): FindIterable =
+ SyncFindIterable(wrapped.find(clientSession.unwrapped(), resultClass = resultClass))
+
+ override fun find(clientSession: ClientSession, filter: Bson): FindIterable =
+ SyncFindIterable(wrapped.find(clientSession.unwrapped(), filter))
+
+ override fun find(clientSession: ClientSession, filter: Bson, resultClass: Class): FindIterable =
+ SyncFindIterable(wrapped.find(clientSession.unwrapped(), filter, resultClass))
+
+ override fun aggregate(pipeline: MutableList): AggregateIterable =
+ SyncAggregateIterable(wrapped.aggregate(pipeline))
+
+ override fun aggregate(pipeline: MutableList, resultClass: Class): AggregateIterable =
+ SyncAggregateIterable(wrapped.aggregate(pipeline, resultClass))
+
+ override fun aggregate(clientSession: ClientSession, pipeline: MutableList): AggregateIterable =
+ SyncAggregateIterable(wrapped.aggregate(clientSession.unwrapped(), pipeline))
+
+ override fun aggregate(
+ clientSession: ClientSession,
+ pipeline: MutableList,
+ resultClass: Class
+ ): AggregateIterable = SyncAggregateIterable(wrapped.aggregate(clientSession.unwrapped(), pipeline, resultClass))
+
+ override fun watch(): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch())
+
+ override fun watch(resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(resultClass = resultClass))
+
+ override fun watch(pipeline: MutableList): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(pipeline))
+
+ override fun watch(pipeline: MutableList, resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(pipeline, resultClass))
+
+ override fun watch(clientSession: ClientSession): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped()))
+
+ override fun watch(clientSession: ClientSession, resultClass: Class): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), resultClass = resultClass))
+
+ override fun watch(clientSession: ClientSession, pipeline: MutableList): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline))
+
+ override fun watch(
+ clientSession: ClientSession,
+ pipeline: MutableList,
+ resultClass: Class
+ ): ChangeStreamIterable =
+ SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass))
+
+ override fun mapReduce(mapFunction: String, reduceFunction: String): MapReduceIterable =
+ throw UnsupportedOperationException("No MapReduce support")
+
+ override fun mapReduce(
+ mapFunction: String,
+ reduceFunction: String,
+ resultClass: Class
+ ): MapReduceIterable = throw UnsupportedOperationException("No MapReduce support")
+
+ override fun mapReduce(
+ clientSession: ClientSession,
+ mapFunction: String,
+ reduceFunction: String
+ ): MapReduceIterable = throw UnsupportedOperationException("No MapReduce support")
+
+ override fun mapReduce(
+ clientSession: ClientSession,
+ mapFunction: String,
+ reduceFunction: String,
+ resultClass: Class
+ ): MapReduceIterable = throw UnsupportedOperationException("No MapReduce support")
+
+ override fun deleteOne(filter: Bson): DeleteResult = wrapped.deleteOne(filter)
+
+ override fun deleteOne(filter: Bson, options: DeleteOptions): DeleteResult = wrapped.deleteOne(filter, options)
+
+ override fun deleteOne(clientSession: ClientSession, filter: Bson): DeleteResult =
+ wrapped.deleteOne(clientSession.unwrapped(), filter)
+
+ override fun deleteOne(clientSession: ClientSession, filter: Bson, options: DeleteOptions): DeleteResult =
+ wrapped.deleteOne(clientSession.unwrapped(), filter, options)
+
+ override fun deleteMany(filter: Bson): DeleteResult = wrapped.deleteMany(filter)
+
+ override fun deleteMany(filter: Bson, options: DeleteOptions): DeleteResult = wrapped.deleteMany(filter, options)
+
+ override fun deleteMany(clientSession: ClientSession, filter: Bson): DeleteResult =
+ wrapped.deleteMany(clientSession.unwrapped(), filter)
+
+ override fun deleteMany(clientSession: ClientSession, filter: Bson, options: DeleteOptions): DeleteResult =
+ wrapped.deleteMany(clientSession.unwrapped(), filter, options)
+
+ override fun updateOne(filter: Bson, update: Bson): UpdateResult = wrapped.updateOne(filter, update)
+
+ override fun updateOne(filter: Bson, update: Bson, updateOptions: UpdateOptions): UpdateResult =
+ wrapped.updateOne(filter, update, updateOptions)
+
+ override fun updateOne(clientSession: ClientSession, filter: Bson, update: Bson): UpdateResult =
+ wrapped.updateOne(clientSession.unwrapped(), filter, update)
+
+ override fun updateOne(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: Bson,
+ updateOptions: UpdateOptions
+ ): UpdateResult = wrapped.updateOne(clientSession.unwrapped(), filter, update, updateOptions)
+
+ override fun updateOne(filter: Bson, update: MutableList): UpdateResult =
+ wrapped.updateOne(filter, update)
+
+ override fun updateOne(filter: Bson, update: MutableList, updateOptions: UpdateOptions): UpdateResult =
+ wrapped.updateOne(filter, update, updateOptions)
+
+ override fun updateOne(clientSession: ClientSession, filter: Bson, update: MutableList): UpdateResult =
+ wrapped.updateOne(clientSession.unwrapped(), filter, update)
+
+ override fun updateOne(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: MutableList,
+ updateOptions: UpdateOptions
+ ): UpdateResult = wrapped.updateOne(clientSession.unwrapped(), filter, update, updateOptions)
+
+ override fun updateMany(filter: Bson, update: Bson): UpdateResult = wrapped.updateMany(filter, update)
+
+ override fun updateMany(filter: Bson, update: Bson, updateOptions: UpdateOptions): UpdateResult =
+ wrapped.updateMany(filter, update, updateOptions)
+
+ override fun updateMany(clientSession: ClientSession, filter: Bson, update: Bson): UpdateResult =
+ wrapped.updateMany(clientSession.unwrapped(), filter, update)
+
+ override fun updateMany(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: Bson,
+ updateOptions: UpdateOptions
+ ): UpdateResult = wrapped.updateMany(clientSession.unwrapped(), filter, update, updateOptions)
+
+ override fun updateMany(filter: Bson, update: MutableList): UpdateResult =
+ wrapped.updateMany(filter, update)
+
+ override fun updateMany(filter: Bson, update: MutableList, updateOptions: UpdateOptions): UpdateResult =
+ wrapped.updateMany(filter, update, updateOptions)
+
+ override fun updateMany(clientSession: ClientSession, filter: Bson, update: MutableList): UpdateResult =
+ wrapped.updateMany(clientSession.unwrapped(), filter, update)
+
+ override fun updateMany(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: MutableList,
+ updateOptions: UpdateOptions
+ ): UpdateResult = wrapped.updateMany(clientSession.unwrapped(), filter, update, updateOptions)
+
+ override fun findOneAndDelete(filter: Bson): T? = wrapped.findOneAndDelete(filter)
+
+ override fun findOneAndDelete(filter: Bson, options: FindOneAndDeleteOptions): T? =
+ wrapped.findOneAndDelete(filter, options)
+
+ override fun findOneAndDelete(clientSession: ClientSession, filter: Bson): T? =
+ wrapped.findOneAndDelete(clientSession.unwrapped(), filter)
+
+ override fun findOneAndDelete(clientSession: ClientSession, filter: Bson, options: FindOneAndDeleteOptions): T? =
+ wrapped.findOneAndDelete(clientSession.unwrapped(), filter, options)
+
+ override fun findOneAndUpdate(filter: Bson, update: Bson): T? = wrapped.findOneAndUpdate(filter, update)
+
+ override fun findOneAndUpdate(filter: Bson, update: Bson, options: FindOneAndUpdateOptions): T? =
+ wrapped.findOneAndUpdate(filter, update, options)
+
+ override fun findOneAndUpdate(clientSession: ClientSession, filter: Bson, update: Bson): T? =
+ wrapped.findOneAndUpdate(clientSession.unwrapped(), filter, update)
+
+ override fun findOneAndUpdate(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: Bson,
+ options: FindOneAndUpdateOptions
+ ): T? = wrapped.findOneAndUpdate(clientSession.unwrapped(), filter, update, options)
+
+ override fun findOneAndUpdate(filter: Bson, update: MutableList): T? =
+ wrapped.findOneAndUpdate(filter, update)
+
+ override fun findOneAndUpdate(filter: Bson, update: MutableList, options: FindOneAndUpdateOptions): T? =
+ wrapped.findOneAndUpdate(filter, update, options)
+
+ override fun findOneAndUpdate(clientSession: ClientSession, filter: Bson, update: MutableList): T? =
+ wrapped.findOneAndUpdate(clientSession.unwrapped(), filter, update)
+
+ override fun findOneAndUpdate(
+ clientSession: ClientSession,
+ filter: Bson,
+ update: MutableList,
+ options: FindOneAndUpdateOptions
+ ): T? = wrapped.findOneAndUpdate(clientSession.unwrapped(), filter, update, options)
+
+ override fun drop() = wrapped.drop()
+
+ override fun drop(clientSession: ClientSession) = wrapped.drop(clientSession.unwrapped())
+
+ override fun drop(dropCollectionOptions: DropCollectionOptions) = wrapped.drop(dropCollectionOptions)
+
+ override fun drop(clientSession: ClientSession, dropCollectionOptions: DropCollectionOptions) =
+ wrapped.drop(clientSession.unwrapped(), dropCollectionOptions)
+
+ override fun createIndex(keys: Bson): String = wrapped.createIndex(keys)
+
+ override fun createIndex(keys: Bson, indexOptions: IndexOptions): String = wrapped.createIndex(keys, indexOptions)
+
+ override fun createIndex(clientSession: ClientSession, keys: Bson): String =
+ wrapped.createIndex(clientSession.unwrapped(), keys)
+
+ override fun createIndex(clientSession: ClientSession, keys: Bson, indexOptions: IndexOptions): String =
+ wrapped.createIndex(clientSession.unwrapped(), keys, indexOptions)
+
+ override fun createIndexes(indexes: MutableList): MutableList =
+ wrapped.createIndexes(indexes).toMutableList()
+
+ override fun createIndexes(
+ indexes: MutableList,
+ createIndexOptions: CreateIndexOptions
+ ): MutableList = wrapped.createIndexes(indexes, createIndexOptions).toMutableList()
+
+ override fun createIndexes(clientSession: ClientSession, indexes: MutableList): MutableList =
+ wrapped.createIndexes(clientSession.unwrapped(), indexes).toMutableList()
+
+ override fun createIndexes(
+ clientSession: ClientSession,
+ indexes: MutableList,
+ createIndexOptions: CreateIndexOptions
+ ): MutableList =
+ wrapped.createIndexes(clientSession.unwrapped(), indexes, createIndexOptions).toMutableList()
+
+ override fun listIndexes(): ListIndexesIterable = SyncListIndexesIterable(wrapped.listIndexes())
+
+ override fun listIndexes(resultClass: Class): ListIndexesIterable =
+ SyncListIndexesIterable(wrapped.listIndexes(resultClass = resultClass))
+
+ override fun listIndexes(clientSession: ClientSession): ListIndexesIterable =
+ SyncListIndexesIterable(wrapped.listIndexes(clientSession.unwrapped()))
+
+ override fun