-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement prose tests checking that neither mongocryptd
nor its client are created when they are not supposed to be
#1113
Conversation
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-sync:test \ | ||
--tests com.mongodb.client.ClientSideEncryptionTest \ | ||
--tests com.mongodb.client.unified.ClientSideEncryptionTest \ | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-reactive-streams:test \ | ||
--tests com.mongodb.reactivestreams.client.ClientSideEncryptionTest \ | ||
--tests com.mongodb.reactivestreams.client.unified.ClientSideEncryptionTest \ | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-scala:integrationTest \ | ||
--tests org.mongodb.scala.ClientSideEncryptionTest | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change together with the assumeFalse/assumeTrue(CRYPT_SHARED_LIB_PATH_SYS_PROP_VALUE != null)
checks in AbstractClientSideEncryptionNotSpawnMongocryptdTest
solves the issue discussed in https://mongodb.slack.com/archives/CFPHLTRMK/p1683160528003019: some of the tests added in this PR not only do not require crypt_shared
, but require the library not to be loaded, which is why they are run separately (in different process) from those that load crypt_shared
(once it is loaded, it can't be unloaded).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad this worked out so easily.
driver-core/src/main/com/mongodb/internal/NoCheckedAutoCloseable.java
Outdated
Show resolved
Hide resolved
@@ -163,8 +163,6 @@ Do the following before running spec tests: | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced this file with the one from mongodb/specifications@33a03f2 (the latest of the spec commits in JAVA-4741 and JAVA-4794).
String cryptSharedLibPath = System.getProperty("org.mongodb.test.crypt.shared.lib.path", ""); | ||
if (!cryptSharedLibPath.isEmpty()) { | ||
extraOptions.put("cryptSharedLibPath", cryptSharedLibPath); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also needed to use this Java system property, so I refactored this code a bit.
kmsProviderProperties -> kmsProviderProperties.put("key", Base64.getDecoder().decode( | ||
"Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZ" | ||
+ "GJkTXVyZG9uSjFk")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also needed to use this key, so I refactored this code a bit. See UnifiedClientEncryptionHelper
.
.keyVaultNamespace(KEY_VAULT_NAMESPACE.getFullName()) | ||
.extraOptions(Stream.of( | ||
new SimpleImmutableEntry<>("cryptSharedLibPath", CRYPT_SHARED_LIB_PATH_SYS_PROP_VALUE), | ||
new SimpleImmutableEntry<>("mongocryptdURI", format("mongodb://%s:%d/db?serverSelectionTimeoutMS=%d", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prose description does not specify serverSelectionTimeoutMS
, however it speeds up the test in a situation when the test fails.
...unctional/com/mongodb/client/AbstractClientSideEncryptionNotCreateMongocryptdClientTest.java
Outdated
Show resolved
Hide resolved
static int findAvailableMongocryptdLoopbackPort() { | ||
try (ServerSocket serverSocket = new ServerSocket()) { | ||
serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); | ||
int foundPort = serverSocket.getLocalPort(); | ||
if (foundPort != DEFAULT_MONGOCRYPTD_PORT) { | ||
return foundPort; | ||
} else { | ||
return findAvailableMongocryptdLoopbackPort(); | ||
} | ||
} catch (IOException e) { | ||
throw new RuntimeException("Failed to find an available port", e); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have just used serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
right away in ConnectionTracker.start
instead of introducing the findAvailableMongocryptdLoopbackPort
method. However, the same approach is not helpful for the tests in AbstractClientSideEncryptionNotSpawnMongocryptdTest
. Additionally, making sure that we never use the default mongocryptd
port in AbstractClientSideEncryptionNotSpawnMongocryptdTest
also improve the isolation between different tests.
To avoid using different approaches, I simply use findAvailableMongocryptdLoopbackPort
in both AbstractClientSideEncryptionNotCreateMongocryptdClientTest
and AbstractClientSideEncryptionNotSpawnMongocryptdTest
.
private void setUpKeyVaultNamespace() { | ||
try (MongoClient client = createMongoClient(MongoClientSettings.builder().build())) { | ||
MongoDatabase db = client.getDatabase(KEY_VAULT_NAMESPACE.getDatabaseName()); | ||
db.drop(); | ||
db.getCollection(KEY_VAULT_NAMESPACE.getCollectionName(), BsonDocument.class) | ||
.withWriteConcern(WriteConcern.MAJORITY) | ||
.insertOne(EXTERNAL_KEY); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prose tests do not require having any keys in the KEY_VAULT_NAMESPACE
: only viaMongocryptdBypassSpawn
attempts to insert an encrypted field, and that insertion is supposed to fail. However, when the driver misbehaves or tests fail (in my case, viaMongocryptdBypassSpawn
was failing if viaLoadingSharedLibrary
runs before it in the same process due to viaLoadingSharedLibrary
loading crypt_shared
), things may get too difficult to understand if the encryption is not properly set up.
// We pick a random available `mongocryptd` port and also include it in the PID file path | ||
// to reduce the chances of different test runs interfering with each other. The interference | ||
// may come from the fact that once spawned, `mongocryptd` stays up and running for some time, | ||
// which may cause failures in other runs if they use the same `mongocryptd` port / PID file. | ||
format("--pidfilepath=bypass-spawning-mongocryptd-%d.pid", mongocryptdSocketAddress.getPort()), | ||
format("--port=%d", mongocryptdSocketAddress.getPort()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment in the code explains why this is done the way it is, even though the prose tests do not require anything like that.
JAVA-4741
… `ConnectionTracker` instead
@jyemin Are you OK with me merging this tests-only PR based on the approval of one reviewer, or do you want to review it? |
I'd like to take a look so please hold off on merging |
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-sync:test \ | ||
--tests com.mongodb.client.ClientSideEncryptionTest \ | ||
--tests com.mongodb.client.unified.ClientSideEncryptionTest \ | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-reactive-streams:test \ | ||
--tests com.mongodb.reactivestreams.client.ClientSideEncryptionTest \ | ||
--tests com.mongodb.reactivestreams.client.unified.ClientSideEncryptionTest \ | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" \ | ||
driver-scala:integrationTest \ | ||
--tests org.mongodb.scala.ClientSideEncryptionTest | ||
--tests "*.ClientEncryption*" --tests "*.ClientSideEncryption*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad this worked out so easily.
driver-core/src/main/com/mongodb/internal/NoCheckedAutoCloseable.java
Outdated
Show resolved
Hide resolved
...unctional/com/mongodb/client/AbstractClientSideEncryptionNotCreateMongocryptdClientTest.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Note that while JAVA-4794 adds one test, the other tests in the same section 8. Bypass Spawning mongocryptd appear to be missing in our codebase, so I also implemented them.
The "Commits" WUI view does something weird to the commit messages. The actual commit messages are something like the following, and point to the ID of the group in the spec:
#8
JAVA-4794#20
JAVA-4741There are small deviations in some tests comparing to their prose description, made to make our life better in a situation when the tests fail. I created DRIVERS-2624 with a PR suggesting to include the changes in the spec.
JAVA-4741
JAVA-4794