diff --git a/src/libmongoc/tests/unified/entity-map.c b/src/libmongoc/tests/unified/entity-map.c index e12d25c384..ad4f50b110 100644 --- a/src/libmongoc/tests/unified/entity-map.c +++ b/src/libmongoc/tests/unified/entity-map.c @@ -1651,7 +1651,10 @@ session_opts_new (bson_t *bson, bson_error_t *error) } entity_t * -entity_session_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) +entity_session_new (entity_map_t *entity_map, + bson_t *bson, + const bson_t *cluster_time_after_initial_data, + bson_error_t *error) { bson_parser_t *parser = NULL; entity_t *entity = NULL; @@ -1691,6 +1694,9 @@ entity_session_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) if (!session) { goto done; } + if (cluster_time_after_initial_data) { + mongoc_client_session_advance_cluster_time (session, cluster_time_after_initial_data); + } entity->value = session; /* Ending a session destroys the session object. * After a session is ended, match assertions may be made on the lsid. @@ -1785,7 +1791,10 @@ entity_bucket_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) * object immediately. */ bool -entity_map_create (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) +entity_map_create (entity_map_t *entity_map, + bson_t *bson, + const bson_t *cluster_time_after_initial_data, + bson_error_t *error) { bson_iter_t iter; const char *entity_type; @@ -1816,7 +1825,7 @@ entity_map_create (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) } else if (0 == strcmp (entity_type, "collection")) { entity = entity_collection_new (entity_map, &entity_bson, error); } else if (0 == strcmp (entity_type, "session")) { - entity = entity_session_new (entity_map, &entity_bson, error); + entity = entity_session_new (entity_map, &entity_bson, cluster_time_after_initial_data, error); } else if (0 == strcmp (entity_type, "bucket")) { entity = entity_bucket_new (entity_map, &entity_bson, error); } else { diff --git a/src/libmongoc/tests/unified/entity-map.h b/src/libmongoc/tests/unified/entity-map.h index f01bc1b690..dd696dd2e8 100644 --- a/src/libmongoc/tests/unified/entity-map.h +++ b/src/libmongoc/tests/unified/entity-map.h @@ -96,7 +96,7 @@ entity_map_destroy (entity_map_t *em); /* Creates an entry in the entity map based on what is specified in @bson. */ bool -entity_map_create (entity_map_t *em, bson_t *bson, bson_error_t *error); +entity_map_create (entity_map_t *em, bson_t *bson, const bson_t *cluster_time_after_initial_data, bson_error_t *error); /* Steals ownership of changestream. */ bool diff --git a/src/libmongoc/tests/unified/operation.c b/src/libmongoc/tests/unified/operation.c index fda829dc18..cfd9cc4498 100644 --- a/src/libmongoc/tests/unified/operation.c +++ b/src/libmongoc/tests/unified/operation.c @@ -3833,7 +3833,7 @@ operation_create_entities (test_t *test, operation_t *op, result_t *result, bson { bson_t entity; bson_iter_bson (&entity_iter, &entity); - bool create_ret = entity_map_create (test->entity_map, &entity, error); + bool create_ret = entity_map_create (test->entity_map, &entity, test->cluster_time_after_initial_data, error); bson_destroy (&entity); if (!create_ret) { goto done; diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index e2d302ee42..7959105198 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -532,6 +532,7 @@ test_destroy (test_t *test) bson_destroy (test->run_on_requirements); bson_free (test->description); bson_free (test->skip_reason); + bson_destroy (test->cluster_time_after_initial_data); bson_free (test); } @@ -866,8 +867,27 @@ test_setup_initial_data (test_t *test, bson_error_t *error) test_file = test->test_file; test_runner = test_file->test_runner; + mongoc_client_session_t *sess = mongoc_client_start_session (test_runner->internal_client, NULL, error); + if (sess == NULL) { + return false; + } + if (!test_file->initial_data) { - return true; + // Send a "ping" command with the session to get a cluster time. + bson_t opts = BSON_INITIALIZER; + bool ok = mongoc_client_session_append (sess, &opts, error); + ok = ok && mongoc_client_command_with_opts ( + test_runner->internal_client, "db", tmp_bson ("{'ping': 1}"), NULL, &opts, NULL, error); + if (ok) { + // Check for cluster time (not available on standalone). + const bson_t *ct = mongoc_client_session_get_cluster_time (sess); + if (ct) { + test->cluster_time_after_initial_data = bson_copy (ct); + } + } + mongoc_client_session_destroy (sess); + bson_destroy (&opts); + return ok; } BSON_FOREACH (test_file->initial_data, initial_data_iter) @@ -899,6 +919,9 @@ test_setup_initial_data (test_t *test, bson_error_t *error) mongoc_write_concern_set_w (wc, MONGOC_WRITE_CONCERN_W_MAJORITY); bulk_opts = bson_new (); mongoc_write_concern_append (wc, bulk_opts); + if (!mongoc_client_session_append (sess, bulk_opts, error)) { + goto loopexit; + } /* Drop the collection. */ /* Check if the server supports majority write concern on 'drop' and @@ -913,6 +936,12 @@ test_setup_initial_data (test_t *test, bson_error_t *error) BSON_APPEND_INT32 (drop_opts, "serverId", 1); BSON_APPEND_INT32 (create_opts, "serverId", 1); } + if (!mongoc_client_session_append (sess, create_opts, error)) { + goto loopexit; + } + if (!mongoc_client_session_append (sess, drop_opts, error)) { + goto loopexit; + } coll = mongoc_client_get_collection (test_runner->internal_client, database_name, collection_name); if (!mongoc_collection_drop_with_opts (coll, drop_opts, error)) { @@ -972,9 +1001,18 @@ test_setup_initial_data (test_t *test, bson_error_t *error) bson_parser_destroy (parser); mongoc_database_destroy (db); if (!ret) { + mongoc_client_session_destroy (sess); return false; } } + + // Obtain cluster time to advance client sessions. See DRIVERS-2816. + // Check for cluster time (not available on standalone). + const bson_t *ct = mongoc_client_session_get_cluster_time (sess); + if (ct) { + test->cluster_time_after_initial_data = bson_copy (ct); + } + mongoc_client_session_destroy (sess); return true; } @@ -1001,7 +1039,7 @@ test_create_entities (test_t *test, bson_error_t *error) bson_t entity_bson; bson_iter_bson (&iter, &entity_bson); - if (!entity_map_create (test->entity_map, &entity_bson, error)) { + if (!entity_map_create (test->entity_map, &entity_bson, test->cluster_time_after_initial_data, error)) { return false; } } diff --git a/src/libmongoc/tests/unified/runner.h b/src/libmongoc/tests/unified/runner.h index 5a3c59ad05..349b15540f 100644 --- a/src/libmongoc/tests/unified/runner.h +++ b/src/libmongoc/tests/unified/runner.h @@ -63,6 +63,7 @@ typedef struct { entity_map_t *entity_map; failpoint_t *failpoints; bool loop_operation_executed; + bson_t *cluster_time_after_initial_data; } test_t; /* Set server_id to 0 if the failpoint was not against a pinned mongos. */