diff --git a/NEWS b/NEWS index a6c75915f03..c011f57176d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,12 @@ libmongoc 1.30.0 (Unreleased) ============================= +Fixes: + + * Additional APM events required by the SDAM specification will now be delivered: + * Servers that have seen `server_opening` will now see a `server_closed` prior to `topology_closed`. + * Before `topology_closed`, a `topology_changed` event will transition to `Unknown` topology type. + Deprecated: * Support for Debian 9 and Debian 10. diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index c1c6401fac7..b0565a87712 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -621,6 +621,7 @@ set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-list.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-linux-distro-scanner.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-log.c + ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-log-and-monitor-private.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-matcher.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-matcher-op.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-memcmp.c diff --git a/src/libmongoc/src/mongoc/mongoc-client-pool.c b/src/libmongoc/src/mongoc/mongoc-client-pool.c index 93a3ed795bb..bdb534a3a12 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-pool.c +++ b/src/libmongoc/src/mongoc/mongoc-client-pool.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -54,8 +55,6 @@ struct _mongoc_client_pool_t { bool error_api_set; bool structured_log_opts_set; bool client_initialized; - mongoc_apm_callbacks_t apm_callbacks; - void *apm_context; int32_t error_api_version; mongoc_server_api_t *api; // `last_known_serverids` is a sorted array of uint32_t. @@ -283,7 +282,6 @@ _initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client) pool->client_initialized = true; client->error_api_version = pool->error_api_version; - _mongoc_client_set_apm_callbacks_private (client, &pool->apm_callbacks, pool->apm_context); client->api = mongoc_server_api_copy (pool->api); @@ -577,35 +575,28 @@ bool mongoc_client_pool_set_apm_callbacks (mongoc_client_pool_t *pool, mongoc_apm_callbacks_t *callbacks, void *context) { BSON_ASSERT_PARAM (pool); + BSON_OPTIONAL_PARAM (callbacks); + BSON_OPTIONAL_PARAM (context); - mongoc_topology_t *const topology = BSON_ASSERT_PTR_INLINE (pool)->topology; - mc_tpld_modification tdmod = mc_tpld_modify_begin (topology); - - // Prevent setting callbacks more than once + // Enforce documented thread-safety restrictions if (pool->apm_callbacks_set) { - mc_tpld_modify_drop (tdmod); - MONGOC_ERROR ("Can only set callbacks once"); + MONGOC_ERROR ("mongoc_client_pool_set_apm_callbacks can only be called once per pool"); return false; - } + } else if (pool->client_initialized) { + MONGOC_ERROR ("mongoc_client_pool_set_apm_callbacks can only be called before mongoc_client_pool_pop"); + /* @todo Since 2017 this requirement has been documented but not actually enforced. For now we are leaving it + * unenforced, for backward compatibility. This usage remains unsafe and incorrect. When possible, this should be + * modified to return false without modifying the APM callbacks. */ + mongoc_log_and_monitor_instance_set_apm_callbacks (&pool->topology->log_and_monitor, callbacks, context); + pool->apm_callbacks_set = true; + return true; - // Update callbacks on the pool - if (callbacks) { - pool->apm_callbacks = *callbacks; } else { - pool->apm_callbacks = (mongoc_apm_callbacks_t){0}; + // Now we can be sure no other threads are relying on concurrent access to the instance yet. + mongoc_log_and_monitor_instance_set_apm_callbacks (&pool->topology->log_and_monitor, callbacks, context); + pool->apm_callbacks_set = true; + return true; } - pool->apm_context = context; - - // Update callbacks on the topology - mongoc_topology_set_apm_callbacks (topology, tdmod.new_td, callbacks, context); - - // Signal that we have already set the callbacks - pool->apm_callbacks_set = true; - - // Save our updated topology - mc_tpld_modify_commit (tdmod); - - return true; } bool @@ -618,14 +609,14 @@ mongoc_client_pool_set_structured_log_opts (mongoc_client_pool_t *pool, const mo * and only before the first client is initialized. Structured logging is generally * expected to warn but not quit when encountering initialization errors. */ if (pool->structured_log_opts_set) { - MONGOC_WARNING ("mongoc_client_pool_set_structured_log_opts can only be called once per pool"); + MONGOC_ERROR ("mongoc_client_pool_set_structured_log_opts can only be called once per pool"); return false; } else if (pool->client_initialized) { - MONGOC_WARNING ("mongoc_client_pool_set_structured_log_opts can only be called before mongoc_client_pool_pop"); + MONGOC_ERROR ("mongoc_client_pool_set_structured_log_opts can only be called before mongoc_client_pool_pop"); return false; } else { // Now we can be sure no other threads are relying on concurrent access to the instance yet. - mongoc_topology_set_structured_log_opts (pool->topology, opts); + mongoc_log_and_monitor_instance_set_structured_log_opts (&pool->topology->log_and_monitor, opts); pool->structured_log_opts_set = true; return true; } diff --git a/src/libmongoc/src/mongoc/mongoc-client-private.h b/src/libmongoc/src/mongoc/mongoc-client-private.h index 6549ae031f5..4bcb0358965 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-private.h +++ b/src/libmongoc/src/mongoc/mongoc-client-private.h @@ -107,9 +107,6 @@ struct _mongoc_client_t { mongoc_read_concern_t *read_concern; mongoc_write_concern_t *write_concern; - mongoc_apm_callbacks_t apm_callbacks; - void *apm_context; - int32_t error_api_version; bool error_api_set; @@ -151,9 +148,6 @@ _mongoc_client_get_rr (const char *hostname, mongoc_client_t * _mongoc_client_new_from_topology (mongoc_topology_t *topology); -bool -_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client, mongoc_apm_callbacks_t *callbacks, void *context); - mongoc_stream_t * mongoc_client_default_stream_initiator (const mongoc_uri_t *uri, const mongoc_host_list_t *host, diff --git a/src/libmongoc/src/mongoc/mongoc-client.c b/src/libmongoc/src/mongoc/mongoc-client.c index 4f5192a4588..096e0f9b763 100644 --- a/src/libmongoc/src/mongoc/mongoc-client.c +++ b/src/libmongoc/src/mongoc/mongoc-client.c @@ -1122,7 +1122,7 @@ _mongoc_client_new_from_topology (mongoc_topology_t *topology) } #endif - mongoc_structured_log (topology->structured_log, + mongoc_structured_log (topology->log_and_monitor.structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION, "Client created"); @@ -1646,8 +1646,6 @@ _mongoc_client_retryable_read_command_with_stream (mongoc_client_t *client, * server does not support retryable reads, fall through and allow the * original error to be reported. */ if (is_retryable && _mongoc_read_error_get_type (ret, error, reply) == MONGOC_READ_ERR_RETRY) { - bson_error_t ignored_error; - /* each read command may be retried at most once */ is_retryable = false; @@ -1667,8 +1665,13 @@ _mongoc_client_retryable_read_command_with_stream (mongoc_client_t *client, .has_operation_id = true, .operation_id = parts->assembled.operation_id, }; - retry_server_stream = mongoc_cluster_stream_for_reads ( - &client->cluster, &ss_log_context, parts->read_prefs, parts->assembled.session, ds, NULL, &ignored_error); + retry_server_stream = mongoc_cluster_stream_for_reads (&client->cluster, + &ss_log_context, + parts->read_prefs, + parts->assembled.session, + ds, + NULL /* reply */, + NULL /* error */); mongoc_deprioritized_servers_destroy (ds); } @@ -2165,14 +2168,14 @@ _mongoc_client_monitor_op_killcursors (mongoc_cluster_t *cluster, const char *collection) { bson_t doc; - mongoc_client_t *client; mongoc_apm_command_started_t event; ENTRY; - client = cluster->client; + mongoc_client_t *client = cluster->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - if (!client->apm_callbacks.started) { + if (!log_and_monitor->apm_callbacks.started) { return; } @@ -2189,9 +2192,9 @@ _mongoc_client_monitor_op_killcursors (mongoc_cluster_t *cluster, &server_stream->sd->service_id, server_stream->sd->server_connection_id, NULL, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.started (&event); + log_and_monitor->apm_callbacks.started (&event); mongoc_apm_command_started_cleanup (&event); bson_destroy (&doc); @@ -2207,16 +2210,16 @@ _mongoc_client_monitor_op_killcursors_succeeded (mongoc_cluster_t *cluster, int64_t operation_id, const char *db) { - mongoc_client_t *client; bson_t doc; bson_array_builder_t *cursors_unknown; mongoc_apm_command_succeeded_t event; ENTRY; - client = cluster->client; + mongoc_client_t *client = cluster->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - if (!client->apm_callbacks.succeeded) { + if (!log_and_monitor->apm_callbacks.succeeded) { EXIT; } @@ -2239,9 +2242,9 @@ _mongoc_client_monitor_op_killcursors_succeeded (mongoc_cluster_t *cluster, &server_stream->sd->service_id, server_stream->sd->server_connection_id, false, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.succeeded (&event); + log_and_monitor->apm_callbacks.succeeded (&event); mongoc_apm_command_succeeded_cleanup (&event); bson_destroy (&doc); @@ -2256,15 +2259,15 @@ _mongoc_client_monitor_op_killcursors_failed (mongoc_cluster_t *cluster, int64_t operation_id, const char *db) { - mongoc_client_t *client; bson_t doc; mongoc_apm_command_failed_t event; ENTRY; - client = cluster->client; + mongoc_client_t *client = cluster->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - if (!client->apm_callbacks.failed) { + if (!log_and_monitor->apm_callbacks.failed) { EXIT; } @@ -2285,9 +2288,9 @@ _mongoc_client_monitor_op_killcursors_failed (mongoc_cluster_t *cluster, &server_stream->sd->service_id, server_stream->sd->server_connection_id, false, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.failed (&event); + log_and_monitor->apm_callbacks.failed (&event); mongoc_apm_command_failed_cleanup (&event); bson_destroy (&doc); @@ -2576,33 +2579,6 @@ mongoc_client_set_stream_initiator (mongoc_client_t *client, mongoc_stream_initi } -bool -_mongoc_client_set_apm_callbacks_private (mongoc_client_t *client, mongoc_apm_callbacks_t *callbacks, void *context) -{ - BSON_ASSERT_PARAM (client); - - if (callbacks) { - memcpy (&client->apm_callbacks, callbacks, sizeof (mongoc_apm_callbacks_t)); - } else { - memset (&client->apm_callbacks, 0, sizeof (mongoc_apm_callbacks_t)); - } - - client->apm_context = context; - - /* A client pool sets APM callbacks for the entire pool. */ - if (client->topology->single_threaded) { - mongoc_topology_set_apm_callbacks (client->topology, - /* We are safe to modify the shared_descr directly, since we are - * single-threaded */ - mc_tpld_unsafe_get_mutable (client->topology), - callbacks, - context); - } - - return true; -} - - bool mongoc_client_set_apm_callbacks (mongoc_client_t *client, mongoc_apm_callbacks_t *callbacks, void *context) { @@ -2614,7 +2590,9 @@ mongoc_client_set_apm_callbacks (mongoc_client_t *client, mongoc_apm_callbacks_t return false; } - return _mongoc_client_set_apm_callbacks_private (client, callbacks, context); + mongoc_log_and_monitor_instance_set_apm_callbacks (&client->topology->log_and_monitor, callbacks, context); + + return true; } @@ -2625,7 +2603,7 @@ mongoc_client_set_structured_log_opts (mongoc_client_t *client, const mongoc_str BSON_OPTIONAL_PARAM (opts); if (client->topology->single_threaded) { - mongoc_topology_set_structured_log_opts (client->topology, opts); + mongoc_log_and_monitor_instance_set_structured_log_opts (&client->topology->log_and_monitor, opts); return true; } else { MONGOC_WARNING ("Cannot set structured log options on a pooled client, use " diff --git a/src/libmongoc/src/mongoc/mongoc-cluster.c b/src/libmongoc/src/mongoc/mongoc-cluster.c index 6ef514fe119..60ecee31b7a 100644 --- a/src/libmongoc/src/mongoc/mongoc-cluster.c +++ b/src/libmongoc/src/mongoc/mongoc-cluster.c @@ -498,7 +498,6 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c bool retval; const int32_t request_id = ++cluster->request_id; uint32_t server_id; - mongoc_apm_callbacks_t *callbacks; mongoc_apm_command_started_t started_event; mongoc_apm_command_succeeded_t succeeded_event; mongoc_apm_command_failed_t failed_event; @@ -515,7 +514,8 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c server_stream = cmd->server_stream; server_id = server_stream->sd->id; - callbacks = &cluster->client->apm_callbacks; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &cluster->client->topology->log_and_monitor; + if (!reply) { reply = &reply_local; } @@ -535,7 +535,7 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c } mongoc_structured_log ( - cluster->client->topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command started", @@ -543,11 +543,11 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c server_description (server_stream->sd, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID, SERVICE_ID), cmd (cmd, DATABASE_NAME, COMMAND_NAME, OPERATION_ID, COMMAND)); - if (callbacks->started) { + if (log_and_monitor->apm_callbacks.started) { mongoc_apm_command_started_init_with_cmd ( - &started_event, cmd, request_id, &is_redacted_by_apm, cluster->client->apm_context); + &started_event, cmd, request_id, &is_redacted_by_apm, log_and_monitor->apm_context); - callbacks->started (&started_event); + log_and_monitor->apm_callbacks.started (&started_event); mongoc_apm_command_started_cleanup (&started_event); } @@ -567,7 +567,7 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c } mongoc_structured_log ( - cluster->client->topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command succeeded", @@ -577,7 +577,7 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c cmd (cmd, DATABASE_NAME, COMMAND_NAME, OPERATION_ID), cmd_reply (cmd, cmd->is_acknowledged ? reply : &fake_reply)); - if (callbacks->succeeded) { + if (log_and_monitor->apm_callbacks.succeeded) { mongoc_apm_command_succeeded_init (&succeeded_event, duration, cmd->is_acknowledged ? reply : &fake_reply, @@ -590,9 +590,9 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c &server_stream->sd->service_id, server_stream->sd->server_connection_id, is_redacted_by_apm, - cluster->client->apm_context); + log_and_monitor->apm_context); - callbacks->succeeded (&succeeded_event); + log_and_monitor->apm_callbacks.succeeded (&succeeded_event); mongoc_apm_command_succeeded_cleanup (&succeeded_event); } @@ -601,7 +601,7 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c int64_t duration = bson_get_monotonic_time () - started; mongoc_structured_log ( - cluster->client->topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command failed", @@ -611,7 +611,7 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c cmd (cmd, DATABASE_NAME, COMMAND_NAME, OPERATION_ID), cmd_failure (cmd, reply, error)); - if (callbacks->failed) { + if (log_and_monitor->apm_callbacks.failed) { mongoc_apm_command_failed_init (&failed_event, duration, cmd->command_name, @@ -625,9 +625,9 @@ mongoc_cluster_run_command_monitored (mongoc_cluster_t *cluster, mongoc_cmd_t *c &server_stream->sd->service_id, server_stream->sd->server_connection_id, is_redacted_by_apm, - cluster->client->apm_context); + log_and_monitor->apm_context); - callbacks->failed (&failed_event); + log_and_monitor->apm_callbacks.failed (&failed_event); mongoc_apm_command_failed_cleanup (&failed_event); } } @@ -2042,7 +2042,7 @@ _mongoc_cluster_stream_for_server (mongoc_cluster_t *cluster, goto done; } - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, err_ptr); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, err_ptr); mongoc_cluster_disconnect_node (cluster, server_id); /* This is not load balanced mode, so there are no service IDs associated * with connections. Pass kZeroObjectId to clear the entire connection @@ -2857,7 +2857,7 @@ mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id) mongoc_cluster_disconnect_node (cluster, server_id); tdmod = mc_tpld_modify_begin (topology); /* invalidate_server() is okay if 'server_id' was already removed. */ - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, &error); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, &error); mc_tpld_modify_commit (tdmod); return false; } @@ -2871,7 +2871,7 @@ mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id) mongoc_cmd_parts_init (&parts, cluster->client, "admin", MONGOC_QUERY_SECONDARY_OK, &command); parts.prohibit_lsid = true; - td = mc_tpld_take_ref (cluster->client->topology); + td = mc_tpld_take_ref (topology); server_stream = _mongoc_cluster_create_server_stream (td.ptr, handshake_sd, stream); mc_tpld_drop_ref (&td); @@ -2887,9 +2887,9 @@ mongoc_cluster_check_interval (mongoc_cluster_t *cluster, uint32_t server_id) if (!r) { mc_tpld_modification tdmod; mongoc_cluster_disconnect_node (cluster, server_id); - tdmod = mc_tpld_modify_begin (cluster->client->topology); + tdmod = mc_tpld_modify_begin (topology); /* invalidate_server() is okay if 'server_id' was already removed. */ - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, &error); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, &error); mc_tpld_modify_commit (tdmod); } } @@ -3614,8 +3614,6 @@ mongoc_cluster_run_retryable_write (mongoc_cluster_t *cluster, // selection fails or the selected server does not support retryable writes, fall through and allow the original // error to be reported. if (can_retry && _mongoc_write_error_get_type (reply) == MONGOC_WRITE_ERR_RETRY) { - bson_error_t ignored_error; - can_retry = false; // Only retry once. // Select a server. @@ -3628,7 +3626,7 @@ mongoc_cluster_run_retryable_write (mongoc_cluster_t *cluster, const mongoc_ss_log_context_t ss_log_context = { .operation = cmd->command_name, .has_operation_id = true, .operation_id = cmd->operation_id}; *retry_server_stream = mongoc_cluster_stream_for_writes ( - cluster, &ss_log_context, cmd->session, ds, NULL /* reply */, &ignored_error); + cluster, &ss_log_context, cmd->session, ds, NULL /* reply */, NULL /* error */); mongoc_deprioritized_servers_destroy (ds); } diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c index 0054b28df04..45b115de41e 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c @@ -49,8 +49,10 @@ _mongoc_cursor_monitor_legacy_get_more (mongoc_cursor_t *cursor, mongoc_server_s client = cursor->client; _mongoc_cursor_prepare_getmore_command (cursor, &doc); + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; + mongoc_structured_log ( - client->topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command started", @@ -61,7 +63,7 @@ _mongoc_cursor_monitor_legacy_get_more (mongoc_cursor_t *cursor, mongoc_server_s int64 ("operationId", cursor->operation_id), bson_as_json ("command", &doc)); - if (!client->apm_callbacks.started) { + if (!log_and_monitor->apm_callbacks.started) { /* successful */ bson_destroy (&doc); RETURN (true); @@ -79,9 +81,9 @@ _mongoc_cursor_monitor_legacy_get_more (mongoc_cursor_t *cursor, mongoc_server_s &server_stream->sd->service_id, server_stream->sd->server_connection_id, NULL, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.started (&event); + log_and_monitor->apm_callbacks.started (&event); mongoc_apm_command_started_cleanup (&event); bson_destroy (&doc); bson_free (db); diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index 10f59ecfefd..5f72badd5be 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -646,16 +646,16 @@ _mongoc_cursor_monitor_command (mongoc_cursor_t *cursor, const bson_t *cmd, const char *cmd_name) { - mongoc_client_t *client; mongoc_apm_command_started_t event; char *db; ENTRY; - client = cursor->client; + mongoc_client_t *client = cursor->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; mongoc_structured_log ( - client->topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command started", @@ -666,7 +666,7 @@ _mongoc_cursor_monitor_command (mongoc_cursor_t *cursor, int64 ("operationId", cursor->operation_id), bson_as_json ("command", cmd)); - if (!client->apm_callbacks.started) { + if (!log_and_monitor->apm_callbacks.started) { /* successful */ RETURN (true); } @@ -684,9 +684,9 @@ _mongoc_cursor_monitor_command (mongoc_cursor_t *cursor, &server_stream->sd->service_id, server_stream->sd->server_connection_id, NULL, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.started (&event); + log_and_monitor->apm_callbacks.started (&event); mongoc_apm_command_started_cleanup (&event); bson_free (db); @@ -726,11 +726,11 @@ _mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor, { bson_t docs_array; mongoc_apm_command_succeeded_t event; - mongoc_client_t *client; ENTRY; - client = cursor->client; + mongoc_client_t *client = cursor->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command: * {ok: 1, cursor: {id: 17, ns: "...", first/nextBatch: [ ... docs ... ]}} @@ -748,7 +748,7 @@ _mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor, bson_destroy (&docs_array); - mongoc_structured_log (client->topology->structured_log, + mongoc_structured_log (log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command succeeded", @@ -760,7 +760,7 @@ _mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor, monotonic_time_duration (duration), cmd_name_reply (cmd_name, &reply)); - if (client->apm_callbacks.succeeded) { + if (log_and_monitor->apm_callbacks.succeeded) { mongoc_apm_command_succeeded_init (&event, duration, &reply, @@ -773,9 +773,9 @@ _mongoc_cursor_monitor_succeeded (mongoc_cursor_t *cursor, &stream->sd->service_id, stream->sd->server_connection_id, false, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.succeeded (&event); + log_and_monitor->apm_callbacks.succeeded (&event); mongoc_apm_command_succeeded_cleanup (&event); } @@ -794,11 +794,11 @@ _mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor, const char *cmd_name) { mongoc_apm_command_failed_t event; - mongoc_client_t *client; ENTRY; - client = cursor->client; + mongoc_client_t *client = cursor->client; + const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command: * {ok: 0} @@ -806,7 +806,7 @@ _mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor, bsonBuildDecl (reply, kv ("ok", int32 (0))); char *db = bson_strndup (cursor->ns, cursor->dblen); - mongoc_structured_log (client->topology->structured_log, + mongoc_structured_log (log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Command failed", @@ -818,7 +818,7 @@ _mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor, monotonic_time_duration (duration), bson_as_json ("failure", &reply)); - if (client->apm_callbacks.failed) { + if (log_and_monitor->apm_callbacks.failed) { mongoc_apm_command_failed_init (&event, duration, cmd_name, @@ -832,9 +832,9 @@ _mongoc_cursor_monitor_failed (mongoc_cursor_t *cursor, &stream->sd->service_id, stream->sd->server_connection_id, false, - client->apm_context); + log_and_monitor->apm_context); - client->apm_callbacks.failed (&event); + log_and_monitor->apm_callbacks.failed (&event); mongoc_apm_command_failed_cleanup (&event); } diff --git a/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.c b/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.c new file mode 100644 index 00000000000..b995be74066 --- /dev/null +++ b/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.c @@ -0,0 +1,104 @@ +/* + * Copyright 2009-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include + + +/** + * @brief Initializes the contents of a just-allocated mongoc_log_and_monitor_instance_t + * + * Captures default structured log options from the environment + */ +void +mongoc_log_and_monitor_instance_init (mongoc_log_and_monitor_instance_t *new_instance) +{ + BSON_ASSERT_PARAM (new_instance); + + mongoc_log_and_monitor_instance_set_apm_callbacks (new_instance, NULL, NULL); + + /* This apm_mutex currently only provides explicit exclusion for heartbeat events. It was introduced along with + * background monitoring threads, to retain compatibility with existing code and with the SDAM spec guarantee: + * + * "Events and log messages MUST be published in the order that their corresponding changes are processed in the + * driver. Events MUST NOT be published concurrently for the same topology ID or server ID, but MAY be published + * concurrently for differing topology IDs and server IDs." + * + * We may want to re-examine the scope of this mutex. It's broader than necessary for strict compliance (per-pool + * rather than per-server) and it's unclear that this always provides the necessary exclusion between different event + * types on the same server. + */ + bson_mutex_init (&new_instance->apm_mutex); + + mongoc_structured_log_opts_t *structured_log_opts = mongoc_structured_log_opts_new (); + new_instance->structured_log = mongoc_structured_log_instance_new (structured_log_opts); + mongoc_structured_log_opts_destroy (structured_log_opts); +} + +/** + * @brief Destroy the contents of a mongoc_log_and_monitor_instance_t + * + * Does not try to free the outer memory allocation; it will be part of another object. + * There must not be any other threads using the instance concurrently. + */ +void +mongoc_log_and_monitor_instance_destroy_contents (mongoc_log_and_monitor_instance_t *instance) +{ + BSON_ASSERT_PARAM (instance); + + BSON_ASSERT (instance->structured_log); + mongoc_structured_log_instance_destroy (instance->structured_log); + instance->structured_log = NULL; + + bson_mutex_destroy (&instance->apm_mutex); +} + +/** + * @brief Set the APM callbacks in a mongoc_log_and_monitor_instance_t + * + * There must not be any other threads using the instance concurrently. + * In single threaded mode, this is only valid on the thread that owns the + * client. In pooled mode, it's only valid prior to the first client init. + */ +void +mongoc_log_and_monitor_instance_set_apm_callbacks (mongoc_log_and_monitor_instance_t *instance, + const mongoc_apm_callbacks_t *callbacks, + void *context) +{ + BSON_ASSERT_PARAM (instance); + instance->apm_callbacks = callbacks ? *callbacks : (mongoc_apm_callbacks_t){0}; + instance->apm_context = context; +} + +/** + * @brief Set the structured log options in a mongoc_log_and_monitor_instance_t + * + * Replace the instance's structured logging options. Options are copied. + * + * There must not be any other threads using the instance concurrently. + * In single threaded mode, this is only valid on the thread that owns the + * client. In pooled mode, it's only valid prior to the first client init. + */ +void +mongoc_log_and_monitor_instance_set_structured_log_opts (mongoc_log_and_monitor_instance_t *instance, + const mongoc_structured_log_opts_t *opts) +{ + BSON_ASSERT_PARAM (instance); + mongoc_structured_log_instance_destroy (instance->structured_log); + instance->structured_log = mongoc_structured_log_instance_new (opts); +} diff --git a/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.h b/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.h new file mode 100644 index 00000000000..4c2e6977fa5 --- /dev/null +++ b/src/libmongoc/src/mongoc/mongoc-log-and-monitor-private.h @@ -0,0 +1,58 @@ +/* + * Copyright 2009-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifndef MONGOC_LOG_AND_MONITOR_PRIVATE_H +#define MONGOC_LOG_AND_MONITOR_PRIVATE_H + +#include +#include + +struct mongoc_structured_log_instance_t; +struct mongoc_structured_log_opts_t; + +/* + * @brief Logging and monitoring instance + * + * Includes APM callbacks, APM callback context, and the structured logging instance. + * + * It's owned by mongoc_topology_t on behalf of client/pool and borrowed by topology_description methods. + */ +typedef struct _mongoc_log_and_monitor_instance_t { + bson_mutex_t apm_mutex; + mongoc_apm_callbacks_t apm_callbacks; + void *apm_context; + struct mongoc_structured_log_instance_t *structured_log; +} mongoc_log_and_monitor_instance_t; + +void +mongoc_log_and_monitor_instance_init (mongoc_log_and_monitor_instance_t *new_instance); + +void +mongoc_log_and_monitor_instance_destroy_contents (mongoc_log_and_monitor_instance_t *instance); + +void +mongoc_log_and_monitor_instance_set_apm_callbacks (mongoc_log_and_monitor_instance_t *instance, + const mongoc_apm_callbacks_t *callbacks, + void *context); + +void +mongoc_log_and_monitor_instance_set_structured_log_opts (mongoc_log_and_monitor_instance_t *instance, + const struct mongoc_structured_log_opts_t *opts); + + +#endif /* MONGOC_LOG_AND_MONITOR_PRIVATE_H */ diff --git a/src/libmongoc/src/mongoc/mongoc-server-description-private.h b/src/libmongoc/src/mongoc/mongoc-server-description-private.h index 2c69852fd81..372a0cf440e 100644 --- a/src/libmongoc/src/mongoc/mongoc-server-description-private.h +++ b/src/libmongoc/src/mongoc/mongoc-server-description-private.h @@ -21,6 +21,7 @@ #include #include +#include #define MONGOC_DEFAULT_WIRE_VERSION 0 @@ -69,6 +70,7 @@ struct _mongoc_server_description_t { bson_t last_hello_response; bool has_hello_response; bool hello_ok; + bool opened; const char *connection_address; /* SDAM dictates storing me/hosts/passives/arbiters after being "normalized * to lower-case" Instead, they are stored in the casing they are received, @@ -76,9 +78,6 @@ struct _mongoc_server_description_t { */ const char *me; - /* whether an APM server-opened callback has been fired before */ - bool opened; - const char *set_name; bson_error_t error; mongoc_server_description_type_t type; @@ -210,7 +209,7 @@ mongoc_server_description_filter_tags (const mongoc_server_description_t **descr /* Compares server descriptions following the "Server Description Equality" * rules. Not all fields are considered. */ bool -_mongoc_server_description_equal (mongoc_server_description_t *sd1, mongoc_server_description_t *sd2); +_mongoc_server_description_equal (const mongoc_server_description_t *sd1, const mongoc_server_description_t *sd2); int mongoc_server_description_topology_version_cmp (const bson_t *tv1, const bson_t *tv2); diff --git a/src/libmongoc/src/mongoc/mongoc-server-description.c b/src/libmongoc/src/mongoc/mongoc-server-description.c index 4f349261603..8503bf4f058 100644 --- a/src/libmongoc/src/mongoc/mongoc-server-description.c +++ b/src/libmongoc/src/mongoc/mongoc-server-description.c @@ -125,7 +125,7 @@ mongoc_server_description_init (mongoc_server_description_t *sd, const char *add sd->type = MONGOC_SERVER_UNKNOWN; sd->round_trip_time_msec = MONGOC_RTT_UNSET; sd->generation = 0; - sd->opened = 0; + sd->opened = false; sd->_generation_map_ = mongoc_generation_map_new (); if (!_mongoc_host_list_from_string (&sd->host, address)) { @@ -1092,7 +1092,7 @@ _nullable_strcmp (const char *a, const char *b) } bool -_mongoc_server_description_equal (mongoc_server_description_t *sd1, mongoc_server_description_t *sd2) +_mongoc_server_description_equal (const mongoc_server_description_t *sd1, const mongoc_server_description_t *sd2) { if (sd1->type != sd2->type) { return false; diff --git a/src/libmongoc/src/mongoc/mongoc-server-monitor.c b/src/libmongoc/src/mongoc/mongoc-server-monitor.c index 619356add9c..246a825bac1 100644 --- a/src/libmongoc/src/mongoc/mongoc-server-monitor.c +++ b/src/libmongoc/src/mongoc/mongoc-server-monitor.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -83,8 +84,6 @@ struct _mongoc_server_monitor_t { mongoc_stream_initiator_t initiator; void *initiator_context; int32_t request_id; - mongoc_apm_callbacks_t apm_callbacks; - void *apm_context; mongoc_stream_t *stream; bool more_to_come; @@ -131,19 +130,37 @@ static void _server_monitor_heartbeat_started (mongoc_server_monitor_t *server_monitor, bool awaited) { mongoc_apm_server_heartbeat_started_t event; - MONGOC_DEBUG_ASSERT (!mcommon_mutex_is_locked (&server_monitor->topology->apm_mutex)); + mongoc_log_and_monitor_instance_t *log_and_monitor = &server_monitor->topology->log_and_monitor; - if (!server_monitor->apm_callbacks.server_heartbeat_started) { + { + mc_shared_tpld td = mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (server_monitor)->topology); + bson_oid_t topology_id; + bson_oid_copy (&td.ptr->topology_id, &topology_id); + mc_tpld_drop_ref (&td); + + mongoc_structured_log ( + log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat started", + oid ("topologyId", &topology_id), + server_description (server_monitor->description, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID), + boolean ("awaited", awaited)); + } + + MONGOC_DEBUG_ASSERT (!mcommon_mutex_is_locked (&log_and_monitor->apm_mutex)); + + if (!log_and_monitor->apm_callbacks.server_heartbeat_started) { return; } event.host = &server_monitor->description->host; - event.context = server_monitor->apm_context; + event.context = log_and_monitor->apm_context; MONITOR_LOG (server_monitor, "%s heartbeat started", awaited ? "awaitable" : "regular"); event.awaited = awaited; - bson_mutex_lock (&server_monitor->topology->apm_mutex); - server_monitor->apm_callbacks.server_heartbeat_started (&event); - bson_mutex_unlock (&server_monitor->topology->apm_mutex); + bson_mutex_lock (&log_and_monitor->apm_mutex); + log_and_monitor->apm_callbacks.server_heartbeat_started (&event); + bson_mutex_unlock (&log_and_monitor->apm_mutex); } static void @@ -153,20 +170,39 @@ _server_monitor_heartbeat_succeeded (mongoc_server_monitor_t *server_monitor, bool awaited) { mongoc_apm_server_heartbeat_succeeded_t event; + mongoc_log_and_monitor_instance_t *log_and_monitor = &server_monitor->topology->log_and_monitor; - if (!server_monitor->apm_callbacks.server_heartbeat_succeeded) { + { + mc_shared_tpld td = mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (server_monitor)->topology); + bson_oid_t topology_id; + bson_oid_copy (&td.ptr->topology_id, &topology_id); + mc_tpld_drop_ref (&td); + + mongoc_structured_log ( + log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat succeeded", + oid ("topologyId", &topology_id), + server_description (server_monitor->description, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID), + boolean ("awaited", awaited), + monotonic_time_duration (duration_usec), + bson_as_json ("reply", reply)); + } + + if (!log_and_monitor->apm_callbacks.server_heartbeat_succeeded) { return; } event.host = &server_monitor->description->host; - event.context = server_monitor->apm_context; + event.context = log_and_monitor->apm_context; event.reply = reply; event.duration_usec = duration_usec; MONITOR_LOG (server_monitor, "%s heartbeat succeeded", awaited ? "awaitable" : "regular"); event.awaited = awaited; - bson_mutex_lock (&server_monitor->topology->apm_mutex); - server_monitor->apm_callbacks.server_heartbeat_succeeded (&event); - bson_mutex_unlock (&server_monitor->topology->apm_mutex); + bson_mutex_lock (&log_and_monitor->apm_mutex); + log_and_monitor->apm_callbacks.server_heartbeat_succeeded (&event); + bson_mutex_unlock (&log_and_monitor->apm_mutex); } static void @@ -176,20 +212,39 @@ _server_monitor_heartbeat_failed (mongoc_server_monitor_t *server_monitor, bool awaited) { mongoc_apm_server_heartbeat_failed_t event; + mongoc_log_and_monitor_instance_t *log_and_monitor = &server_monitor->topology->log_and_monitor; - if (!server_monitor->apm_callbacks.server_heartbeat_failed) { + { + mc_shared_tpld td = mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (server_monitor)->topology); + bson_oid_t topology_id; + bson_oid_copy (&td.ptr->topology_id, &topology_id); + mc_tpld_drop_ref (&td); + + mongoc_structured_log ( + log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat failed", + oid ("topologyId", &topology_id), + server_description (server_monitor->description, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID), + boolean ("awaited", awaited), + monotonic_time_duration (duration_usec), + error ("failure", error)); + } + + if (!log_and_monitor->apm_callbacks.server_heartbeat_failed) { return; } event.host = &server_monitor->description->host; - event.context = server_monitor->apm_context; + event.context = log_and_monitor->apm_context; event.error = error; event.duration_usec = duration_usec; MONITOR_LOG (server_monitor, "%s heartbeat failed", awaited ? "awaitable" : "regular"); event.awaited = awaited; - bson_mutex_lock (&server_monitor->topology->apm_mutex); - server_monitor->apm_callbacks.server_heartbeat_failed (&event); - bson_mutex_unlock (&server_monitor->topology->apm_mutex); + bson_mutex_lock (&log_and_monitor->apm_mutex); + log_and_monitor->apm_callbacks.server_heartbeat_failed (&event); + bson_mutex_unlock (&log_and_monitor->apm_mutex); } static void @@ -784,8 +839,12 @@ _update_topology_description (mongoc_server_monitor_t *server_monitor, mongoc_se bson_mutex_lock (&server_monitor->shared.mutex); server_monitor->shared.scan_requested = false; bson_mutex_unlock (&server_monitor->shared.mutex); - mongoc_topology_description_handle_hello ( - tdmod.new_td, server_monitor->server_id, hello_response, description->round_trip_time_msec, &description->error); + mongoc_topology_description_handle_hello (tdmod.new_td, + &topology->log_and_monitor, + server_monitor->server_id, + hello_response, + description->round_trip_time_msec, + &description->error); /* Reconcile server monitors. */ _mongoc_topology_background_monitoring_reconcile (topology, tdmod.new_td); /* Wake threads performing server selection. */ @@ -838,8 +897,6 @@ mongoc_server_monitor_new (mongoc_topology_t *topology, _mongoc_ssl_opts_copy_to (topology->scanner->ssl_opts, server_monitor->ssl_opts, true); } #endif - memcpy (&server_monitor->apm_callbacks, &td->apm_callbacks, sizeof (mongoc_apm_callbacks_t)); - server_monitor->apm_context = td->apm_context; server_monitor->initiator = topology->scanner->initiator; server_monitor->initiator_context = topology->scanner->initiator_context; server_monitor->mode = _server_monitor_get_mode_enum (server_monitor); diff --git a/src/libmongoc/src/mongoc/mongoc-structured-log-private.h b/src/libmongoc/src/mongoc/mongoc-structured-log-private.h index 7f49f79dbab..083fb630497 100644 --- a/src/libmongoc/src/mongoc/mongoc-structured-log-private.h +++ b/src/libmongoc/src/mongoc/mongoc-structured-log-private.h @@ -216,6 +216,16 @@ mongoc_structured_log_instance_destroy (mongoc_structured_log_instance_t *instan .arg1.utf8 = (_key_or_null), \ .arg2.read_prefs = (_value_read_prefs)}, +/** + * @def oid(key, value) + * @brief Structured log item, bson_oid_t + * + * @param key Key as a NUL-terminated const char * expression, or NULL to skip this item. + * @param value OID as a const bson_oid_t * expression, or NULL for a null value. + */ +#define _mongoc_structured_log_item_oid(_key_or_null, _value_oid) \ + {.func = _mongoc_structured_log_append_oid, .arg1.utf8 = (_key_or_null), .arg2.oid = (_value_oid)}, + /** * @def oid_as_hex(key, value) * @brief Structured log item, bson_oid_t converted to a hex string @@ -239,6 +249,18 @@ mongoc_structured_log_instance_destroy (mongoc_structured_log_instance_t *instan #define _mongoc_structured_log_item_bson_as_json(_key_or_null, _value_bson) \ {.func = _mongoc_structured_log_append_bson_as_json, .arg1.utf8 = (_key_or_null), .arg2.bson = (_value_bson)}, +/** + * @def topology_description_as_json(key, value) + * @brief Structured log item, mongoc_topology_description_t serialized into a json string + * + * @param key Key as a NUL-terminated const char * expression, or NULL to skip this item. + * @param value Topology description as a const mongoc_topology_description_t * expression, or NULL for a null value. + */ +#define _mongoc_structured_log_item_topology_description_as_json(_key_or_null, _value_topology_description) \ + {.func = _mongoc_structured_log_append_topology_description_as_json, \ + .arg1.utf8 = (_key_or_null), \ + .arg2.topology_description = (_value_topology_description)}, + /** * @def topology_as_description_json(key, topology) * @brief Structured log item, current description from a mongoc_topology_t serialized into a json string @@ -372,11 +394,12 @@ struct mongoc_structured_log_builder_stage_t { } arg1; union { bool boolean; - bson_oid_t *oid; const bson_error_t *error; + const bson_oid_t *oid; const bson_t *bson; const char *utf8; const mongoc_read_prefs_t *read_prefs; + const struct _mongoc_topology_description_t *topology_description; const struct _mongoc_topology_t *topology; double double_value; int32_t int32; @@ -456,6 +479,11 @@ _mongoc_structured_log_append_oid_as_hex (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, const mongoc_structured_log_opts_t *opts); +const mongoc_structured_log_builder_stage_t * +_mongoc_structured_log_append_oid (bson_t *bson, + const mongoc_structured_log_builder_stage_t *stage, + const mongoc_structured_log_opts_t *opts); + const mongoc_structured_log_builder_stage_t * _mongoc_structured_log_append_bson_as_json (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, @@ -501,6 +529,11 @@ _mongoc_structured_log_append_server_description (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, const mongoc_structured_log_opts_t *opts); +const mongoc_structured_log_builder_stage_t * +_mongoc_structured_log_append_topology_description_as_json (bson_t *bson, + const mongoc_structured_log_builder_stage_t *stage, + const mongoc_structured_log_opts_t *opts); + const mongoc_structured_log_builder_stage_t * _mongoc_structured_log_append_topology_as_description_json (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, diff --git a/src/libmongoc/src/mongoc/mongoc-structured-log.c b/src/libmongoc/src/mongoc/mongoc-structured-log.c index 8fc2aebc0e9..d8c0d2273ae 100644 --- a/src/libmongoc/src/mongoc/mongoc-structured-log.c +++ b/src/libmongoc/src/mongoc/mongoc-structured-log.c @@ -742,6 +742,24 @@ _mongoc_structured_log_append_boolean (bson_t *bson, return stage + 1; } +const mongoc_structured_log_builder_stage_t * +_mongoc_structured_log_append_oid (bson_t *bson, + const mongoc_structured_log_builder_stage_t *stage, + const mongoc_structured_log_opts_t *opts) +{ + BSON_UNUSED (opts); + const char *key_or_null = stage->arg1.utf8; + const bson_oid_t *oid_or_null = stage->arg2.oid; + if (key_or_null) { + if (oid_or_null) { + bson_append_oid (bson, key_or_null, -1, oid_or_null); + } else { + bson_append_null (bson, key_or_null, -1); + } + } + return stage + 1; +} + const mongoc_structured_log_builder_stage_t * _mongoc_structured_log_append_oid_as_hex (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, @@ -1022,10 +1040,9 @@ _mongoc_structured_log_append_server_description (bson_t *bson, return stage + 1; } -const mongoc_structured_log_builder_stage_t * -_mongoc_structured_log_append_topology_as_description_json (bson_t *bson, - const mongoc_structured_log_builder_stage_t *stage, - const mongoc_structured_log_opts_t *opts) +static mcommon_string_t * +_mongoc_structured_log_topology_description_as_json (const mongoc_topology_description_t *td, + const mongoc_structured_log_opts_t *opts) { const mongoc_topology_description_content_flags_t td_flags = MONGOC_TOPOLOGY_DESCRIPTION_CONTENT_FLAG_TYPE | MONGOC_TOPOLOGY_DESCRIPTION_CONTENT_FLAG_SET_NAME | @@ -1038,21 +1055,29 @@ _mongoc_structured_log_append_topology_as_description_json (bson_t *bson, const mongoc_server_description_content_flags_t server_flags = MONGOC_SERVER_DESCRIPTION_CONTENT_FLAG_TYPE | MONGOC_SERVER_DESCRIPTION_CONTENT_FLAG_ADDRESS; + bson_t doc = BSON_INITIALIZER; + mongoc_topology_description_append_contents_to_bson (td, &doc, td_flags, server_flags); + mcommon_string_t *result = _mongoc_structured_log_document_as_truncated_json (&doc, opts); + bson_destroy (&doc); + return result; +} + +const mongoc_structured_log_builder_stage_t * +_mongoc_structured_log_append_topology_as_description_json (bson_t *bson, + const mongoc_structured_log_builder_stage_t *stage, + const mongoc_structured_log_opts_t *opts) +{ const char *key_or_null = stage->arg1.utf8; const mongoc_topology_t *topology_or_null = stage->arg2.topology; if (key_or_null) { if (topology_or_null) { mc_shared_tpld td = mc_tpld_take_ref (topology_or_null); - bson_t inner_bson = BSON_INITIALIZER; - mongoc_topology_description_append_contents_to_bson (td.ptr, &inner_bson, td_flags, server_flags); - mcommon_string_t *json = _mongoc_structured_log_document_as_truncated_json (&inner_bson, opts); + mcommon_string_t *json = _mongoc_structured_log_topology_description_as_json (td.ptr, opts); if (json) { BSON_ASSERT (json->len <= (uint32_t) INT_MAX); bson_append_utf8 (bson, key_or_null, -1, json->str, (int) json->len); mcommon_string_destroy (json); } - // If invalid BSON was found in the input, the key is not logged. - bson_destroy (&inner_bson); mc_tpld_drop_ref (&td); } else { bson_append_null (bson, key_or_null, -1); @@ -1061,6 +1086,29 @@ _mongoc_structured_log_append_topology_as_description_json (bson_t *bson, return stage + 1; } +const mongoc_structured_log_builder_stage_t * +_mongoc_structured_log_append_topology_description_as_json (bson_t *bson, + const mongoc_structured_log_builder_stage_t *stage, + const mongoc_structured_log_opts_t *opts) +{ + const char *key_or_null = stage->arg1.utf8; + const mongoc_topology_description_t *topology_description_or_null = stage->arg2.topology_description; + if (key_or_null) { + if (topology_description_or_null) { + mcommon_string_t *json = + _mongoc_structured_log_topology_description_as_json (topology_description_or_null, opts); + if (json) { + BSON_ASSERT (json->len <= (uint32_t) INT_MAX); + bson_append_utf8 (bson, key_or_null, -1, json->str, (int) json->len); + mcommon_string_destroy (json); + } + } else { + bson_append_null (bson, key_or_null, -1); + } + } + return stage + 1; +} + const mongoc_structured_log_builder_stage_t * _mongoc_structured_log_append_read_prefs (bson_t *bson, const mongoc_structured_log_builder_stage_t *stage, diff --git a/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c b/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c index 10b5ec1ba01..c42b32b54df 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c +++ b/src/libmongoc/src/mongoc/mongoc-topology-background-monitoring.c @@ -146,7 +146,7 @@ _mongoc_topology_background_monitoring_start (mongoc_topology_t *topology) tdmod = mc_tpld_modify_begin (topology); _mongoc_handshake_freeze (); - _mongoc_topology_description_monitor_opening (tdmod.new_td); + _mongoc_topology_description_monitor_opening (tdmod.new_td, &topology->log_and_monitor); if (tdmod.new_td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) { /* Do not proceed to start monitoring threads. */ TRACE ("%s", "disabling monitoring for load balanced topology"); diff --git a/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h b/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h index b004dedde28..234cd4e0d07 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h +++ b/src/libmongoc/src/mongoc/mongoc-topology-description-apm-private.h @@ -21,6 +21,7 @@ #include #include +#include /* Application Performance Monitoring for topology events, complies with the * SDAM Monitoring Spec: @@ -31,26 +32,32 @@ void _mongoc_topology_description_monitor_server_opening (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_server_description_t *sd); void _mongoc_topology_description_monitor_server_changed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *prev_sd, const mongoc_server_description_t *new_sd); void _mongoc_topology_description_monitor_server_closed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *sd); -/* td is not const: we set its "opened" field here */ +/* td is not const: we set its "opened" flag here */ void -_mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td); +_mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor); void _mongoc_topology_description_monitor_changed (const mongoc_topology_description_t *prev_td, - const mongoc_topology_description_t *new_td); + const mongoc_topology_description_t *new_td, + const mongoc_log_and_monitor_instance_t *log_and_monitor); void -_mongoc_topology_description_monitor_closed (const mongoc_topology_description_t *td); +_mongoc_topology_description_monitor_closed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor); #endif /* MONGOC_TOPOLOGY_DESCRIPTION_APM_PRIVATE_H */ diff --git a/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c b/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c index b87ee1c0924..3ec96dd1bce 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c +++ b/src/libmongoc/src/mongoc/mongoc-topology-description-apm.c @@ -16,6 +16,7 @@ #include #include +#include /* Application Performance Monitoring for topology events, complies with the * SDAM Monitoring Spec: @@ -27,26 +28,40 @@ /* ServerOpeningEvent */ void _mongoc_topology_description_monitor_server_opening (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_server_description_t *sd) { - if (td->apm_callbacks.server_opening && !sd->opened) { - mongoc_apm_server_opening_t event; - - bson_oid_copy (&td->topology_id, &event.topology_id); - event.host = &sd->host; - event.context = td->apm_context; + /* Topology opening will be deferred until server selection, and + * server opening must be deferred until topology opening. */ + if (td->opened && !sd->opened) { sd->opened = true; - td->apm_callbacks.server_opening (&event); + + mongoc_structured_log (log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Starting server monitoring", + oid ("topologyId", &td->topology_id), + server_description (sd, SERVER_HOST, SERVER_PORT)); + + if (log_and_monitor->apm_callbacks.server_opening) { + mongoc_apm_server_opening_t event; + + bson_oid_copy (&td->topology_id, &event.topology_id); + event.host = &sd->host; + event.context = log_and_monitor->apm_context; + log_and_monitor->apm_callbacks.server_opening (&event); + } } } /* ServerDescriptionChangedEvent */ void _mongoc_topology_description_monitor_server_changed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *prev_sd, const mongoc_server_description_t *new_sd) { - if (td->apm_callbacks.server_changed) { + if (log_and_monitor->apm_callbacks.server_changed) { mongoc_apm_server_changed_t event; /* address is same in previous and new sd */ @@ -54,63 +69,74 @@ _mongoc_topology_description_monitor_server_changed (const mongoc_topology_descr event.host = &new_sd->host; event.previous_description = prev_sd; event.new_description = new_sd; - event.context = td->apm_context; - td->apm_callbacks.server_changed (&event); + event.context = log_and_monitor->apm_context; + log_and_monitor->apm_callbacks.server_changed (&event); } } /* ServerClosedEvent */ void _mongoc_topology_description_monitor_server_closed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *sd) { - if (td->apm_callbacks.server_closed) { + if (!sd->opened) { + return; + } + + mongoc_structured_log (log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Stopped server monitoring", + oid ("topologyId", &td->topology_id), + server_description (sd, SERVER_HOST, SERVER_PORT)); + + if (log_and_monitor->apm_callbacks.server_closed) { mongoc_apm_server_closed_t event; bson_oid_copy (&td->topology_id, &event.topology_id); event.host = &sd->host; - event.context = td->apm_context; - td->apm_callbacks.server_closed (&event); + event.context = log_and_monitor->apm_context; + log_and_monitor->apm_callbacks.server_closed (&event); } } /* Send TopologyOpeningEvent when first called on this topology description. - * td is not const: we set its "opened" field here */ + * td is not const: we mark it as "opened" by the current log-and-monitor instance. */ void -_mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td) +_mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor) { - mongoc_topology_description_t *prev_td = NULL; - mongoc_server_description_t *sd; - if (td->opened) { return; } + td->opened = true; - if (td->apm_callbacks.topology_changed) { - /* prepare to call monitor_changed */ - prev_td = BSON_ALIGNED_ALLOC0 (mongoc_topology_description_t); - mongoc_topology_description_init (prev_td, td->heartbeat_msec); - } + // The initial 'previous' topology description, with Unknown type + mongoc_topology_description_t *prev_td = BSON_ALIGNED_ALLOC0 (mongoc_topology_description_t); + mongoc_topology_description_init (prev_td, td->heartbeat_msec); - td->opened = true; + mongoc_structured_log (log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Starting topology monitoring", + oid ("topologyId", &td->topology_id)); - if (td->apm_callbacks.topology_opening) { + if (log_and_monitor->apm_callbacks.topology_opening) { mongoc_apm_topology_opening_t event; bson_oid_copy (&td->topology_id, &event.topology_id); - event.context = td->apm_context; - td->apm_callbacks.topology_opening (&event); + event.context = log_and_monitor->apm_context; + log_and_monitor->apm_callbacks.topology_opening (&event); } - if (td->apm_callbacks.topology_changed) { - /* send initial description-changed event */ - _mongoc_topology_description_monitor_changed (prev_td, td); - } + /* send initial description-changed event */ + _mongoc_topology_description_monitor_changed (prev_td, td, log_and_monitor); for (size_t i = 0u; i < mc_tpld_servers (td)->items_len; i++) { - sd = mongoc_set_get_item (mc_tpld_servers (td), i); - _mongoc_topology_description_monitor_server_opening (td, sd); + mongoc_server_description_t *sd = mongoc_set_get_item (mc_tpld_servers (td), i); + _mongoc_topology_description_monitor_server_opening (td, log_and_monitor, sd); } /* If this is a load balanced topology: @@ -124,19 +150,17 @@ _mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td) /* LoadBalanced deployments must have exactly one host listed. Otherwise, * an error would have occurred when constructing the topology. */ BSON_ASSERT (mc_tpld_servers (td)->items_len == 1); - sd = mongoc_set_get_item (mc_tpld_servers (td), 0); + mongoc_server_description_t *sd = mongoc_set_get_item (mc_tpld_servers (td), 0); prev_sd = mongoc_server_description_new_copy (sd); BSON_ASSERT (prev_sd); - if (td->apm_callbacks.topology_changed) { - mongoc_topology_description_cleanup (prev_td); - _mongoc_topology_description_copy_to (td, prev_td); - } + + mongoc_topology_description_cleanup (prev_td); + _mongoc_topology_description_copy_to (td, prev_td); + sd->type = MONGOC_SERVER_LOAD_BALANCER; - _mongoc_topology_description_monitor_server_changed (td, prev_sd, sd); + _mongoc_topology_description_monitor_server_changed (td, log_and_monitor, prev_sd, sd); mongoc_server_description_destroy (prev_sd); - if (td->apm_callbacks.topology_changed) { - _mongoc_topology_description_monitor_changed (prev_td, td); - } + _mongoc_topology_description_monitor_changed (prev_td, td, log_and_monitor); } if (prev_td) { @@ -148,38 +172,54 @@ _mongoc_topology_description_monitor_opening (mongoc_topology_description_t *td) /* TopologyDescriptionChangedEvent */ void _mongoc_topology_description_monitor_changed (const mongoc_topology_description_t *prev_td, - const mongoc_topology_description_t *new_td) + const mongoc_topology_description_t *new_td, + const mongoc_log_and_monitor_instance_t *log_and_monitor) { - if (new_td->apm_callbacks.topology_changed) { + mongoc_structured_log (log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Topology description changed", + oid ("topologyId", &new_td->topology_id), + topology_description_as_json ("previousDescription", prev_td), + topology_description_as_json ("newDescription", new_td)); + + if (log_and_monitor->apm_callbacks.topology_changed) { mongoc_apm_topology_changed_t event; /* callbacks, context, and id are the same in previous and new td */ bson_oid_copy (&new_td->topology_id, &event.topology_id); - event.context = new_td->apm_context; + event.context = log_and_monitor->apm_context; event.previous_description = prev_td; event.new_description = new_td; - new_td->apm_callbacks.topology_changed (&event); + log_and_monitor->apm_callbacks.topology_changed (&event); } } /* TopologyClosedEvent */ void -_mongoc_topology_description_monitor_closed (const mongoc_topology_description_t *td) +_mongoc_topology_description_monitor_closed (const mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor) { - if (td->apm_callbacks.topology_closed) { - mongoc_apm_topology_closed_t event; + // Expected preconditions for 'closed' events: + // (mongoc_topology_destroy() carries out these transitions prior to close of monitoring.) + BSON_ASSERT (td->type == MONGOC_TOPOLOGY_UNKNOWN); + BSON_ASSERT (mc_tpld_servers_const (td)->items_len == 0); + + if (!td->opened) { + return; + } - if (td->type == MONGOC_TOPOLOGY_LOAD_BALANCED) { - const mongoc_server_description_t *sd; + mongoc_structured_log (log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Stopped topology monitoring", + oid ("topologyId", &td->topology_id)); - /* LoadBalanced deployments must have exactly one host listed. */ - BSON_ASSERT (mc_tpld_servers_const (td)->items_len == 1); - sd = mongoc_set_get_item_const (mc_tpld_servers_const (td), 0); - _mongoc_topology_description_monitor_server_closed (td, sd); - } + if (log_and_monitor->apm_callbacks.topology_closed) { + mongoc_apm_topology_closed_t event; bson_oid_copy (&td->topology_id, &event.topology_id); - event.context = td->apm_context; - td->apm_callbacks.topology_closed (&event); + event.context = log_and_monitor->apm_context; + log_and_monitor->apm_callbacks.topology_closed (&event); } } diff --git a/src/libmongoc/src/mongoc/mongoc-topology-description-private.h b/src/libmongoc/src/mongoc/mongoc-topology-description-private.h index 9a8b646eba5..aa7e3916a90 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-description-private.h +++ b/src/libmongoc/src/mongoc/mongoc-topology-description-private.h @@ -26,6 +26,7 @@ #include #include #include +#include typedef enum { @@ -40,7 +41,6 @@ typedef enum { struct _mongoc_topology_description_t { bson_oid_t topology_id; - bool opened; mongoc_topology_description_type_t type; int64_t heartbeat_msec; mongoc_set_t *_servers_; @@ -51,6 +51,7 @@ struct _mongoc_topology_description_t { uint32_t max_server_id; int32_t max_hosts; /* srvMaxHosts */ bool stale; + bool opened; unsigned int rand_seed; /* the greatest seen cluster time, for a MongoDB 3.6+ sharded cluster. @@ -60,9 +61,6 @@ struct _mongoc_topology_description_t { /* smallest seen logicalSessionTimeoutMinutes, or -1 if any server has no * logicalSessionTimeoutMinutes. see Server Discovery and Monitoring Spec */ int64_t session_timeout_minutes; - - mongoc_apm_callbacks_t apm_callbacks; - void *apm_context; }; typedef enum { MONGOC_SS_READ, MONGOC_SS_WRITE, MONGOC_SS_AGGREGATE_WITH_WRITE } mongoc_ss_optype_t; @@ -109,6 +107,7 @@ mongoc_topology_description_cleanup (mongoc_topology_description_t *description) void mongoc_topology_description_handle_hello (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, uint32_t server_id, const bson_t *hello_response, int64_t rtt_msec, @@ -141,6 +140,9 @@ _mongoc_topology_description_validate_max_staleness (const mongoc_topology_descr int64_t max_staleness_seconds, bson_error_t *error); +const mongoc_server_description_t * +_mongoc_topology_description_has_primary (const mongoc_topology_description_t *description); + void mongoc_topology_description_suitable_servers (mongoc_array_t *set, /* OUT */ mongoc_ss_optype_t optype, @@ -155,11 +157,13 @@ mongoc_topology_description_has_data_node (const mongoc_topology_description_t * void mongoc_topology_description_invalidate_server (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, uint32_t id, const bson_error_t *error /* IN */); bool mongoc_topology_description_add_server (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const char *server, uint32_t *id /* OUT */); @@ -167,7 +171,9 @@ void mongoc_topology_description_update_cluster_time (mongoc_topology_description_t *td, const bson_t *reply); void -mongoc_topology_description_reconcile (mongoc_topology_description_t *td, mongoc_host_list_t *host_list); +mongoc_topology_description_reconcile (mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, + mongoc_host_list_t *host_list); /** * @brief Invalidate open connnections to a server. diff --git a/src/libmongoc/src/mongoc/mongoc-topology-description.c b/src/libmongoc/src/mongoc/mongoc-topology-description.c index e00450ac27d..5ca344ec619 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-description.c +++ b/src/libmongoc/src/mongoc/mongoc-topology-description.c @@ -84,7 +84,6 @@ mongoc_topology_description_init (mongoc_topology_description_t *description, in memset (description, 0, sizeof (*description)); bson_oid_init (&description->topology_id, NULL); - description->opened = false; description->type = MONGOC_TOPOLOGY_UNKNOWN; description->heartbeat_msec = heartbeat_msec; description->_servers_ = mongoc_set_new (8, _mongoc_topology_server_dtor, NULL); @@ -147,9 +146,6 @@ _mongoc_topology_description_copy_to (const mongoc_topology_description_t *src, dst->max_server_id = src->max_server_id; dst->max_hosts = src->max_hosts; dst->stale = src->stale; - memcpy (&dst->apm_callbacks, &src->apm_callbacks, sizeof (mongoc_apm_callbacks_t)); - - dst->apm_context = src->apm_context; bson_copy_to (&src->cluster_time, &dst->cluster_time); @@ -287,7 +283,7 @@ _mongoc_topology_description_has_primary_cb (const void *item, void *ctx /* OUT * *-------------------------------------------------------------------------- */ -static const mongoc_server_description_t * +const mongoc_server_description_t * _mongoc_topology_description_has_primary (const mongoc_topology_description_t *description) { mongoc_server_description_t *primary = NULL; @@ -1121,12 +1117,13 @@ mongoc_topology_description_server_by_id_const (const mongoc_topology_descriptio */ static void _mongoc_topology_description_remove_server (mongoc_topology_description_t *description, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { BSON_ASSERT (description); BSON_ASSERT (server); - _mongoc_topology_description_monitor_server_closed (description, server); + _mongoc_topology_description_monitor_server_closed (description, log_and_monitor, server); mongoc_set_rm (mc_tpld_servers (description), server->id); /* Check if removing server resulted in an empty set of servers */ @@ -1318,9 +1315,11 @@ _update_rs_type (mongoc_topology_description_t *topology) */ static void _mongoc_topology_description_check_if_has_primary (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { BSON_UNUSED (server); + BSON_UNUSED (log_and_monitor); _update_rs_type (topology); } @@ -1343,6 +1342,7 @@ _mongoc_topology_description_check_if_has_primary (mongoc_topology_description_t */ void mongoc_topology_description_invalidate_server (mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, uint32_t id, const bson_error_t *error /* IN */) { @@ -1354,7 +1354,7 @@ mongoc_topology_description_invalidate_server (mongoc_topology_description_t *td } /* send NULL hello reply */ - mongoc_topology_description_handle_hello (td, id, NULL, MONGOC_RTT_UNSET, error); + mongoc_topology_description_handle_hello (td, log_and_monitor, id, NULL, MONGOC_RTT_UNSET, error); } /* @@ -1376,6 +1376,7 @@ mongoc_topology_description_invalidate_server (mongoc_topology_description_t *td */ bool mongoc_topology_description_add_server (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const char *server, uint32_t *id /* OUT */) { @@ -1394,9 +1395,13 @@ mongoc_topology_description_add_server (mongoc_topology_description_t *topology, mongoc_set_add (mc_tpld_servers (topology), server_id, description); - /* if we're in topology_new then no callbacks are registered and this is - * a no-op. later, if we discover a new RS member this sends an event. */ - _mongoc_topology_description_monitor_server_opening (topology, description); + /* Note that libmongoc defers topology 'opening' until server selection or background monitoring begins, + * and server monitoring must correspondingly only be 'opened' after the API has seen topology monitoring open. + * + * If the topology is already opened, we will send server opening events immediately. + * Otherwise this has no effect, and server opening events will be sent later by + * _mongoc_topology_description_monitor_opening. */ + _mongoc_topology_description_monitor_server_opening (topology, log_and_monitor, description); } if (id) { @@ -1469,6 +1474,7 @@ mongoc_topology_description_update_cluster_time (mongoc_topology_description_t * static void _mongoc_topology_description_add_new_servers (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { bson_iter_t member_iter; @@ -1483,7 +1489,7 @@ _mongoc_topology_description_add_new_servers (mongoc_topology_description_t *top BSON_ASSERT (bson_iter_init (&member_iter, rs_members[i])); while (bson_iter_next (&member_iter)) { - mongoc_topology_description_add_server (topology, bson_iter_utf8 (&member_iter, NULL), NULL); + mongoc_topology_description_add_server (topology, log_and_monitor, bson_iter_utf8 (&member_iter, NULL), NULL); } } } @@ -1513,6 +1519,7 @@ _mongoc_topology_description_invalidate_primaries_cb (void *item, void *ctx) /* Remove and destroy all replica set members not in primary's hosts lists */ static void _mongoc_topology_description_remove_unreported_servers (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *primary) { mongoc_array_t to_remove; @@ -1537,7 +1544,7 @@ _mongoc_topology_description_remove_unreported_servers (mongoc_topology_descript for (size_t i = 0u; i < to_remove.len; i++) { const mongoc_server_description_t *member = _mongoc_array_index (&to_remove, mongoc_server_description_t *, i); - _mongoc_topology_description_remove_server (topology, member); + _mongoc_topology_description_remove_server (topology, log_and_monitor, member); } _mongoc_array_destroy (&to_remove); @@ -1606,6 +1613,7 @@ _mongoc_topology_description_matches_me (const mongoc_server_description_t *serv */ static void _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { mongoc_primary_and_topology_t data; @@ -1626,7 +1634,7 @@ _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description if (!topology->set_name) { topology->set_name = bson_strdup (server->set_name); } else if (strcmp (topology->set_name, server->set_name) != 0) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); _update_rs_type (topology); return; } @@ -1640,7 +1648,7 @@ _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description } else { bson_set_error ( &error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "member's setVersion or electionId is stale"); - mongoc_topology_description_invalidate_server (topology, server->id, &error); + mongoc_topology_description_invalidate_server (topology, log_and_monitor, server->id, &error); _update_rs_type (topology); return; } @@ -1656,7 +1664,7 @@ _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description // stale primary code return: bson_set_error ( &error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "member's setVersion or electionId is stale"); - mongoc_topology_description_invalidate_server (topology, server->id, &error); + mongoc_topology_description_invalidate_server (topology, log_and_monitor, server->id, &error); _update_rs_type (topology); return; } @@ -1677,10 +1685,10 @@ _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description mongoc_set_for_each (mc_tpld_servers (topology), _mongoc_topology_description_invalidate_primaries_cb, &data); /* Add to topology description any new servers primary knows about */ - _mongoc_topology_description_add_new_servers (topology, server); + _mongoc_topology_description_add_new_servers (topology, log_and_monitor, server); /* Remove from topology description any servers primary doesn't know about */ - _mongoc_topology_description_remove_unreported_servers (topology, server); + _mongoc_topology_description_remove_unreported_servers (topology, log_and_monitor, server); /* Finally, set topology type */ _update_rs_type (topology); @@ -1703,6 +1711,7 @@ _mongoc_topology_description_update_rs_from_primary (mongoc_topology_description */ static void _mongoc_topology_description_update_rs_without_primary (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { BSON_ASSERT (topology); @@ -1717,13 +1726,13 @@ _mongoc_topology_description_update_rs_without_primary (mongoc_topology_descript if (!topology->set_name) { topology->set_name = bson_strdup (server->set_name); } else if (strcmp (topology->set_name, server->set_name) != 0) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); return; } } /* Add new servers that this replica set member knows about */ - _mongoc_topology_description_add_new_servers (topology, server); + _mongoc_topology_description_add_new_servers (topology, log_and_monitor, server); /* If this server thinks there is a primary, label it POSSIBLE_PRIMARY */ if (server->current_primary) { @@ -1732,7 +1741,7 @@ _mongoc_topology_description_update_rs_without_primary (mongoc_topology_descript } if (!_mongoc_topology_description_matches_me (server)) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); return; } } @@ -1754,8 +1763,10 @@ _mongoc_topology_description_update_rs_without_primary (mongoc_topology_descript *-------------------------------------------------------------------------- */ static void -_mongoc_topology_description_update_rs_with_primary_from_member (mongoc_topology_description_t *topology, - const mongoc_server_description_t *server) +_mongoc_topology_description_update_rs_with_primary_from_member ( + mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, + const mongoc_server_description_t *server) { BSON_ASSERT (topology); BSON_ASSERT (server); @@ -1766,13 +1777,13 @@ _mongoc_topology_description_update_rs_with_primary_from_member (mongoc_topology /* set_name should never be null here */ if (strcmp (topology->set_name, server->set_name) != 0) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); _update_rs_type (topology); return; } if (!_mongoc_topology_description_matches_me (server)) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); return; } @@ -1802,9 +1813,11 @@ _mongoc_topology_description_update_rs_with_primary_from_member (mongoc_topology */ static void _mongoc_topology_description_set_topology_type_to_sharded (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { BSON_UNUSED (server); + BSON_UNUSED (log_and_monitor); _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SHARDED); } @@ -1827,11 +1840,13 @@ _mongoc_topology_description_set_topology_type_to_sharded (mongoc_topology_descr *-------------------------------------------------------------------------- */ static void -_mongoc_topology_description_transition_unknown_to_rs_no_primary (mongoc_topology_description_t *topology, - const mongoc_server_description_t *server) +_mongoc_topology_description_transition_unknown_to_rs_no_primary ( + mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, + const mongoc_server_description_t *server) { _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_RS_NO_PRIMARY); - _mongoc_topology_description_update_rs_without_primary (topology, server); + _mongoc_topology_description_update_rs_without_primary (topology, log_and_monitor, server); } /* @@ -1851,9 +1866,10 @@ _mongoc_topology_description_transition_unknown_to_rs_no_primary (mongoc_topolog */ static void _mongoc_topology_description_remove_and_check_primary (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); _update_rs_type (topology); } @@ -1877,6 +1893,7 @@ _mongoc_topology_description_remove_and_check_primary (mongoc_topology_descripti */ static void _mongoc_topology_description_update_unknown_with_standalone (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const mongoc_server_description_t *server) { BSON_ASSERT (topology); @@ -1887,7 +1904,7 @@ _mongoc_topology_description_update_unknown_with_standalone (mongoc_topology_des if (mc_tpld_servers_const (topology)->items_len > 1) { /* This cluster contains other servers, it cannot be a standalone. */ - _mongoc_topology_description_remove_server (topology, server); + _mongoc_topology_description_remove_server (topology, log_and_monitor, server); } else { _mongoc_topology_description_set_state (topology, MONGOC_TOPOLOGY_SINGLE); } @@ -1913,7 +1930,9 @@ _mongoc_topology_description_update_unknown_with_standalone (mongoc_topology_des *-------------------------------------------------------------------------- */ -typedef void (*transition_t) (mongoc_topology_description_t *topology, const mongoc_server_description_t *server); +typedef void (*transition_t) (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, + const mongoc_server_description_t *server); transition_t gSDAMTransitionTable[MONGOC_SERVER_DESCRIPTION_TYPES][MONGOC_TOPOLOGY_DESCRIPTION_TYPES] = { { @@ -2112,6 +2131,7 @@ _mongoc_topology_description_check_compatible (mongoc_topology_description_t *td void mongoc_topology_description_handle_hello (mongoc_topology_description_t *topology, + const mongoc_log_and_monitor_instance_t *log_and_monitor, uint32_t server_id, const bson_t *hello_response, int64_t rtt_msec, @@ -2133,7 +2153,7 @@ mongoc_topology_description_handle_hello (mongoc_topology_description_t *topolog return; /* server already removed from topology */ } - if (topology->apm_callbacks.topology_changed) { + if (log_and_monitor->apm_callbacks.topology_changed) { prev_td = BSON_ALIGNED_ALLOC0 (mongoc_topology_description_t); _mongoc_topology_description_copy_to (topology, prev_td); } @@ -2157,7 +2177,7 @@ mongoc_topology_description_handle_hello (mongoc_topology_description_t *topolog } } - if (topology->apm_callbacks.topology_changed || topology->apm_callbacks.server_changed) { + if (log_and_monitor->apm_callbacks.topology_changed || log_and_monitor->apm_callbacks.server_changed) { /* Only copy the previous server description if a monitoring callback is * registered. */ prev_sd = mongoc_server_description_new_copy (sd); @@ -2205,14 +2225,14 @@ mongoc_topology_description_handle_hello (mongoc_topology_description_t *topolog sd_changed = !_mongoc_server_description_equal (prev_sd, sd); } if (sd_changed) { - _mongoc_topology_description_monitor_server_changed (topology, prev_sd, sd); + _mongoc_topology_description_monitor_server_changed (topology, log_and_monitor, prev_sd, sd); } if (gSDAMTransitionTable[sd->type][topology->type]) { TRACE ("Topology description %s handling server description %s", _tpld_type_str (topology->type), mongoc_server_description_type (sd)); - gSDAMTransitionTable[sd->type][topology->type](topology, sd); + gSDAMTransitionTable[sd->type][topology->type](topology, log_and_monitor, sd); } else { TRACE ("Topology description %s ignoring server description %s", _tpld_type_str (topology->type), @@ -2229,7 +2249,7 @@ mongoc_topology_description_handle_hello (mongoc_topology_description_t *topolog /* If server description did not change, then neither did topology * description */ if (sd_changed) { - _mongoc_topology_description_monitor_changed (prev_td, topology); + _mongoc_topology_description_monitor_changed (prev_td, topology, log_and_monitor); } if (prev_td) { @@ -2395,6 +2415,7 @@ _count_num_hosts_to_remove (void *sd_void, void *ctx_void) typedef struct { mongoc_host_list_t *host_list; mongoc_topology_description_t *td; + const mongoc_log_and_monitor_instance_t *log_and_monitor; } _remove_if_not_in_host_list_ctx_t; static bool @@ -2413,12 +2434,14 @@ _remove_if_not_in_host_list_cb (void *sd_void, void *ctx_void) if (_mongoc_host_list_contains_one (host_list, &sd->host)) { return true; } - _mongoc_topology_description_remove_server (td, sd); + _mongoc_topology_description_remove_server (td, ctx->log_and_monitor, sd); return true; } void -mongoc_topology_description_reconcile (mongoc_topology_description_t *td, mongoc_host_list_t *host_list) +mongoc_topology_description_reconcile (mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, + mongoc_host_list_t *host_list) { mongoc_set_t *servers; size_t host_list_length; @@ -2451,7 +2474,7 @@ mongoc_topology_description_reconcile (mongoc_topology_description_t *td, mongoc LL_FOREACH (host_list, host) { /* "add" is really an "upsert" */ - mongoc_topology_description_add_server (td, host->host_and_port, NULL); + mongoc_topology_description_add_server (td, log_and_monitor, host->host_and_port, NULL); } } @@ -2477,7 +2500,7 @@ mongoc_topology_description_reconcile (mongoc_topology_description_t *td, mongoc const mongoc_host_list_t *const elem = hl_array[idx]; /* "add" is really an "upsert" */ - mongoc_topology_description_add_server (td, elem->host_and_port, NULL); + mongoc_topology_description_add_server (td, log_and_monitor, elem->host_and_port, NULL); } /* There should not be a situation where all items in the valid host list @@ -2497,6 +2520,7 @@ mongoc_topology_description_reconcile (mongoc_topology_description_t *td, mongoc ctx.host_list = host_list; ctx.td = td; + ctx.log_and_monitor = log_and_monitor; mongoc_set_for_each (servers, _remove_if_not_in_host_list_cb, &ctx); } diff --git a/src/libmongoc/src/mongoc/mongoc-topology-private.h b/src/libmongoc/src/mongoc/mongoc-topology-private.h index d7475b221a3..72f2d8c0b9a 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-private.h +++ b/src/libmongoc/src/mongoc/mongoc-topology-private.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -208,9 +209,10 @@ typedef struct _mongoc_topology_t { /* For background monitoring. */ mongoc_set_t *server_monitors; mongoc_set_t *rtt_monitors; - bson_mutex_t apm_mutex; - struct mongoc_structured_log_instance_t *structured_log; + // APM callbacks, structured logging handlers and callbacks. + // Documented as per-client and per-pool, implemented as owned by topology_t. + mongoc_log_and_monitor_instance_t log_and_monitor; /* This is overridable for SRV polling tests to mock DNS records. */ _mongoc_rr_resolver_fn rr_resolver; @@ -234,12 +236,6 @@ typedef struct _mongoc_topology_t { mongoc_topology_t * mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded); -void -mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology, - mongoc_topology_description_t *td, - mongoc_apm_callbacks_t const *callbacks, - void *context); - void mongoc_topology_set_structured_log_opts (mongoc_topology_t *topology, const mongoc_structured_log_opts_t *opts); @@ -621,16 +617,16 @@ mc_tpld_unsafe_get_const (const mongoc_topology_t *tpl) * This is intended for testing purposes, as it provides thread-safe * direct topology modification. * - * @param td The topology to modify. + * @param topology The topology to modify. * @param server_id The ID of a server in the topology. */ static BSON_INLINE void -_mongoc_topology_invalidate_server (mongoc_topology_t *td, uint32_t server_id) +_mongoc_topology_invalidate_server (mongoc_topology_t *topology, uint32_t server_id) { bson_error_t error; - mc_tpld_modification tdmod = mc_tpld_modify_begin (td); + mc_tpld_modification tdmod = mc_tpld_modify_begin (topology); bson_set_error (&error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "invalidated"); - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, &error); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, &error); mc_tpld_modify_commit (tdmod); } diff --git a/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h b/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h index d120a976aec..7bffb4366a1 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h +++ b/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h @@ -115,6 +115,7 @@ typedef struct mongoc_topology_scanner { bson_t *handshake_cmd; handshake_state_t handshake_state; bson_t cluster_time; + bson_oid_t topology_id; const char *appname; mongoc_topology_scanner_setup_err_cb_t setup_err_cb; @@ -134,8 +135,6 @@ typedef struct mongoc_topology_scanner { SSL_CTX *openssl_ctx; #endif - mongoc_apm_callbacks_t apm_callbacks; - void *apm_context; int64_t dns_cache_timeout_ms; /* only used by single-threaded clients to negotiate auth mechanisms. */ bool negotiate_sasl_supported_mechs; @@ -143,11 +142,14 @@ typedef struct mongoc_topology_scanner { bool speculative_authentication; mongoc_server_api_t *api; + mongoc_log_and_monitor_instance_t *log_and_monitor; // Not null. bool loadbalanced; } mongoc_topology_scanner_t; mongoc_topology_scanner_t * mongoc_topology_scanner_new (const mongoc_uri_t *uri, + const bson_oid_t *topology_id, + mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_topology_scanner_setup_err_cb_t setup_err_cb, mongoc_topology_scanner_cb_t cb, void *data, diff --git a/src/libmongoc/src/mongoc/mongoc-topology-scanner.c b/src/libmongoc/src/mongoc/mongoc-topology-scanner.c index 223de6f3595..a7ef7ec87b8 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-scanner.c +++ b/src/libmongoc/src/mongoc/mongoc-topology-scanner.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -411,6 +412,8 @@ _begin_hello_cmd (mongoc_topology_scanner_node_t *node, mongoc_topology_scanner_t * mongoc_topology_scanner_new (const mongoc_uri_t *uri, + const bson_oid_t *topology_id, + mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_topology_scanner_setup_err_cb_t setup_err_cb, mongoc_topology_scanner_cb_t cb, void *data, @@ -420,11 +423,13 @@ mongoc_topology_scanner_new (const mongoc_uri_t *uri, ts->async = mongoc_async_new (); + bson_oid_copy (topology_id, &ts->topology_id); ts->setup_err_cb = setup_err_cb; ts->cb = cb; ts->cb_data = data; ts->uri = uri; ts->appname = NULL; + ts->log_and_monitor = log_and_monitor; ts->api = NULL; ts->handshake_state = HANDSHAKE_CMD_UNINITIALIZED; ts->connect_timeout_msec = connect_timeout_msec; @@ -1276,12 +1281,21 @@ _mongoc_topology_scanner_set_cluster_time (mongoc_topology_scanner_t *ts, const static void _mongoc_topology_scanner_monitor_heartbeat_started (const mongoc_topology_scanner_t *ts, const mongoc_host_list_t *host) { - if (ts->apm_callbacks.server_heartbeat_started) { + mongoc_structured_log (ts->log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat started", + oid ("topologyId", &ts->topology_id), + utf8 ("serverHost", host->host), + int32 ("serverPort", host->port), + boolean ("awaited", false)); + + if (ts->log_and_monitor->apm_callbacks.server_heartbeat_started) { mongoc_apm_server_heartbeat_started_t event; event.host = host; - event.context = ts->apm_context; + event.context = ts->log_and_monitor->apm_context; event.awaited = false; - ts->apm_callbacks.server_heartbeat_started (&event); + ts->log_and_monitor->apm_callbacks.server_heartbeat_started (&event); } } @@ -1292,22 +1306,38 @@ _mongoc_topology_scanner_monitor_heartbeat_succeeded (const mongoc_topology_scan const bson_t *reply, int64_t duration_usec) { - if (ts->apm_callbacks.server_heartbeat_succeeded) { + /* This redaction is more lenient than the general command redaction in the Command Logging and Monitoring spec and + * the cmd*() structured log items. In those general command logs, sensitive replies are omitted entirely. In this + * APM message, the reply is passed through with only the speculativeAuthenticate field stripped. The Server + * Discovery and Monitoring Logging spec does not mention reply redaction, so we choose to be consistent with the APM + * event. */ + + bson_t hello_redacted; + bson_init (&hello_redacted); + bson_copy_to_excluding_noinit (reply, &hello_redacted, "speculativeAuthenticate", NULL); + + mongoc_structured_log (ts->log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat succeeded", + oid ("topologyId", &ts->topology_id), + utf8 ("serverHost", host->host), + int32 ("serverPort", host->port), + boolean ("awaited", false), + monotonic_time_duration (duration_usec), + bson_as_json ("reply", &hello_redacted)); + + if (ts->log_and_monitor->apm_callbacks.server_heartbeat_succeeded) { mongoc_apm_server_heartbeat_succeeded_t event; - bson_t hello_redacted; - - bson_init (&hello_redacted); - bson_copy_to_excluding_noinit (reply, &hello_redacted, "speculativeAuthenticate", NULL); - event.host = host; - event.context = ts->apm_context; + event.context = ts->log_and_monitor->apm_context; event.reply = reply; event.duration_usec = duration_usec; event.awaited = false; - ts->apm_callbacks.server_heartbeat_succeeded (&event); - - bson_destroy (&hello_redacted); + ts->log_and_monitor->apm_callbacks.server_heartbeat_succeeded (&event); } + + bson_destroy (&hello_redacted); } /* SDAM Monitoring Spec: send HeartbeatFailedEvent */ @@ -1317,14 +1347,25 @@ _mongoc_topology_scanner_monitor_heartbeat_failed (const mongoc_topology_scanner const bson_error_t *error, int64_t duration_usec) { - if (ts->apm_callbacks.server_heartbeat_failed) { + mongoc_structured_log (ts->log_and_monitor->structured_log, + MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, + MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY, + "Server heartbeat failed", + oid ("topologyId", &ts->topology_id), + utf8 ("serverHost", host->host), + int32 ("serverPort", host->port), + boolean ("awaited", false), + monotonic_time_duration (duration_usec), + error ("failure", error)); + + if (ts->log_and_monitor->apm_callbacks.server_heartbeat_failed) { mongoc_apm_server_heartbeat_failed_t event; event.host = host; - event.context = ts->apm_context; + event.context = ts->log_and_monitor->apm_context; event.error = error; event.duration_usec = duration_usec; event.awaited = false; - ts->apm_callbacks.server_heartbeat_failed (&event); + ts->log_and_monitor->apm_callbacks.server_heartbeat_failed (&event); } } diff --git a/src/libmongoc/src/mongoc/mongoc-topology.c b/src/libmongoc/src/mongoc/mongoc-topology.c index 74959a53038..e95173eaec9 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology.c +++ b/src/libmongoc/src/mongoc/mongoc-topology.c @@ -98,9 +98,10 @@ _mongoc_topology_update_no_lock (uint32_t id, const bson_t *hello_response, int64_t rtt_msec, mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, const bson_error_t *error /* IN */) { - mongoc_topology_description_handle_hello (td, id, hello_response, rtt_msec, error); + mongoc_topology_description_handle_hello (td, log_and_monitor, id, hello_response, rtt_msec, error); /* return false if server removed from topology */ return mongoc_topology_description_server_by_id (td, id, NULL) != NULL; @@ -131,7 +132,8 @@ _mongoc_topology_scanner_setup_err_cb (uint32_t id, void *data, const bson_error // Use `mc_tpld_unsafe_get_mutable` to get a mutable topology description // without locking. This function only applies to single-threaded clients. mongoc_topology_description_t *td = mc_tpld_unsafe_get_mutable (topology); - mongoc_topology_description_handle_hello (td, id, NULL /* hello reply */, -1 /* rtt_msec */, error); + mongoc_topology_description_handle_hello ( + td, &topology->log_and_monitor, id, NULL /* hello reply */, -1 /* rtt_msec */, error); } } @@ -181,13 +183,13 @@ _mongoc_topology_scanner_cb ( * client MUST change its type to Unknown only after it has retried the * server once." */ if (!hello_response && sd && sd->type != MONGOC_SERVER_UNKNOWN) { - _mongoc_topology_update_no_lock (id, hello_response, rtt_msec, td, error); + _mongoc_topology_update_no_lock (id, hello_response, rtt_msec, td, &topology->log_and_monitor, error); /* add another hello call to the current scan - the scan continues * until all commands are done */ mongoc_topology_scanner_scan (topology->scanner, sd->id); } else { - _mongoc_topology_update_no_lock (id, hello_response, rtt_msec, td, error); + _mongoc_topology_update_no_lock (id, hello_response, rtt_msec, td, &topology->log_and_monitor, error); /* The processing of the hello results above may have added, changed, or * removed server descriptions. We need to reconcile that with our @@ -403,9 +405,7 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded) _server_session_init, _server_session_destroy, _server_session_should_prune, topology); // Capture default structured log options from the environment - mongoc_structured_log_opts_t *structured_log_opts = mongoc_structured_log_opts_new (); - topology->structured_log = mongoc_structured_log_instance_new (structured_log_opts); - mongoc_structured_log_opts_destroy (structured_log_opts); + mongoc_log_and_monitor_instance_init (&topology->log_and_monitor); topology->valid = false; @@ -460,6 +460,8 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded) topology->scanner_state = MONGOC_TOPOLOGY_SCANNER_OFF; topology->scanner = mongoc_topology_scanner_new (topology->uri, + &td->topology_id, + &topology->log_and_monitor, _mongoc_topology_scanner_setup_err_cb, _mongoc_topology_scanner_cb, topology, @@ -610,7 +612,6 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded) if (!topology->single_threaded) { topology->server_monitors = mongoc_set_new (1, NULL, NULL); topology->rtt_monitors = mongoc_set_new (1, NULL, NULL); - bson_mutex_init (&topology->apm_mutex); bson_mutex_init (&topology->srv_polling_mtx); mongoc_cond_init (&topology->srv_polling_cond); } @@ -631,7 +632,7 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded) uint32_t id = 0u; - mongoc_topology_description_add_server (td, elem->host_and_port, &id); + mongoc_topology_description_add_server (td, &topology->log_and_monitor, elem->host_and_port, &id); mongoc_topology_scanner_add (topology->scanner, elem, id, false); } @@ -640,62 +641,6 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded) return topology; } -/* - *------------------------------------------------------------------------- - * - * mongoc_topology_set_apm_callbacks -- - * - * Set Application Performance Monitoring callbacks. - * - *------------------------------------------------------------------------- - */ -void -mongoc_topology_set_apm_callbacks (mongoc_topology_t *topology, - mongoc_topology_description_t *td, - mongoc_apm_callbacks_t const *callbacks, - void *context) -{ - if (callbacks) { - td->apm_callbacks = *callbacks; - topology->scanner->apm_callbacks = *callbacks; - } else { - td->apm_callbacks = (mongoc_apm_callbacks_t){0}; - topology->scanner->apm_callbacks = (mongoc_apm_callbacks_t){0}; - } - - td->apm_context = context; - topology->scanner->apm_context = context; -} - -/* - *------------------------------------------------------------------------- - * - * mongoc_topology_set_structured_log_opts -- - * - * Replace the topology's structured logging options. Options are copied. - * The structured log instance used by a client or client pool in the public - * API is internally owned by a mongoc_topology_t. - * - * This is only safe to call when no other threads may be accessing the - * structured log. On a single-threaded topology it can be used on the - * thread that owns that topology. On a multi-threaded topology it can - * only be used during initialization, before clients have been created. - * This limitation is enforced by mongoc_client_pool_set_structured_log_opts. - * - *------------------------------------------------------------------------- - */ - -void -mongoc_topology_set_structured_log_opts (mongoc_topology_t *topology, const mongoc_structured_log_opts_t *opts) -{ - BSON_ASSERT_PARAM (topology); - BSON_OPTIONAL_PARAM (opts); - - mongoc_structured_log_instance_destroy (topology->structured_log); - topology->structured_log = mongoc_structured_log_instance_new (opts); -} - - /* *------------------------------------------------------------------------- * @@ -733,15 +678,32 @@ mongoc_topology_destroy (mongoc_topology_t *topology) BSON_ASSERT (topology->scanner_state == MONGOC_TOPOLOGY_SCANNER_OFF); mongoc_set_destroy (topology->server_monitors); mongoc_set_destroy (topology->rtt_monitors); - bson_mutex_destroy (&topology->apm_mutex); bson_mutex_destroy (&topology->srv_polling_mtx); mongoc_cond_destroy (&topology->srv_polling_cond); } - if (topology->valid) { - /* Do not emit a topology_closed event. A topology opening event was not - * emitted. */ - _mongoc_topology_description_monitor_closed (mc_tpld_unsafe_get_const (topology)); + /* Before reporting this topology as closed, life cycle rules expect us to close + * all servers and transition to an unknown topology. */ + { + /* Prefer mc_tpld_unsafe_get_const to mc_tpld_take_ref/drop_ref here: no other references remain, and bypassing + * the shared pointer lock has the side-effect of revealing problems in TSAN. */ + const mongoc_topology_description_t *td = mc_tpld_unsafe_get_const (topology); + + for (size_t i = 0u; i < mc_tpld_servers_const (td)->items_len; i++) { + const mongoc_server_description_t *sd = mongoc_set_get_item_const (mc_tpld_servers_const (td), i); + _mongoc_topology_description_monitor_server_closed (td, &topology->log_and_monitor, sd); + } + + // Transition to an "Unknown" td that will exist only for monitoring purposes just before closing + mongoc_topology_description_t next_td; + mongoc_topology_description_init (&next_td, td->heartbeat_msec); + bson_oid_copy (&td->topology_id, &next_td.topology_id); + next_td.opened = td->opened; + + _mongoc_topology_description_monitor_changed (td, &next_td, &topology->log_and_monitor); + _mongoc_topology_description_monitor_closed (&next_td, &topology->log_and_monitor); + + mongoc_topology_description_cleanup (&next_td); } mongoc_uri_destroy (topology->uri); @@ -749,7 +711,7 @@ mongoc_topology_destroy (mongoc_topology_t *topology) mongoc_topology_scanner_destroy (topology->scanner); mongoc_server_session_pool_free (topology->session_pool); bson_free (topology->clientSideEncryption.autoOptions.extraOptions.cryptSharedLibPath); - mongoc_structured_log_instance_destroy (topology->structured_log); + mongoc_log_and_monitor_instance_destroy_contents (&topology->log_and_monitor); mongoc_cond_destroy (&topology->cond_client); bson_mutex_destroy (&topology->tpld_modification_mtx); @@ -763,6 +725,7 @@ mongoc_topology_destroy (mongoc_topology_t *topology) bool mongoc_topology_apply_scanned_srv_hosts (mongoc_uri_t *uri, mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_host_list_t *hosts, bson_error_t *error) { @@ -787,7 +750,7 @@ mongoc_topology_apply_scanned_srv_hosts (mongoc_uri_t *uri, if (valid_hosts) { /* Reconcile with the topology description. Newly found servers will start * getting monitored and are eligible to be used by clients. */ - mongoc_topology_description_reconcile (td, valid_hosts); + mongoc_topology_description_reconcile (td, log_and_monitor, valid_hosts); had_valid_hosts = true; } else { bson_set_error (error, @@ -892,7 +855,7 @@ mongoc_topology_rescan_srv (mongoc_topology_t *topology) tdmod = mc_tpld_modify_begin (topology); if (!mongoc_topology_apply_scanned_srv_hosts ( - topology->uri, tdmod.new_td, rr_data.hosts, &topology->scanner->error)) { + topology->uri, tdmod.new_td, &topology->log_and_monitor, rr_data.hosts, &topology->scanner->error)) { MONGOC_ERROR ("%s", topology->scanner->error.message); /* Special case when DNS returns zero records successfully or no valid * hosts exist. @@ -1071,12 +1034,13 @@ _mongoc_topology_select_server_id_loadbalanced (mongoc_topology_t *topology, bso BSON_ASSERT (td.ptr->type == MONGOC_TOPOLOGY_LOAD_BALANCED); /* Emit the opening SDAM events if they have not emitted already. */ - if (!td.ptr->opened) { + { mc_tpld_modification tdmod = mc_tpld_modify_begin (topology); - _mongoc_topology_description_monitor_opening (tdmod.new_td); + _mongoc_topology_description_monitor_opening (tdmod.new_td, &topology->log_and_monitor); mc_tpld_modify_commit (tdmod); mc_tpld_renew_ref (&td, topology); } + selected_server = mongoc_topology_description_select (td.ptr, MONGOC_SS_WRITE, NULL /* read prefs */, @@ -1163,6 +1127,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, int64_t heartbeat_msec; uint32_t server_id; mc_shared_tpld td = mc_tpld_take_ref (topology); + const mongoc_log_and_monitor_instance_t *log_and_monitor = &topology->log_and_monitor; mcommon_string_append_t topology_type; mcommon_string_new_as_append (&topology_type); @@ -1179,7 +1144,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, BSON_ASSERT (topology); ts = topology->scanner; - mongoc_structured_log (topology->structured_log, + mongoc_structured_log (log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION, "Server selection started", @@ -1210,13 +1175,11 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, expire_at = loop_start + ((int64_t) topology->server_selection_timeout_msec * 1000); if (topology->single_threaded) { - if (!td.ptr->opened) { - // Use `mc_tpld_unsafe_get_mutable` to get a mutable topology - // description without locking. This block only applies to - // single-threaded clients. - _mongoc_topology_description_monitor_opening (mc_tpld_unsafe_get_mutable (topology)); - mc_tpld_renew_ref (&td, topology); - } + // Use `mc_tpld_unsafe_get_mutable` to get a mutable topology + // description without locking. This block only applies to + // single-threaded clients. + _mongoc_topology_description_monitor_opening (mc_tpld_unsafe_get_mutable (topology), log_and_monitor); + mc_tpld_renew_ref (&td, topology); tried_once = false; next_update = topology->last_scan + heartbeat_msec * 1000; @@ -1250,7 +1213,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, if (!logged_waiting_for_suitable_server) { logged_waiting_for_suitable_server = true; mongoc_structured_log ( - topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_INFO, MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION, "Waiting for suitable server to become available", @@ -1351,7 +1314,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, if (!logged_waiting_for_suitable_server) { logged_waiting_for_suitable_server = true; - mongoc_structured_log (topology->structured_log, + mongoc_structured_log (log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_INFO, MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION, "Waiting for suitable server to become available", @@ -1408,7 +1371,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, if (error && error->domain == MONGOC_ERROR_SERVER_SELECTION) { _mongoc_error_append (error, mcommon_str_from_append (&topology_type)); } - mongoc_structured_log (topology->structured_log, + mongoc_structured_log (log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION, "Server selection failed", @@ -1419,7 +1382,7 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology, error ("failure", error)); } else { mongoc_structured_log ( - topology->structured_log, + log_and_monitor->structured_log, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION, "Server selection succeeded", @@ -1479,8 +1442,8 @@ _mongoc_topology_update_from_handshake (mongoc_topology_t *topology, const mongo tdmod = mc_tpld_modify_begin (topology); /* return false if server was removed from topology */ - has_server = - _mongoc_topology_update_no_lock (sd->id, &sd->last_hello_response, sd->round_trip_time_msec, tdmod.new_td, NULL); + has_server = _mongoc_topology_update_no_lock ( + sd->id, &sd->last_hello_response, sd->round_trip_time_msec, tdmod.new_td, &topology->log_and_monitor, NULL); /* if pooled, wake threads waiting in mongoc_topology_server_by_id */ mongoc_cond_broadcast (&topology->cond_client); @@ -1865,7 +1828,7 @@ _handle_sdam_app_error_command (mongoc_topology_t *topology, * current ServerDescription's topologyVersion it MUST replace the * server's description with a ServerDescription of type Unknown. */ - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, &cmd_error); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, &cmd_error); if (topology->single_threaded) { /* SDAM: For single-threaded clients, in the case of a "not primary" or @@ -1946,7 +1909,7 @@ _mongoc_topology_handle_app_error (mongoc_topology_t *topology, goto ignore_error; } /* Mark server as unknown. */ - mongoc_topology_description_invalidate_server (tdmod.new_td, server_id, why); + mongoc_topology_description_invalidate_server (tdmod.new_td, &topology->log_and_monitor, server_id, why); /* Clear the connection pool */ _mongoc_topology_description_clear_connection_pool (tdmod.new_td, server_id, service_id); cleared_pool = true; diff --git a/src/libmongoc/tests/json-test.c b/src/libmongoc/tests/json-test.c index 1e78eb283a8..72979df98d8 100644 --- a/src/libmongoc/tests/json-test.c +++ b/src/libmongoc/tests/json-test.c @@ -220,7 +220,8 @@ process_sdam_test_hello_responses (bson_t *phase, mongoc_topology_t *topology) /* send hello through the topology description's handler */ capture_logs (true); - mongoc_topology_description_handle_hello (tdmod.new_td, sd->id, &response, 1, NULL); + mongoc_topology_description_handle_hello ( + tdmod.new_td, &topology->log_and_monitor, sd->id, &response, 1, NULL); if (mc_tpld_servers_const (tdmod.new_td)->items_len == 0) { ASSERT_CAPTURED_LOG ("topology", MONGOC_LOG_LEVEL_WARNING, "Last server removed from topology"); } diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/errors/prefer-error-code.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/errors/prefer-error-code.json index 21d123f4295..eb00b696131 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/errors/prefer-error-code.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/errors/prefer-error-code.json @@ -52,7 +52,7 @@ } }, { - "description": "errmsg \"not writable primary\" gets ignored when error code exists", + "description": "errmsg \"not master\" gets ignored when error code exists", "applicationErrors": [ { "address": "a:27017", @@ -61,7 +61,7 @@ "type": "command", "response": { "ok": 0, - "errmsg": "not writable primary", + "errmsg": "not master", "code": 1 } } diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/discovered_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/discovered_standalone.json index 8fad5cf3575..097203694ea 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/discovered_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/discovered_standalone.json @@ -8,9 +8,10 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_no_primary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_no_primary.json index 53366c0001d..41d048729da 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_no_primary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_no_primary.json @@ -8,6 +8,7 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", @@ -18,7 +19,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_primary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_primary.json index df57c2265d9..3ccc127d1d6 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_primary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_primary.json @@ -8,6 +8,7 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, @@ -17,7 +18,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_removal.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_removal.json index cb48ecf1b45..dc6fbe7e7d8 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_removal.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/replica_set_with_removal.json @@ -60,6 +60,7 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, @@ -68,13 +69,14 @@ "a:27017" ], "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ], [ "b:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true } ] diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/required_replica_set.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/required_replica_set.json index d86b1dfcc62..1f4e5c1d715 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/required_replica_set.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/required_replica_set.json @@ -8,6 +8,7 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, @@ -17,7 +18,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone.json index 69a100f454d..f375a383ca2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone.json @@ -8,9 +8,10 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone_suppress_equal_description_changes.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone_suppress_equal_description_changes.json index 1771f85fc0e..4d046ff8ed6 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone_suppress_equal_description_changes.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/monitoring/standalone_suppress_equal_description_changes.json @@ -8,18 +8,20 @@ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ], [ "a:27017", { "ok": 1, + "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 4 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters.json index 53709b0cee9..803462b1561 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters_replicaset.json index 64fb49f4fcd..e58d7c7fb4c 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_arbiters_replicaset.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost.json index 2e24c83e0b7..3b7fc836ec1 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost.json @@ -12,7 +12,7 @@ "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost_replicaset.json index cf5fe83a542..1a8457983b2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_ghost_replicaset.json @@ -12,7 +12,7 @@ "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden.json index e4a90f1f9cd..10bd51edebd 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden_replicaset.json index 04420596f00..63cf5586757 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_hidden_replicaset.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives.json index 30258409f64..0a292c675c2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -56,7 +56,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives_replicaset.json index 266eaa52344..c48fd476251 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_passives_replicaset.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -56,7 +56,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary.json index 2d1292bbd47..04e7a4984c8 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary_replicaset.json index 54dfefba5fd..3cdcfdcee2d 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_primary_replicaset.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother.json index 4ab25667f01..9c3b8d8b7dd 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother.json @@ -17,7 +17,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother_replicaset.json index e3958d70adb..3da9efb0660 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_rsother_replicaset.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -34,7 +34,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary.json index 22325d4e03a..64a1ce31e31 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary.json @@ -17,7 +17,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary_replicaset.json index d903b6444d7..d230f976a2c 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discover_secondary_replicaset.json @@ -17,7 +17,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discovery.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discovery.json index 50e1269223a..e9deaa7587f 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discovery.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/discovery.json @@ -18,7 +18,7 @@ "c:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -59,7 +59,7 @@ "d:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -103,7 +103,7 @@ "e:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -147,7 +147,7 @@ "c:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/electionId_precedence_setVersion.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/electionId_precedence_setVersion.json index bf04d4efb92..2fcea2bf660 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/electionId_precedence_setVersion.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/electionId_precedence_setVersion.json @@ -89,4 +89,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/equal_electionids.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/equal_electionids.json index 17df3207fa8..f1deedf9f42 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/equal_electionids.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/equal_electionids.json @@ -20,7 +20,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -39,7 +39,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/hosts_differ_from_seeds.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/hosts_differ_from_seeds.json index 4e02304c619..085e81e2663 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/hosts_differ_from_seeds.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/hosts_differ_from_seeds.json @@ -15,7 +15,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_arbiter.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_arbiter.json index f0539cb3373..bda18d9f6f7 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_arbiter.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_arbiter.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_ghost.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_ghost.json index 824e953f906..9d82e316822 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_ghost.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_ghost.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_other.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_other.json index 6f301ef5de3..149ba01142a 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_other.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/incompatible_other.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/ls_timeout.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/ls_timeout.json index 96389d3b769..c68790ddfda 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/ls_timeout.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/ls_timeout.json @@ -20,7 +20,7 @@ "setName": "rs", "logicalSessionTimeoutMinutes": 3, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -58,7 +58,7 @@ "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -104,7 +104,7 @@ "setName": "rs", "arbiterOnly": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -152,7 +152,7 @@ "setName": "rs", "logicalSessionTimeoutMinutes": 2, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -194,7 +194,7 @@ "hidden": true, "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -244,7 +244,7 @@ "setName": "rs", "logicalSessionTimeoutMinutes": null, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_reconfig.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_reconfig.json index 0e2c2c462ea..a05fed0efb3 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_reconfig.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_reconfig.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -49,7 +49,7 @@ "a:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_standalone.json index 0756003a89f..db100db9f37 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/member_standalone.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -40,7 +40,7 @@ "a:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary.json index ed1a6245f96..1a84c69c919 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -50,7 +50,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_electionid.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_electionid.json index ccb3a41f757..509720d445a 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_electionid.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_electionid.json @@ -20,7 +20,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -67,7 +67,7 @@ "$oid": "000000000000000000000002" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -114,7 +114,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_setversion.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_setversion.json index 415a0f66aa9..96533c61ee2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_setversion.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_new_setversion.json @@ -20,7 +20,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -67,7 +67,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -114,7 +114,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_wrong_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_wrong_set_name.json index d7b19cfe8f1..774b3a57364 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_wrong_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/new_primary_wrong_set_name.json @@ -16,7 +16,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -49,7 +49,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/non_rs_member.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/non_rs_member.json index 538077ef099..6bf10bd628f 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/non_rs_member.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/non_rs_member.json @@ -10,7 +10,7 @@ "ok": 1, "helloOk": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case.json index 96a944f0c35..62915495e0c 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case.json @@ -21,7 +21,7 @@ "C:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case_me.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case_me.json index ab1720cefc0..0d9ba6213e2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case_me.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/normalize_case_me.json @@ -22,7 +22,7 @@ "C:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -67,7 +67,7 @@ "C:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/null_election_id-pre-6.0.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/null_election_id-pre-6.0.json index dedf900ec0e..7261fbfc2a8 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/null_election_id-pre-6.0.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/null_election_id-pre-6.0.json @@ -1,204 +1,203 @@ { - "description": "Pre 6.0 Primaries with and without electionIds", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017", - "c:27017" - ], - "setVersion": 1, - "setName": "rs", - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "c:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + "description": "Pre 6.0 Primaries with and without electionIds", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017", + "c:27017" + ], + "setVersion": 1, + "setName": "rs", + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1 - } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017", - "c:27017" - ], - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - }, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - } + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + }, + "c:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1 + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017", + "c:27017" + ], + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" }, - "c:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + }, + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" } }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000002" + "c:27017": { + "type": "Unknown", + "setName": null, + "electionId": null } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000002" } - }, - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017", - "c:27017" - ], - "setVersion": 1, - "setName": "rs", - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "c:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + } + }, + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017", + "c:27017" + ], + "setVersion": 1, + "setName": "rs", + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null + }, + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000002" + "c:27017": { + "type": "Unknown", + "setName": null, + "electionId": null } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000002" } - }, - { - "responses": [ - [ - "c:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017", - "c:27017" - ], - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000001" - }, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + } + }, + { + "responses": [ + [ + "c:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017", + "c:27017" + ], + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000001" }, - "c:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null + }, + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000002" + "c:27017": { + "type": "Unknown", + "setName": null, + "electionId": null } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000002" } } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_ghost.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_ghost.json index 9c54b39856e..e34280e88c1 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_ghost.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_ghost.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -41,7 +41,7 @@ "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_mongos.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_mongos.json index ac416e57d5f..79510d9399b 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_mongos.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_mongos.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -41,7 +41,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_standalone.json index a64524d0ca4..abcc1e2d012 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_becomes_standalone.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -38,7 +38,7 @@ { "ok": 1, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_changes_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_changes_set_name.json index bf70ca3014b..3b564d2c931 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_changes_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_changes_set_name.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -44,7 +44,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect.json index 3db854f0859..73a01a82a9f 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_electionid.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_electionid.json index 3a80b150fe3..5a91188ea8d 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_electionid.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_electionid.json @@ -20,7 +20,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -39,7 +39,7 @@ "$oid": "000000000000000000000002" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -115,7 +115,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -159,7 +159,7 @@ "$oid": "000000000000000000000003" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -203,7 +203,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_setversion.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_setversion.json index 32e03fb7d4b..f7417ad77bc 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_setversion.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_disconnect_setversion.json @@ -20,7 +20,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -39,7 +39,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -115,7 +115,7 @@ "$oid": "000000000000000000000001" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -159,7 +159,7 @@ "$oid": "000000000000000000000002" }, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -203,7 +203,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_hint_from_secondary_with_mismatched_me.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_hint_from_secondary_with_mismatched_me.json index bc02cc95712..1ca72225a29 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_hint_from_secondary_with_mismatched_me.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_hint_from_secondary_with_mismatched_me.json @@ -18,7 +18,7 @@ "setName": "rs", "primary": "b:27017", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -48,7 +48,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_mismatched_me.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_mismatched_me.json index 2d2c0f40d8d..6bb6226f8a7 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_mismatched_me.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_mismatched_me.json @@ -31,7 +31,7 @@ "ok": 1, "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ] diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_reports_new_member.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_reports_new_member.json index ac0d9374f0d..ed28c48c871 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_reports_new_member.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_reports_new_member.json @@ -17,7 +17,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -51,7 +51,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -86,7 +86,7 @@ "c:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -127,7 +127,7 @@ "c:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_to_no_primary_mismatched_me.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_to_no_primary_mismatched_me.json index 6dbd73dadc1..798a648d196 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_to_no_primary_mismatched_me.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_to_no_primary_mismatched_me.json @@ -17,7 +17,7 @@ "me": "a:27017", "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -52,7 +52,7 @@ "me": "c:27017", "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_wrong_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_wrong_set_name.json index cc0691fb8c7..1366e389969 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_wrong_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/primary_wrong_set_name.json @@ -15,7 +15,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/repeated.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/repeated.json index 610aeae0ac7..3ce0948ab82 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/repeated.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/repeated.json @@ -18,7 +18,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -49,7 +49,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -84,7 +84,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -120,7 +120,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/replicaset_rsnp.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/replicaset_rsnp.json index 3148e1c141f..1cd732b82f1 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/replicaset_rsnp.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/replicaset_rsnp.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/response_from_removed.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/response_from_removed.json index 87a66d9e728..fa46a14ceb3 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/response_from_removed.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/response_from_removed.json @@ -15,7 +15,7 @@ "a:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -46,7 +46,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/sec_not_auth.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/sec_not_auth.json index a39855e654a..ccbe7a08af9 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/sec_not_auth.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/sec_not_auth.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -32,7 +32,7 @@ "c:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0-pre-6.0.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0-pre-6.0.json index 7db59aa3b1e..f27060533cd 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0-pre-6.0.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0-pre-6.0.json @@ -1,84 +1,83 @@ { - "description": "Pre 6.0 New primary", - "uri": "mongodb://a,b/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "setName": "rs", - "hosts": [ - "a:27017", - "b:27017" - ], - "minWireVersion": 0, - "maxWireVersion": 6 - } - ], - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": false, - "secondary": true, - "setName": "rs", - "hosts": [ - "a:27017", - "b:27017" - ], - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] + "description": "Pre 6.0 New primary", + "uri": "mongodb://a,b/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "setName": "rs", + "hosts": [ + "a:27017", + "b:27017" + ], + "minWireVersion": 0, + "maxWireVersion": 21 + } ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs" - }, - "b:27017": { - "type": "RSSecondary", - "setName": "rs" - } + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": false, + "secondary": true, + "setName": "rs", + "hosts": [ + "a:27017", + "b:27017" + ], + "minWireVersion": 0, + "maxWireVersion": 21 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs" }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs" - } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 0, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs" - }, - "b:27017": { - "type": "Unknown", - "setName": null - } + "b:27017": { + "type": "RSSecondary", + "setName": "rs" + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 0, + "minWireVersion": 0, + "maxWireVersion": 21 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs" }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs" - } + "b:27017": { + "type": "Unknown", + "setName": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0.json index 4c1cb011a50..9ffff58ef05 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_ignore_ok_0.json @@ -1,5 +1,5 @@ { - "description": "New primary", + "description": "Secondary ignored when ok is zero", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -32,7 +32,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -59,7 +59,7 @@ { "ok": 0, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_mismatched_me.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_mismatched_me.json index 6f1b9b59866..790e4bfca84 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_mismatched_me.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_mismatched_me.json @@ -32,7 +32,7 @@ "ok": 1, "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ] diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name.json index 8d2f152f594..1f86b505437 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name.json @@ -16,7 +16,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name_with_primary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name_with_primary.json index b7ef2d6d6ab..6b899141514 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name_with_primary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/secondary_wrong_set_name_with_primary.json @@ -16,7 +16,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -51,7 +51,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/set_version_can_rollback.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/set_version_can_rollback.json index add5d3c14d8..1cc608a344d 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/set_version_can_rollback.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/set_version_can_rollback.json @@ -1,148 +1,147 @@ { - "description": "Set version rolls back after new primary with higher election Id", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 2, - "electionId": { - "$oid": "000000000000000000000001" - }, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 2, - "electionId": { - "$oid": "000000000000000000000001" - } + "description": "Set version rolls back after new primary with higher election Id", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 2, + "electionId": { + "$oid": "000000000000000000000001" }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 2, + "electionId": { + "$oid": "000000000000000000000001" } }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2, - "maxElectionId": { - "$oid": "000000000000000000000001" + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2, + "maxElectionId": { + "$oid": "000000000000000000000001" } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - }, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - } - } + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000002" + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" + } } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000002" } - }, - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 2, - "electionId": { - "$oid": "000000000000000000000001" - }, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + } + }, + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 2, + "electionId": { + "$oid": "000000000000000000000001" }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - } - } + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000002" + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" + } } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000002" } } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_equal_max_without_electionid.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_equal_max_without_electionid.json index ebbf654b774..3669511c5ab 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_equal_max_without_electionid.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_equal_max_without_electionid.json @@ -1,85 +1,84 @@ { - "description": "setVersion version that is equal is treated the same as greater than if there is no electionId", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + "description": "setVersion version that is equal is treated the same as greater than if there is no electionId", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1 - } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - } + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1 + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1 - } + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1 } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_greaterthan_max_without_electionid.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_greaterthan_max_without_electionid.json index 3b15af71f13..97870d71d53 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_greaterthan_max_without_electionid.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_greaterthan_max_without_electionid.json @@ -1,85 +1,84 @@ { - "description": "setVersion that is greater than maxSetVersion is used if there is no electionId", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + "description": "setVersion that is greater than maxSetVersion is used if there is no electionId", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1 - } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 2, - "minWireVersion": 0, - "maxWireVersion": 17 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 2, - "electionId": null - } + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1 + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 2, + "minWireVersion": 0, + "maxWireVersion": 17 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2 - } + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 2, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2 } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_without_electionid-pre-6.0.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_without_electionid-pre-6.0.json index bc0e86fad9e..e62c6963ed3 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_without_electionid-pre-6.0.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/setversion_without_electionid-pre-6.0.json @@ -1,85 +1,84 @@ { - "description": "Pre 6.0 setVersion is ignored if there is no electionId", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 2, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 2, - "electionId": null - }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - } + "description": "Pre 6.0 setVersion is ignored if there is no electionId", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 2, + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 2, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2 - } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": null - } + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2 + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2 - } + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2 } - ] - } - \ No newline at end of file + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/stepdown_change_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/stepdown_change_set_name.json index e9075f97f22..6de995518d3 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/stepdown_change_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/stepdown_change_set_name.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -45,7 +45,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_new.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_new.json index 0433d27a368..696246f8e10 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_new.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_new.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_old.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_old.json index 461d00acc4c..dc8a5b2b9c4 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_old.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/too_old.json @@ -16,7 +16,7 @@ "b:27017" ], "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -30,7 +30,9 @@ "hosts": [ "a:27017", "b:27017" - ] + ], + "minWireVersion": 999, + "maxWireVersion": 1000 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/unexpected_mongos.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/unexpected_mongos.json index cc19a961f2c..c6ffb321cae 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/unexpected_mongos.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/unexpected_mongos.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/use_setversion_without_electionid-pre-6.0.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/use_setversion_without_electionid-pre-6.0.json index d8e6186fb0d..2f9b567b850 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/use_setversion_without_electionid-pre-6.0.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/use_setversion_without_electionid-pre-6.0.json @@ -1,138 +1,138 @@ { - "description": "Pre 6.0 Record max setVersion, even from primary without electionId", - "uri": "mongodb://a/?replicaSet=rs", - "phases": [ - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000001" - }, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000001" - } + "description": "Pre 6.0 Record max setVersion, even from primary without electionId", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000001" }, - "b:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000001" } }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 1, - "maxElectionId": { - "$oid": "000000000000000000000001" + "b:27017": { + "type": "Unknown", + "setName": null, + "electionId": null } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 1, + "maxElectionId": { + "$oid": "000000000000000000000001" } - }, - { - "responses": [ - [ - "b:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 2, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null - }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 2 - } + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 2, + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2, - "maxElectionId": { - "$oid": "000000000000000000000001" + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 2 } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2, + "maxElectionId": { + "$oid": "000000000000000000000001" } - }, - { - "responses": [ - [ - "a:27017", - { - "ok": 1, - "helloOk": true, - "isWritablePrimary": true, - "hosts": [ - "a:27017", - "b:27017" - ], - "setName": "rs", - "setVersion": 1, - "electionId": { - "$oid": "000000000000000000000002" - }, - "minWireVersion": 0, - "maxWireVersion": 6 - } - ] - ], - "outcome": { - "servers": { - "a:27017": { - "type": "Unknown", - "setName": null, - "electionId": null + } + }, + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "helloOk": true, + "isWritablePrimary": true, + "hosts": [ + "a:27017", + "b:27017" + ], + "setName": "rs", + "setVersion": 1, + "electionId": { + "$oid": "000000000000000000000002" }, - "b:27017": { - "type": "RSPrimary", - "setName": "rs", - "setVersion": 2 - } + "minWireVersion": 0, + "maxWireVersion": 7 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "Unknown", + "setName": null, + "electionId": null }, - "topologyType": "ReplicaSetWithPrimary", - "logicalSessionTimeoutMinutes": null, - "setName": "rs", - "maxSetVersion": 2, - "maxElectionId": { - "$oid": "000000000000000000000001" + "b:27017": { + "type": "RSPrimary", + "setName": "rs", + "setVersion": 2 } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs", + "maxSetVersion": 2, + "maxElectionId": { + "$oid": "000000000000000000000001" } } - ] - } + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/wrong_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/wrong_set_name.json index 9654ff7b79b..d0764d24dc3 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/wrong_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/rs/wrong_set_name.json @@ -17,7 +17,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/discover_single_mongos.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/discover_single_mongos.json index 9e877a0840d..bf7e57521c0 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/discover_single_mongos.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/discover_single_mongos.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/ls_timeout_mongos.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/ls_timeout_mongos.json index 93fa398d52e..3da0f84ca23 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/ls_timeout_mongos.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/ls_timeout_mongos.json @@ -13,7 +13,7 @@ "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -25,7 +25,7 @@ "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 2, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -56,7 +56,7 @@ "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -67,7 +67,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/mongos_disconnect.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/mongos_disconnect.json index 50a93eda5ff..29b33518695 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/mongos_disconnect.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/mongos_disconnect.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -23,7 +23,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -76,7 +76,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/multiple_mongoses.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/multiple_mongoses.json index 311592d715a..ae0c2d9cdef 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/multiple_mongoses.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/multiple_mongoses.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -23,7 +23,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/non_mongos_removed.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/non_mongos_removed.json index d74375ebbfd..4698f576d5a 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/non_mongos_removed.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/non_mongos_removed.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -26,7 +26,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_new.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_new.json index 4b997d21639..c4e984ddec0 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_new.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_new.json @@ -21,7 +21,9 @@ "ok": 1, "helloOk": true, "isWritablePrimary": true, - "msg": "isdbgrid" + "msg": "isdbgrid", + "minWireVersion": 7, + "maxWireVersion": 900 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_old.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_old.json index 688e1db0f5a..b918715ada8 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_old.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/sharded/too_old.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 2, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_external_ip.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_external_ip.json index 90676a8f9b0..1461b4c4694 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_external_ip.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_external_ip.json @@ -15,7 +15,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_mongos.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_mongos.json index 25fe9651856..72be020862b 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_mongos.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_mongos.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_replicaset.json index cd8660888a0..82a51d390eb 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_replicaset.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_replicaset.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsarbiter.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsarbiter.json index e2049560566..e06d2843645 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsarbiter.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsarbiter.json @@ -17,7 +17,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsprimary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsprimary.json index 409e8502b3c..45eb1602fb7 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsprimary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rsprimary.json @@ -16,7 +16,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rssecondary.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rssecondary.json index 305f283b527..b1bef8a49f4 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rssecondary.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_rssecondary.json @@ -17,7 +17,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_standalone.json index b47278482a7..e71ba07e740 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_standalone.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_wrong_set_name.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_wrong_set_name.json index 71080e6810e..8014a0a5337 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_wrong_set_name.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/direct_connection_wrong_set_name.json @@ -16,7 +16,7 @@ ], "setName": "wrong", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], @@ -45,7 +45,7 @@ ], "setName": "rs", "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/discover_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/discover_standalone.json index 858cbdaf638..d78c81654b2 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/discover_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/discover_standalone.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/ls_timeout_standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/ls_timeout_standalone.json index 87b3e4e8a10..236eabe00ab 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/ls_timeout_standalone.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/ls_timeout_standalone.json @@ -12,7 +12,7 @@ "isWritablePrimary": true, "logicalSessionTimeoutMinutes": 7, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/not_ok_response.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/not_ok_response.json index 8e7c2a10e37..cfaac3564ac 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/not_ok_response.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/not_ok_response.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ], [ @@ -21,7 +21,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_removed.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_removed.json index 57f8f861b18..675cdbb0083 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_removed.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_removed.json @@ -11,7 +11,7 @@ "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_using_legacy_hello.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_using_legacy_hello.json index 46660fa8de5..488cac49181 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_using_legacy_hello.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/standalone_using_legacy_hello.json @@ -10,7 +10,7 @@ "ok": 1, "ismaster": true, "minWireVersion": 0, - "maxWireVersion": 6 + "maxWireVersion": 21 } ] ], diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/too_old_then_upgraded.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/too_old_then_upgraded.json index 7ab930536b1..c3dd98cf62e 100644 --- a/src/libmongoc/tests/json/server_discovery_and_monitoring/single/too_old_then_upgraded.json +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/single/too_old_then_upgraded.json @@ -1,5 +1,5 @@ { - "description": "Standalone with default maxWireVersion of 0 is upgraded to one with maxWireVersion 6", + "description": "Standalone with default maxWireVersion of 0 is upgraded to one with maxWireVersion 21", "uri": "mongodb://a", "phases": [ { diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-error.json new file mode 100644 index 00000000000..62d26494c7c --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-error.json @@ -0,0 +1,230 @@ +{ + "description": "auth-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "auth": true, + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "auth-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after AuthenticationFailure error", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authErrorTest", + "errorCode": 18 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "auth-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "auth-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "auth-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-misc-command-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-misc-command-error.json new file mode 100644 index 00000000000..fd62fe604e9 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-misc-command-error.json @@ -0,0 +1,230 @@ +{ + "description": "auth-misc-command-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "auth": true, + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "auth-misc-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after misc command error", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authMiscErrorTest", + "errorCode": 1 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authMiscErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "auth-misc-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "auth-misc-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "auth-misc-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-error.json new file mode 100644 index 00000000000..84763af32e4 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-error.json @@ -0,0 +1,230 @@ +{ + "description": "auth-network-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "auth": true, + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "auth-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after network error during authentication", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "closeConnection": true, + "appName": "authNetworkErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authNetworkErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "auth-network-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "auth-network-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "auth-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-timeout-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-timeout-error.json new file mode 100644 index 00000000000..3cf9576eba9 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-network-timeout-error.json @@ -0,0 +1,233 @@ +{ + "description": "auth-network-timeout-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "auth": true, + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "auth-network-timeout-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after network timeout error during authentication", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "blockConnection": true, + "blockTimeMS": 500, + "appName": "authNetworkTimeoutErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authNetworkTimeoutErrorTest", + "connectTimeoutMS": 250, + "socketTimeoutMS": 250 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "auth-network-timeout-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "auth-network-timeout-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "auth-network-timeout-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-shutdown-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-shutdown-error.json new file mode 100644 index 00000000000..b9e503af66e --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/auth-shutdown-error.json @@ -0,0 +1,230 @@ +{ + "description": "auth-shutdown-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "auth": true, + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "auth-shutdown-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after shutdown error during authentication", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authShutdownErrorTest", + "errorCode": 91 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authShutdownErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "auth-shutdown-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "auth-shutdown-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "auth-shutdown-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/cancel-server-check.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/cancel-server-check.json new file mode 100644 index 00000000000..a60ccfcb414 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/cancel-server-check.json @@ -0,0 +1,201 @@ +{ + "description": "cancel-server-check", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ], + "serverless": "forbid" + }, + { + "minServerVersion": "4.2", + "topologies": [ + "sharded" + ], + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "cancel-server-check", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Cancel server check", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": true, + "heartbeatFrequencyMS": 10000, + "serverSelectionTimeoutMS": 5000, + "appname": "cancelServerCheckTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "cancel-server-check" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + }, + "client": "setupClient" + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 2 + } + }, + "expectResult": { + "insertedId": 2 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 3 + } + }, + "expectResult": { + "insertedId": 3 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "outcome": [ + { + "collectionName": "cancel-server-check", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/connectTimeoutMS.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/connectTimeoutMS.json new file mode 100644 index 00000000000..d3e860a9cb2 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/connectTimeoutMS.json @@ -0,0 +1,221 @@ +{ + "description": "connectTimeoutMS", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "connectTimeoutMS", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "connectTimeoutMS=0", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 0, + "heartbeatFrequencyMS": 500, + "appname": "connectTimeoutMS=0" + }, + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "connectTimeoutMS" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "connectTimeoutMS=0", + "blockConnection": true, + "blockTimeMS": 550 + } + }, + "client": "setupClient" + } + }, + { + "name": "wait", + "object": "testRunner", + "arguments": { + "ms": 750 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 0 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 0 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "connectTimeoutMS", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "connectTimeoutMS", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "connectTimeoutMS", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-error.json new file mode 100644 index 00000000000..c1b6db40ca3 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-error.json @@ -0,0 +1,234 @@ +{ + "description": "find-network-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "find-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after network error on find", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true, + "appName": "findNetworkErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "retryReads": false, + "appname": "findNetworkErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "find-network-error" + } + } + ] + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "find-network-error" + }, + "commandName": "find", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "find-network-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "find-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-timeout-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-timeout-error.json new file mode 100644 index 00000000000..e5ac9f21aa7 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-network-timeout-error.json @@ -0,0 +1,199 @@ +{ + "description": "find-network-timeout-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "find-network-timeout-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Ignore network timeout error on find", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "blockConnection": true, + "blockTimeMS": 500, + "appName": "findNetworkTimeoutErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "retryReads": false, + "appname": "findNetworkTimeoutErrorTest", + "socketTimeoutMS": 250 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "find-network-timeout-error" + } + } + ] + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 3 + } + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 0 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 0 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "find-network-timeout-error" + }, + "commandName": "find", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "find-network-timeout-error", + "documents": [ + { + "_id": 3 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "find-network-timeout-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-shutdown-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-shutdown-error.json new file mode 100644 index 00000000000..6e5a2cac055 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/find-shutdown-error.json @@ -0,0 +1,251 @@ +{ + "description": "find-shutdown-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "find-shutdown-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Concurrent shutdown error on find", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "uriOptions": { + "retryWrites": false, + "retryReads": false, + "heartbeatFrequencyMS": 500, + "appname": "shutdownErrorFindTest" + }, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "find-shutdown-error" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "appName": "shutdownErrorFindTest", + "errorCode": 91, + "blockConnection": true, + "blockTimeMS": 500 + } + }, + "client": "setupClient" + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "thread": { + "id": "thread0" + } + }, + { + "thread": { + "id": "thread1" + } + } + ] + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread0", + "operation": { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread0" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 4 + } + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "outcome": [ + { + "collectionName": "find-shutdown-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-command-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-command-error.json new file mode 100644 index 00000000000..87958cb2c0b --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-command-error.json @@ -0,0 +1,376 @@ +{ + "description": "hello-command-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4.7", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "hello-command-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Command error on Monitor handshake", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "commandErrorHandshakeTest", + "closeConnection": false, + "errorCode": 91 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent", + "commandStartedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 250, + "heartbeatFrequencyMS": 500, + "appname": "commandErrorHandshakeTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-command-error" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-command-error", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-command-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + }, + { + "description": "Command error on Monitor check", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 1000, + "heartbeatFrequencyMS": 500, + "appname": "commandErrorCheckTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-command-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "commandErrorCheckTest", + "closeConnection": false, + "blockConnection": true, + "blockTimeMS": 750, + "errorCode": 91 + } + }, + "client": "setupClient" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-command-error", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "hello-command-error", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-command-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-network-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-network-error.json new file mode 100644 index 00000000000..15ed2b605e2 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-network-error.json @@ -0,0 +1,346 @@ +{ + "description": "hello-network-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4.7", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "hello-network-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Network error on Monitor handshake", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "networkErrorHandshakeTest", + "closeConnection": true + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 250, + "heartbeatFrequencyMS": 500, + "appname": "networkErrorHandshakeTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-network-error" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-network-error", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + }, + { + "description": "Network error on Monitor check", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 250, + "heartbeatFrequencyMS": 500, + "appname": "networkErrorCheckTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-network-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "networkErrorCheckTest", + "closeConnection": true + } + }, + "client": "setupClient" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-network-error", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "hello-network-error", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-timeout.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-timeout.json new file mode 100644 index 00000000000..fe7cf4e78d1 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/hello-timeout.json @@ -0,0 +1,514 @@ +{ + "description": "hello-timeout", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "hello-timeout", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Network timeout on Monitor handshake", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "timeoutMonitorHandshakeTest", + "blockConnection": true, + "blockTimeMS": 1000 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 250, + "heartbeatFrequencyMS": 500, + "appname": "timeoutMonitorHandshakeTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-timeout" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-timeout", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-timeout", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ] + }, + { + "description": "Network timeout on Monitor check", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 750, + "heartbeatFrequencyMS": 500, + "appname": "timeoutMonitorCheckTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-timeout" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "timeoutMonitorCheckTest", + "blockConnection": true, + "blockTimeMS": 1000 + } + }, + "client": "setupClient" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-timeout", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "hello-timeout", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-timeout", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + ] + }, + { + "description": "Driver extends timeout while streaming", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "connectTimeoutMS": 250, + "heartbeatFrequencyMS": 500, + "appname": "extendsTimeoutTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "hello-timeout" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + }, + { + "name": "wait", + "object": "testRunner", + "arguments": { + "ms": 2000 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 0 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 0 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "hello-timeout", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "hello-timeout", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "hello-timeout", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-network-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-network-error.json new file mode 100644 index 00000000000..bfe41a4cb66 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-network-error.json @@ -0,0 +1,246 @@ +{ + "description": "insert-network-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "insert-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Reset server and pool after network error on insert", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true, + "appName": "insertNetworkErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "commandStartedEvent", + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "insertNetworkErrorTest" + }, + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "insert-network-error" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "insert-network-error", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "insert-network-error", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "insert-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-shutdown-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-shutdown-error.json new file mode 100644 index 00000000000..af7c6c987af --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/insert-shutdown-error.json @@ -0,0 +1,250 @@ +{ + "description": "insert-shutdown-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "insert-shutdown-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Concurrent shutdown error on insert", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "uriOptions": { + "retryWrites": false, + "heartbeatFrequencyMS": 500, + "appname": "shutdownErrorInsertTest" + }, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "insert-shutdown-error" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "appName": "shutdownErrorInsertTest", + "errorCode": 91, + "blockConnection": true, + "blockTimeMS": 500 + } + }, + "client": "setupClient" + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "thread": { + "id": "thread0" + } + }, + { + "thread": { + "id": "thread1" + } + } + ] + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread0", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 2 + } + }, + "expectError": { + "isError": true + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 3 + } + }, + "expectError": { + "isError": true + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread0" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 4 + } + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "outcome": [ + { + "collectionName": "insert-shutdown-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 4 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/interruptInUse-pool-clear.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/interruptInUse-pool-clear.json new file mode 100644 index 00000000000..d9329646d4c --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/interruptInUse-pool-clear.json @@ -0,0 +1,591 @@ +{ + "description": "interruptInUse", + "schemaVersion": "1.11", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "interruptInUse", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Connection pool clear uses interruptInUseConnections=true after monitor timeout", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "poolClearedEvent", + "connectionClosedEvent", + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent", + "connectionCheckedOutEvent", + "connectionCheckedInEvent" + ], + "uriOptions": { + "connectTimeoutMS": 500, + "heartbeatFrequencyMS": 500, + "appname": "interruptInUse", + "retryReads": false, + "minPoolSize": 0 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "interruptInUse" + } + }, + { + "thread": { + "id": "thread1" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$where": "sleep(2000) || true" + } + }, + "expectError": { + "isError": true + } + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "blockConnection": true, + "blockTimeMS": 1500, + "appName": "interruptInUse" + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandSucceededEvent": { + "commandName": "insert" + } + }, + { + "commandStartedEvent": { + "commandName": "find" + } + }, + { + "commandFailedEvent": { + "commandName": "find" + } + } + ] + }, + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckedOutEvent": {} + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionCheckedOutEvent": {} + }, + { + "poolClearedEvent": { + "interruptInUseConnections": true + } + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ], + "outcome": [ + { + "collectionName": "interruptInUse", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "Error returned from connection pool clear with interruptInUseConnections=true is retryable", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "poolClearedEvent", + "connectionClosedEvent", + "commandStartedEvent", + "commandFailedEvent", + "commandSucceededEvent", + "connectionCheckedOutEvent", + "connectionCheckedInEvent" + ], + "uriOptions": { + "connectTimeoutMS": 500, + "heartbeatFrequencyMS": 500, + "appname": "interruptInUseRetryable", + "retryReads": true, + "minPoolSize": 0 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "interruptInUse" + } + }, + { + "thread": { + "id": "thread1" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$where": "sleep(2000) || true" + } + } + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "blockConnection": true, + "blockTimeMS": 1500, + "appName": "interruptInUseRetryable" + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandSucceededEvent": { + "commandName": "insert" + } + }, + { + "commandStartedEvent": { + "commandName": "find" + } + }, + { + "commandFailedEvent": { + "commandName": "find" + } + }, + { + "commandStartedEvent": { + "commandName": "find" + } + }, + { + "commandSucceededEvent": { + "commandName": "find" + } + } + ] + }, + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckedOutEvent": {} + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionCheckedOutEvent": {} + }, + { + "poolClearedEvent": { + "interruptInUseConnections": true + } + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionClosedEvent": {} + }, + { + "connectionCheckedOutEvent": {} + }, + { + "connectionCheckedInEvent": {} + } + ] + } + ], + "outcome": [ + { + "collectionName": "interruptInUse", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ] + }, + { + "description": "Error returned from connection pool clear with interruptInUseConnections=true is retryable for write", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "poolClearedEvent", + "connectionClosedEvent", + "commandStartedEvent", + "commandFailedEvent", + "commandSucceededEvent", + "connectionCheckedOutEvent", + "connectionCheckedInEvent" + ], + "uriOptions": { + "connectTimeoutMS": 500, + "heartbeatFrequencyMS": 500, + "appname": "interruptInUseRetryableWrite", + "retryWrites": true, + "minPoolSize": 0 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "interruptInUse" + } + }, + { + "thread": { + "id": "thread1" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "updateOne", + "object": "collection", + "arguments": { + "filter": { + "$where": "sleep(2000) || true" + }, + "update": { + "$set": { + "a": "bar" + } + } + } + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 4 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "blockConnection": true, + "blockTimeMS": 1500, + "appName": "interruptInUseRetryableWrite" + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert" + } + }, + { + "commandSucceededEvent": { + "commandName": "insert" + } + }, + { + "commandStartedEvent": { + "commandName": "update" + } + }, + { + "commandFailedEvent": { + "commandName": "update" + } + }, + { + "commandStartedEvent": { + "commandName": "update" + } + }, + { + "commandSucceededEvent": { + "commandName": "update" + } + } + ] + }, + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckedOutEvent": {} + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionCheckedOutEvent": {} + }, + { + "poolClearedEvent": { + "interruptInUseConnections": true + } + }, + { + "connectionCheckedInEvent": {} + }, + { + "connectionClosedEvent": {} + }, + { + "connectionCheckedOutEvent": {} + }, + { + "connectionCheckedInEvent": {} + } + ] + } + ], + "outcome": [ + { + "collectionName": "interruptInUse", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1, + "a": "bar" + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/loadbalanced-emit-topology-changed-before-close.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/loadbalanced-emit-topology-changed-before-close.json new file mode 100644 index 00000000000..30c0657630b --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/loadbalanced-emit-topology-changed-before-close.json @@ -0,0 +1,88 @@ +{ + "description": "loadbalanced-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "load-balanced" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": {} + } + }, + { + "topologyDescriptionChangedEvent": { + "newDescription": { + "type": "LoadBalanced" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-loadbalanced.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-loadbalanced.json new file mode 100644 index 00000000000..0ad3b0ceaa5 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-loadbalanced.json @@ -0,0 +1,166 @@ +{ + "description": "loadbalanced-logging", + "schemaVersion": "1.16", + "runOnRequirements": [ + { + "topologies": [ + "load-balanced" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "topologyDescriptionChangedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring", + "topologyId": { + "$$exists": true + } + } + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-replicaset.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-replicaset.json new file mode 100644 index 00000000000..fe6ac60b685 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-replicaset.json @@ -0,0 +1,610 @@ +{ + "description": "replicaset-logging", + "schemaVersion": "1.16", + "runOnRequirements": [ + { + "topologies": [ + "replicaset" + ], + "minServerVersion": "4.4" + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient" + } + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "topologyDescriptionChangedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 4 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring", + "topologyId": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "Successful heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatSucceededEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatSucceededEvent": {} + }, + "count": 3 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "serverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1 + } + } + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "serverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1 + } + } + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "serverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1 + } + } + } + } + } + ] + } + ] + }, + { + "description": "Failing heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatFailedEvent" + ], + "uriOptions": { + "appname": "failingHeartbeatLoggingTest" + } + } + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "failingHeartbeatLoggingTest", + "closeConnection": true + } + }, + "client": "setupClient" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatFailedEvent": {} + }, + "count": 1 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "failure": { + "$$exists": true + } + } + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-sharded.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-sharded.json new file mode 100644 index 00000000000..3788708ab08 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-sharded.json @@ -0,0 +1,494 @@ +{ + "description": "sharded-logging", + "schemaVersion": "1.16", + "runOnRequirements": [ + { + "topologies": [ + "sharded" + ], + "minServerVersion": "4.4" + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "topologyDescriptionChangedEvent" + ], + "useMultipleMongoses": true + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 3 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring", + "topologyId": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "Successful heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatSucceededEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatSucceededEvent": {} + }, + "count": 1 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "serverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1 + } + } + } + } + } + ] + } + ] + }, + { + "description": "Failing heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatFailedEvent" + ], + "uriOptions": { + "appname": "failingHeartbeatLoggingTest" + } + } + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "failingHeartbeatLoggingTest", + "closeConnection": true + } + }, + "client": "setupClient" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatFailedEvent": {} + }, + "count": 1 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "failure": { + "$$exists": true + } + } + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-standalone.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-standalone.json new file mode 100644 index 00000000000..0682a1a4fb2 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/logging-standalone.json @@ -0,0 +1,519 @@ +{ + "description": "standalone-logging", + "schemaVersion": "1.16", + "runOnRequirements": [ + { + "topologies": [ + "single" + ], + "minServerVersion": "4.4" + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient" + } + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "topologyDescriptionChangedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring", + "topologyId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring", + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring", + "topologyId": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "Successful heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatSucceededEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatSucceededEvent": {} + }, + "count": 1 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + } + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "serverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1 + } + } + } + } + } + ] + } + ] + }, + { + "description": "Failing heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "topology": "debug" + }, + "observeEvents": [ + "serverHeartbeatFailedEvent" + ], + "uriOptions": { + "appname": "failingHeartbeatLoggingTest" + } + } + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "failingHeartbeatLoggingTest", + "closeConnection": true + } + } + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatFailedEvent": {} + }, + "count": 1 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "ignoreExtraMessages": true, + "ignoreMessages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped topology monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Stopped server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting server monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Starting topology monitoring" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat started" + } + }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat succeeded" + } + } + ], + "messages": [ + { + "level": "debug", + "component": "topology", + "data": { + "message": "Server heartbeat failed", + "awaited": { + "$$exists": true + }, + "topologyId": { + "$$exists": true + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "driverConnectionId": { + "$$exists": true + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + }, + "failure": { + "$$exists": true + } + } + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/minPoolSize-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/minPoolSize-error.json new file mode 100644 index 00000000000..bd9e9fcdec7 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/minPoolSize-error.json @@ -0,0 +1,177 @@ +{ + "description": "minPoolSize-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4.7", + "serverless": "forbid", + "topologies": [ + "single" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "sdam-minPoolSize-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Network error on minPoolSize background creation", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "skip": 3 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "SDAMminPoolSizeError", + "closeConnection": true + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent", + "poolReadyEvent" + ], + "uriOptions": { + "heartbeatFrequencyMS": 10000, + "appname": "SDAMminPoolSizeError", + "minPoolSize": 10, + "serverSelectionTimeoutMS": 1000 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "sdam-minPoolSize-error" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolReadyEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": {} + }, + "commandName": "ping" + }, + "expectError": { + "isError": true + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "off" + }, + "client": "setupClient" + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolReadyEvent": {} + }, + "count": 2 + } + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-application-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-application-error.json new file mode 100644 index 00000000000..b8fd95fee39 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-application-error.json @@ -0,0 +1,149 @@ +{ + "description": "pool-clear-application-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "find-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Pool is cleared before application connection is checked into the pool", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true, + "appName": "findNetworkErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "poolClearedEvent", + "connectionCheckedInEvent" + ], + "uriOptions": { + "retryWrites": false, + "retryReads": false, + "appname": "findNetworkErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "find-network-error" + } + } + ] + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionCheckedInEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "poolClearedEvent": {} + }, + { + "connectionCheckedInEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-checkout-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-checkout-error.json new file mode 100644 index 00000000000..126ee545333 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-checkout-error.json @@ -0,0 +1,296 @@ +{ + "description": "pool-clear-on-error-checkout", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "tests": [ + { + "description": "Pool is cleared before connection is closed (authentication error)", + "runOnRequirements": [ + { + "auth": true + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authErrorTest", + "errorCode": 18 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "connectionCheckOutStartedEvent", + "poolClearedEvent", + "connectionClosedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "bar" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + }, + { + "description": "Pool is cleared before connection is closed (handshake error)", + "runOnRequirements": [ + { + "topologies": [ + "single" + ] + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "connectionCheckOutStartedEvent", + "poolClearedEvent", + "connectionClosedEvent", + "topologyDescriptionChangedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authErrorTest", + "minPoolSize": 0, + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 1000000 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "bar" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + "count": 1 + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "authErrorTest", + "closeConnection": true + } + } + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-min-pool-size-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-min-pool-size-error.json new file mode 100644 index 00000000000..11c6be5bc16 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-clear-min-pool-size-error.json @@ -0,0 +1,230 @@ +{ + "description": "pool-cleared-on-min-pool-size-population-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "tests": [ + { + "description": "Pool is cleared on authentication error during minPoolSize population", + "runOnRequirements": [ + { + "auth": true + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authErrorTest", + "errorCode": 18 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "connectionCreatedEvent", + "poolClearedEvent", + "connectionClosedEvent" + ], + "uriOptions": { + "appname": "authErrorTest", + "minPoolSize": 1 + } + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCreatedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + }, + { + "description": "Pool is cleared on handshake error during minPoolSize population", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "connectionCreatedEvent", + "poolClearedEvent", + "connectionClosedEvent", + "connectionReadyEvent" + ], + "uriOptions": { + "appname": "authErrorTest", + "minPoolSize": 5, + "maxConnecting": 1, + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 1000000 + } + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + "count": 1 + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "authErrorTest", + "closeConnection": true + } + } + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCreatedEvent": {} + }, + { + "connectionReadyEvent": {} + }, + { + "connectionCreatedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-cleared-error.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-cleared-error.json new file mode 100644 index 00000000000..b7f6924f2ba --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/pool-cleared-error.json @@ -0,0 +1,373 @@ +{ + "description": "pool-cleared-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.9", + "serverless": "forbid", + "topologies": [ + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "pool-cleared-error", + "databaseName": "sdam-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "PoolClearedError does not mark server unknown", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "serverDescriptionChangedEvent", + "poolClearedEvent" + ], + "uriOptions": { + "retryWrites": true, + "maxPoolSize": 1, + "appname": "poolClearedErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "pool-cleared-error" + } + } + ] + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 1 + } + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "blockConnection": true, + "blockTimeMS": 100, + "closeConnection": true, + "appName": "poolClearedErrorTest" + } + }, + "client": "setupClient" + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "thread": { + "id": "thread0" + } + }, + { + "thread": { + "id": "thread1" + } + }, + { + "thread": { + "id": "thread2" + } + }, + { + "thread": { + "id": "thread3" + } + }, + { + "thread": { + "id": "thread4" + } + }, + { + "thread": { + "id": "thread5" + } + } + ] + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread0", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 2 + } + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread1", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 3 + } + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread2", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 4 + } + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread3", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 5 + } + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread4", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 6 + } + } + } + } + }, + { + "name": "runOnThread", + "object": "testRunner", + "arguments": { + "thread": "thread5", + "operation": { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 7 + } + } + } + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread0" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread1" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread2" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread3" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread4" + } + }, + { + "name": "waitForThread", + "object": "testRunner", + "arguments": { + "thread": "thread5" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "_id": 8 + } + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + } + ], + "outcome": [ + { + "collectionName": "pool-cleared-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + }, + { + "_id": 5 + }, + { + "_id": 6 + }, + { + "_id": 7 + }, + { + "_id": 8 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/rediscover-quickly-after-step-down.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/rediscover-quickly-after-step-down.json new file mode 100644 index 00000000000..3147a07a1e6 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/rediscover-quickly-after-step-down.json @@ -0,0 +1,242 @@ +{ + "description": "rediscover-quickly-after-step-down", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient" + } + }, + { + "database": { + "id": "adminDatabase", + "client": "setupClient", + "databaseName": "admin" + } + } + ], + "initialData": [ + { + "collectionName": "test-replSetStepDown", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Rediscover quickly after replSetStepDown", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "poolClearedEvent", + "commandStartedEvent" + ], + "uriOptions": { + "appname": "replSetStepDownTest", + "heartbeatFrequencyMS": 60000, + "serverSelectionTimeoutMS": 5000, + "w": "majority" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "test-replSetStepDown" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + } + }, + { + "name": "recordTopologyDescription", + "object": "testRunner", + "arguments": { + "client": "client", + "id": "topologyDescription" + } + }, + { + "name": "assertTopologyType", + "object": "testRunner", + "arguments": { + "topologyDescription": "topologyDescription", + "topologyType": "ReplicaSetWithPrimary" + } + }, + { + "name": "runCommand", + "object": "adminDatabase", + "arguments": { + "command": { + "replSetFreeze": 0 + }, + "readPreference": { + "mode": "secondary" + }, + "commandName": "replSetFreeze" + } + }, + { + "name": "runCommand", + "object": "adminDatabase", + "arguments": { + "command": { + "replSetStepDown": 30, + "secondaryCatchUpPeriodSecs": 30, + "force": false + }, + "commandName": "replSetStepDown" + } + }, + { + "name": "waitForPrimaryChange", + "object": "testRunner", + "arguments": { + "client": "client", + "priorTopologyDescription": "topologyDescription", + "timeoutMS": 15000 + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 0 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "command", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "test-replSetStepDown", + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "test-replSetStepDown", + "documents": [ + { + "_id": 5 + }, + { + "_id": 6 + } + ] + }, + "commandName": "insert", + "databaseName": "sdam-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "test-replSetStepDown", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + }, + { + "_id": 3 + }, + { + "_id": 4 + }, + { + "_id": 5 + }, + { + "_id": 6 + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/replicaset-emit-topology-changed-before-close.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/replicaset-emit-topology-changed-before-close.json new file mode 100644 index 00000000000..066a4ffee5f --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/replicaset-emit-topology-changed-before-close.json @@ -0,0 +1,89 @@ +{ + "description": "replicaset-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "replicaset" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 4 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "ReplicaSetWithPrimary" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/serverMonitoringMode.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/serverMonitoringMode.json new file mode 100644 index 00000000000..4b492f7d853 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/serverMonitoringMode.json @@ -0,0 +1,512 @@ +{ + "description": "serverMonitoringMode", + "schemaVersion": "1.17", + "runOnRequirements": [ + { + "topologies": [ + "single", + "sharded", + "sharded-replicaset" + ], + "serverless": "forbid" + } + ], + "tests": [ + { + "description": "connect with serverMonitoringMode=auto >=4.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "auto" + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent", + "serverHeartbeatFailedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "db", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectResult": { + "ok": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 2 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": true, + "events": [ + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + }, + { + "serverHeartbeatSucceededEvent": { + "awaited": false + } + }, + { + "serverHeartbeatStartedEvent": { + "awaited": true + } + } + ] + } + ] + }, + { + "description": "connect with serverMonitoringMode=auto <4.4", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "auto", + "heartbeatFrequencyMS": 500 + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent", + "serverHeartbeatFailedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "db", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectResult": { + "ok": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 2 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": true, + "events": [ + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + }, + { + "serverHeartbeatSucceededEvent": { + "awaited": false + } + }, + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + } + ] + } + ] + }, + { + "description": "connect with serverMonitoringMode=stream >=4.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "stream" + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent", + "serverHeartbeatFailedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "db", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectResult": { + "ok": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 2 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": true, + "events": [ + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + }, + { + "serverHeartbeatSucceededEvent": { + "awaited": false + } + }, + { + "serverHeartbeatStartedEvent": { + "awaited": true + } + } + ] + } + ] + }, + { + "description": "connect with serverMonitoringMode=stream <4.4", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "stream", + "heartbeatFrequencyMS": 500 + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent", + "serverHeartbeatFailedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "db", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectResult": { + "ok": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 2 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": true, + "events": [ + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + }, + { + "serverHeartbeatSucceededEvent": { + "awaited": false + } + }, + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + } + ] + } + ] + }, + { + "description": "connect with serverMonitoringMode=poll", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 500 + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent", + "serverHeartbeatFailedEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "db", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectResult": { + "ok": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 2 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": true, + "events": [ + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + }, + { + "serverHeartbeatSucceededEvent": { + "awaited": false + } + }, + { + "serverHeartbeatStartedEvent": { + "awaited": false + } + } + ] + } + ] + }, + { + "description": "poll waits after successful heartbeat", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "uriOptions": { + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 1000000 + }, + "useMultipleMongoses": false, + "observeEvents": [ + "serverHeartbeatStartedEvent", + "serverHeartbeatSucceededEvent" + ] + } + }, + { + "database": { + "id": "db", + "client": "client", + "databaseName": "sdam-tests" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatSucceededEvent": {} + }, + "count": 1 + } + }, + { + "name": "wait", + "object": "testRunner", + "arguments": { + "ms": 500 + } + }, + { + "name": "assertEventCount", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverHeartbeatStartedEvent": {} + }, + "count": 1 + } + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/sharded-emit-topology-changed-before-close.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/sharded-emit-topology-changed-before-close.json new file mode 100644 index 00000000000..98fb5855314 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/sharded-emit-topology-changed-before-close.json @@ -0,0 +1,108 @@ +{ + "description": "sharded-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "sharded" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ], + "useMultipleMongoses": true + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 3 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Sharded" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Sharded" + }, + "newDescription": { + "type": "Sharded" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Sharded" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/standalone-emit-topology-changed-before-close.json b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/standalone-emit-topology-changed-before-close.json new file mode 100644 index 00000000000..27b5444d541 --- /dev/null +++ b/src/libmongoc/tests/json/server_discovery_and_monitoring/unified/standalone-emit-topology-changed-before-close.json @@ -0,0 +1,97 @@ +{ + "description": "standalone-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "single" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Single" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/src/libmongoc/tests/test-happy-eyeballs.c b/src/libmongoc/tests/test-happy-eyeballs.c index 77c7ee02762..2c60c2c3cee 100644 --- a/src/libmongoc/tests/test-happy-eyeballs.c +++ b/src/libmongoc/tests/test-happy-eyeballs.c @@ -6,6 +6,7 @@ #include #include +#include "common-oid-private.h" #include "TestSuite.h" #include "mock_server/mock-server.h" @@ -45,6 +46,7 @@ typedef struct he_testcase_state { mock_server_t *mock_server; mongoc_host_list_t host; mongoc_topology_scanner_t *ts; + mongoc_log_and_monitor_instance_t log_and_monitor; int64_t start; int last_duration; /* set if timing fails, so it can be retried once. */ } he_testcase_state_t; @@ -246,7 +248,11 @@ _testcase_setup (he_testcase_t *testcase) _init_host (&testcase->state.host, mock_server_get_port (mock_server), testcase->client.type); - testcase->state.ts = mongoc_topology_scanner_new (NULL, NULL, &_test_scanner_callback, testcase, TIMEOUT); + bson_oid_t topology_id; + mcommon_oid_set_zero (&topology_id); + mongoc_log_and_monitor_instance_init (&testcase->state.log_and_monitor); + testcase->state.ts = mongoc_topology_scanner_new ( + NULL, &topology_id, &testcase->state.log_and_monitor, NULL, &_test_scanner_callback, testcase, TIMEOUT); testcase->state.mock_server = mock_server; @@ -260,6 +266,7 @@ _testcase_teardown (he_testcase_t *testcase) { mock_server_destroy (testcase->state.mock_server); mongoc_topology_scanner_destroy (testcase->state.ts); + mongoc_log_and_monitor_instance_destroy_contents (&testcase->state.log_and_monitor); } static void diff --git a/src/libmongoc/tests/test-libmongoc.c b/src/libmongoc/tests/test-libmongoc.c index 99ee4e18093..9fa20283336 100644 --- a/src/libmongoc/tests/test-libmongoc.c +++ b/src/libmongoc/tests/test-libmongoc.c @@ -59,36 +59,12 @@ typedef struct { static bson_mutex_t captured_logs_mutex; static mongoc_array_t captured_logs; static bool capturing_logs; -static int suppress_structured_logs_counter_atomic; + #ifdef MONGOC_ENABLE_SSL static mongoc_ssl_opt_t gSSLOptions; #endif -bool -test_is_suppressing_structured_logs (void) -{ - int c = mcommon_atomic_int_fetch (&suppress_structured_logs_counter_atomic, mcommon_memory_order_seq_cst); - BSON_ASSERT (c >= 0); - return c > 0; -} - -// Ignore logs generated by test-internal operations. Can be nested. Structured logs only; see capturing_logs too. -void -test_begin_suppressing_structured_logs (void) -{ - mcommon_atomic_int_fetch_add (&suppress_structured_logs_counter_atomic, 1, mcommon_memory_order_seq_cst); -} - -void -test_end_suppressing_structured_logs (void) -{ - int previous = - mcommon_atomic_int_fetch_sub (&suppress_structured_logs_counter_atomic, 1, mcommon_memory_order_seq_cst); - BSON_ASSERT (previous > 0); -} - - static log_entry_t * log_entry_create (mongoc_log_level_t level, const char *msg) { @@ -869,8 +845,6 @@ call_hello_with_host_and_port (const char *host_and_port, bson_t *reply) mongoc_client_t *client; bson_error_t error; - test_begin_suppressing_structured_logs (); - if (test_framework_get_user_password (&user, &password)) { uri_str = bson_strdup_printf ( "mongodb://%s:%s@%s%s", user, password, host_and_port, test_framework_get_ssl () ? "/?ssl=true" : ""); @@ -917,7 +891,6 @@ call_hello_with_host_and_port (const char *host_and_port, bson_t *reply) mongoc_client_destroy (client); mongoc_uri_destroy (uri); bson_free (uri_str); - test_end_suppressing_structured_logs (); } /* @@ -2605,7 +2578,7 @@ test_libmongoc_destroy (TestSuite *suite) TestSuite_Destroy (suite); capture_logs (false); /* clear entries */ _mongoc_array_destroy (&captured_logs); - BSON_ASSERT (!test_is_suppressing_structured_logs ()); + bson_mutex_destroy (&captured_logs_mutex); mongoc_cleanup (); } diff --git a/src/libmongoc/tests/test-libmongoc.h b/src/libmongoc/tests/test-libmongoc.h index 468211e90e0..1b9a2b925a4 100644 --- a/src/libmongoc/tests/test-libmongoc.h +++ b/src/libmongoc/tests/test-libmongoc.h @@ -36,12 +36,7 @@ char * gen_collection_name (const char *prefix); mongoc_collection_t * get_test_collection (mongoc_client_t *client, const char *prefix); -bool -test_is_suppressing_structured_logs (void); -void -test_begin_suppressing_structured_logs (void); -void -test_end_suppressing_structured_logs (void); + void capture_logs (bool capture); void diff --git a/src/libmongoc/tests/test-mongoc-background-monitoring.c b/src/libmongoc/tests/test-mongoc-background-monitoring.c index 8b2ee879892..282795b3647 100644 --- a/src/libmongoc/tests/test-mongoc-background-monitoring.c +++ b/src/libmongoc/tests/test-mongoc-background-monitoring.c @@ -303,7 +303,7 @@ _signal_shutdown (test_fixture_t *tf) /* Ignore the "Last server removed from topology" warning. */ capture_logs (true); /* remove the server description from the topology description. */ - mongoc_topology_description_reconcile (tdmod.new_td, NULL); + mongoc_topology_description_reconcile (tdmod.new_td, &tf->client->topology->log_and_monitor, NULL); capture_logs (false); /* remove the server monitor from the set of server monitors. */ _mongoc_topology_background_monitoring_reconcile (tf->client->topology, tdmod.new_td); @@ -319,7 +319,8 @@ _add_server_monitor (test_fixture_t *tf) uri = mock_server_get_uri (tf->server); /* remove the server description from the topology description. */ - mongoc_topology_description_add_server (tdmod.new_td, mongoc_uri_get_hosts (uri)->host_and_port, &id); + mongoc_topology_description_add_server ( + tdmod.new_td, &tf->client->topology->log_and_monitor, mongoc_uri_get_hosts (uri)->host_and_port, &id); /* add the server monitor from the set of server monitors. */ _mongoc_topology_background_monitoring_reconcile (tf->client->topology, tdmod.new_td); mc_tpld_modify_commit (tdmod); diff --git a/src/libmongoc/tests/test-mongoc-client-pool.c b/src/libmongoc/tests/test-mongoc-client-pool.c index 462e03aa5b2..963fc39dd32 100644 --- a/src/libmongoc/tests/test-mongoc-client-pool.c +++ b/src/libmongoc/tests/test-mongoc-client-pool.c @@ -380,12 +380,12 @@ test_client_pool_create_unused_session (void *context) callbacks = mongoc_apm_callbacks_new (); pool = test_framework_new_default_client_pool (); - client = mongoc_client_pool_pop (pool); - session = mongoc_client_start_session (client, NULL, &error); - mongoc_apm_set_command_started_cb (callbacks, command_started_cb); mongoc_client_pool_set_apm_callbacks (pool, callbacks, &count); + client = mongoc_client_pool_pop (pool); + session = mongoc_client_start_session (client, NULL, &error); + mongoc_client_session_destroy (session); mongoc_client_pool_push (pool, client); mongoc_client_pool_destroy (pool); diff --git a/src/libmongoc/tests/test-mongoc-command-monitoring.c b/src/libmongoc/tests/test-mongoc-command-monitoring.c index e0a491a0179..0e8161e8cc0 100644 --- a/src/libmongoc/tests/test-mongoc-command-monitoring.c +++ b/src/libmongoc/tests/test-mongoc-command-monitoring.c @@ -355,8 +355,9 @@ _test_set_callbacks (bool pooled, bool try_pop) if (pooled) { ASSERT (!mongoc_client_pool_set_apm_callbacks (pool, NULL, (void *) &n_calls)); - ASSERT_CAPTURED_LOG ( - "mongoc_client_pool_set_apm_callbacks", MONGOC_LOG_LEVEL_ERROR, "Can only set callbacks once"); + ASSERT_CAPTURED_LOG ("mongoc_client_pool_set_apm_callbacks", + MONGOC_LOG_LEVEL_ERROR, + "mongoc_client_pool_set_apm_callbacks can only be called once per pool"); clear_captured_logs (); ASSERT (!mongoc_client_set_apm_callbacks (client, NULL, (void *) &n_calls)); diff --git a/src/libmongoc/tests/test-mongoc-dns.c b/src/libmongoc/tests/test-mongoc-dns.c index 6b7e2d86e72..7afd0921397 100644 --- a/src/libmongoc/tests/test-mongoc-dns.c +++ b/src/libmongoc/tests/test-mongoc-dns.c @@ -452,6 +452,7 @@ test_all_spec_tests (TestSuite *suite) extern bool mongoc_topology_apply_scanned_srv_hosts (mongoc_uri_t *uri, mongoc_topology_description_t *td, + const mongoc_log_and_monitor_instance_t *log_and_monitor, mongoc_host_list_t *hosts, bson_error_t *error); @@ -510,13 +511,16 @@ check_topology_description (mongoc_topology_description_t *td, mongoc_host_list_ mongoc_host_list_t *host; const mongoc_set_t *servers = mc_tpld_servers_const (td); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + for (host = hosts; host; host = host->next) { ++nhosts; /* Check that "host" is already in the topology description by upserting * it, and ensuring that the number of servers remains constant. */ const size_t server_count = servers->items_len; - BSON_ASSERT (mongoc_topology_description_add_server (td, host->host_and_port, NULL)); + BSON_ASSERT (mongoc_topology_description_add_server (td, &log_and_monitor, host->host_and_port, NULL)); if (server_count != servers->items_len) { dump_topology_description (td); @@ -530,6 +534,8 @@ check_topology_description (mongoc_topology_description_t *td, mongoc_host_list_ dump_hosts (hosts); test_error ("topology description had extra hosts"); } + + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } static void @@ -544,13 +550,16 @@ test_srv_polling_mocked (void *unused) BSON_UNUSED (unused); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + mongoc_topology_description_init (&td, 0); uri = mongoc_uri_new ("mongodb+srv://server.test.com/?tls=true"); capture_logs (true); hosts = MAKE_HOSTS ("a.test.com", "b.test.com"); expected = MAKE_HOSTS ("a.test.com", "b.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, hosts, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, hosts, &error); ASSERT_OR_PRINT (ret, error); check_topology_description (&td, expected); _mongoc_host_list_destroy_all (expected); @@ -560,7 +569,7 @@ test_srv_polling_mocked (void *unused) /* Add an extra host. */ hosts = MAKE_HOSTS ("x.test.com", "a.test.com", "y.test.com", "b.test.com"); expected = MAKE_HOSTS ("x.test.com", "a.test.com", "y.test.com", "b.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, hosts, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, hosts, &error); ASSERT_OR_PRINT (ret, error); check_topology_description (&td, expected); _mongoc_host_list_destroy_all (expected); @@ -570,7 +579,7 @@ test_srv_polling_mocked (void *unused) /* Remove all but one host. */ hosts = MAKE_HOSTS ("x.test.com"); expected = MAKE_HOSTS ("x.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, hosts, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, hosts, &error); ASSERT_OR_PRINT (ret, error); check_topology_description (&td, expected); _mongoc_host_list_destroy_all (expected); @@ -581,7 +590,7 @@ test_srv_polling_mocked (void *unused) * logged. */ hosts = MAKE_HOSTS ("x.test.com", "y.test.com", "bad.wrongdomain.com"); expected = MAKE_HOSTS ("x.test.com", "y.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, hosts, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, hosts, &error); ASSERT_OR_PRINT (ret, error); check_topology_description (&td, expected); _mongoc_host_list_destroy_all (expected); @@ -591,7 +600,7 @@ test_srv_polling_mocked (void *unused) /* An empty host list returns false but does NOT change topology description */ expected = MAKE_HOSTS ("x.test.com", "y.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, NULL, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, NULL, &error); BSON_ASSERT (!ret); ASSERT_ERROR_CONTAINS ( error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_NAME_RESOLUTION, "SRV response did not contain any valid hosts"); @@ -603,7 +612,7 @@ test_srv_polling_mocked (void *unused) */ hosts = MAKE_HOSTS ("bad1.wrongdomain.com", "bad2.wrongdomain.com"); expected = MAKE_HOSTS ("x.test.com", "y.test.com"); - ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, NULL, &error); + ret = mongoc_topology_apply_scanned_srv_hosts (uri, &td, &log_and_monitor, NULL, &error); BSON_ASSERT (!ret); ASSERT_ERROR_CONTAINS ( error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_NAME_RESOLUTION, "SRV response did not contain any valid hosts"); @@ -614,6 +623,7 @@ test_srv_polling_mocked (void *unused) mongoc_topology_description_cleanup (&td); mongoc_uri_destroy (uri); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } static void diff --git a/src/libmongoc/tests/test-mongoc-loadbalanced.c b/src/libmongoc/tests/test-mongoc-loadbalanced.c index 9a0a1c2b283..4923b35de75 100644 --- a/src/libmongoc/tests/test-mongoc-loadbalanced.c +++ b/src/libmongoc/tests/test-mongoc-loadbalanced.c @@ -119,6 +119,14 @@ set_client_callbacks (mongoc_client_t *client) cbs = make_callbacks (); mongoc_client_set_apm_callbacks (client, cbs, stats); mongoc_apm_callbacks_destroy (cbs); + + if (test_suite_debug_output ()) { + mongoc_structured_log_opts_t *log_opts = mongoc_structured_log_opts_new (); + mongoc_structured_log_opts_set_max_level_for_all_components (log_opts, MONGOC_STRUCTURED_LOG_LEVEL_DEBUG); + mongoc_client_set_structured_log_opts (client, log_opts); + mongoc_structured_log_opts_destroy (log_opts); + } + return stats; } @@ -141,7 +149,12 @@ static void free_and_assert_stats (stats_t *stats) { ASSERT_CMPINT (stats->topology_opening_events, ==, 1); - ASSERT_CMPINT (stats->topology_changed_events, ==, 2); + /* See https://specifications.readthedocs.io/en/latest/load-balancers/load-balancers/ + * Expected TopologyDescriptionChangedEvent instances: + * 1. TopologyType Unknown -> TopologyType LoadBalanced with ServerType Unknown + * 2. TopologyType LoadBalanced with ServerType Unknown -> ServerType LoadBalancer + * 3. LoadBalanced LoadBalancer -> Unknown */ + ASSERT_CMPINT (stats->topology_changed_events, ==, 3); ASSERT_CMPINT (stats->server_opening_events, ==, 1); ASSERT_CMPINT (stats->server_changed_events, ==, 1); ASSERT_CMPINT (stats->server_closed_events, ==, 1); diff --git a/src/libmongoc/tests/test-mongoc-sdam-monitoring.c b/src/libmongoc/tests/test-mongoc-sdam-monitoring.c index ba172bc33aa..a66a40bd058 100644 --- a/src/libmongoc/tests/test-mongoc-sdam-monitoring.c +++ b/src/libmongoc/tests/test-mongoc-sdam-monitoring.c @@ -472,7 +472,7 @@ test_sdam_monitoring_cb (void *test_vp) * doesn't exercise this code path naturally, see below in * _test_topology_events for a non-hacky test of this event */ mc_tpld_modification tdmod = mc_tpld_modify_begin (topology); - _mongoc_topology_description_monitor_opening (tdmod.new_td); + _mongoc_topology_description_monitor_opening (tdmod.new_td, &topology->log_and_monitor); mc_tpld_modify_commit (tdmod); first_phase = false; } else { diff --git a/src/libmongoc/tests/test-mongoc-sdam.c b/src/libmongoc/tests/test-mongoc-sdam.c index 2b61ddd72ca..055e213601d 100644 --- a/src/libmongoc/tests/test-mongoc-sdam.c +++ b/src/libmongoc/tests/test-mongoc-sdam.c @@ -5,6 +5,7 @@ #include "json-test.h" +#include #include #include #include @@ -165,7 +166,7 @@ test_sdam_cb (void *test_vp) * when SDAM monitoring begins. Force an opening, which would occur on the * first operation on the client. */ tdmod = mc_tpld_modify_begin (client->topology); - _mongoc_topology_description_monitor_opening (tdmod.new_td); + _mongoc_topology_description_monitor_opening (tdmod.new_td, &client->topology->log_and_monitor); mc_tpld_modify_commit (tdmod); while (bson_iter_next (&phase_iter)) { @@ -848,6 +849,137 @@ test_prose_rtt (void *unused) BSON_ASSERT (ctx.n_heartbeat_succeeded > 0); } +typedef enum prose_heartbeat_event_t { + PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_STARTED = 1, + PROSE_HEARTBEAT_EVENT_CLIENT_CONNECTED, + PROSE_HEARTBEAT_EVENT_CLIENT_HELLO_RECEIVED, + PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_FAILED, +} prose_heartbeat_event_t; + +#define PROSE_HEARTBEAT_EVENTS_MAX 10 + +typedef struct prose_heartbeat_context_t { + bson_mutex_t mutex; + mongoc_cond_t cond; + uint16_t listen_port; + size_t num_events; + prose_heartbeat_event_t events[PROSE_HEARTBEAT_EVENTS_MAX]; +} prose_heartbeat_context_t; + +static void +prose_heartbeat_context_append_event (prose_heartbeat_context_t *context, prose_heartbeat_event_t event) +{ + bson_mutex_lock (&context->mutex); + size_t num_events = context->num_events; + ASSERT_CMPSIZE_T (num_events, <, PROSE_HEARTBEAT_EVENTS_MAX); + context->events[num_events] = event; + context->num_events = num_events + 1; + bson_mutex_unlock (&context->mutex); +} + +static BSON_THREAD_FUN (prose_heartbeat_thread, generic_context) +{ + prose_heartbeat_context_t *context = (prose_heartbeat_context_t *) generic_context; + + mongoc_socket_t *listen_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); + BSON_ASSERT (listen_sock); + + struct sockaddr_in server_addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + .sin_port = htons (0), + }; + + ASSERT_CMPINT (0, ==, mongoc_socket_bind (listen_sock, (struct sockaddr *) &server_addr, sizeof server_addr)); + + mongoc_socklen_t sock_len = sizeof (server_addr); + ASSERT_CMPINT (0, ==, mongoc_socket_getsockname (listen_sock, (struct sockaddr *) &server_addr, &sock_len)); + + ASSERT_CMPINT (0, ==, mongoc_socket_listen (listen_sock, 10)); + + bson_mutex_lock (&context->mutex); + context->listen_port = ntohs (server_addr.sin_port); + mongoc_cond_signal (&context->cond); + bson_mutex_unlock (&context->mutex); + + mongoc_socket_t *conn_sock = mongoc_socket_accept (listen_sock, -1); + BSON_ASSERT (conn_sock); + + prose_heartbeat_context_append_event (context, PROSE_HEARTBEAT_EVENT_CLIENT_CONNECTED); + + int64_t expire_at = bson_get_monotonic_time () + 10000000; + uint8_t buf[1]; + ASSERT_CMPINT (1, ==, mongoc_socket_recv (conn_sock, buf, sizeof buf, 0, expire_at)); + + prose_heartbeat_context_append_event (context, PROSE_HEARTBEAT_EVENT_CLIENT_HELLO_RECEIVED); + + mongoc_socket_destroy (conn_sock); + mongoc_socket_destroy (listen_sock); + + BSON_THREAD_RETURN; +} + +static void +prose_heartbeat_event_started (const mongoc_apm_server_heartbeat_started_t *event) +{ + prose_heartbeat_context_t *context = + (prose_heartbeat_context_t *) mongoc_apm_server_heartbeat_started_get_context (event); + prose_heartbeat_context_append_event (context, PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_STARTED); +} + +static void +prose_heartbeat_event_failed (const mongoc_apm_server_heartbeat_failed_t *event) +{ + prose_heartbeat_context_t *context = + (prose_heartbeat_context_t *) mongoc_apm_server_heartbeat_failed_get_context (event); + prose_heartbeat_context_append_event (context, PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_FAILED); +} + +static void +test_prose_heartbeat (void) +{ + bson_thread_t thread; + prose_heartbeat_context_t context = {.num_events = 0, .listen_port = 0}; + + bson_mutex_init (&context.mutex); + mongoc_cond_init (&context.cond); + + BSON_ASSERT (0 == mcommon_thread_create (&thread, prose_heartbeat_thread, &context)); + + bson_mutex_lock (&context.mutex); + uint16_t listen_port = context.listen_port; + while (!listen_port) { + mongoc_cond_wait (&context.cond, &context.mutex); + listen_port = context.listen_port; + } + bson_mutex_unlock (&context.mutex); + + MONGOC_INFO ("Mock server listening on port %d", listen_port); + + mongoc_client_t *client = + mongoc_client_new (tmp_str ("mongodb://127.0.0.1:%hu/?serverselectiontimeoutms=500", listen_port)); + BSON_ASSERT (client); + + mongoc_apm_callbacks_t *callbacks = mongoc_apm_callbacks_new (); + mongoc_apm_set_server_heartbeat_started_cb (callbacks, prose_heartbeat_event_started); + mongoc_apm_set_server_heartbeat_failed_cb (callbacks, prose_heartbeat_event_failed); + mongoc_client_set_apm_callbacks (client, callbacks, &context); + mongoc_apm_callbacks_destroy (callbacks); + + BSON_ASSERT (!mongoc_client_command_simple (client, "test", tmp_bson ("{'ping': 1}"), NULL, NULL, NULL)); + + mongoc_client_destroy (client); + mcommon_thread_join (thread); + mongoc_cond_destroy (&context.cond); + bson_mutex_destroy (&context.mutex); + + ASSERT_CMPSIZE_T (context.num_events, ==, 4); + ASSERT_CMPINT (context.events[0], ==, PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_STARTED); + ASSERT_CMPINT (context.events[1], ==, PROSE_HEARTBEAT_EVENT_CLIENT_CONNECTED); + ASSERT_CMPINT (context.events[2], ==, PROSE_HEARTBEAT_EVENT_CLIENT_HELLO_RECEIVED); + ASSERT_CMPINT (context.events[3], ==, PROSE_HEARTBEAT_EVENT_SERVER_HEARTBEAT_FAILED); +} + void test_sdam_install (TestSuite *suite) { @@ -876,4 +1008,5 @@ test_sdam_install (TestSuite *suite) NULL /* dtor */, NULL /* ctx */, test_framework_skip_if_max_wire_version_less_than_9); + TestSuite_Add (suite, "/server_discovery_and_monitoring/prose/heartbeat", test_prose_heartbeat); } diff --git a/src/libmongoc/tests/test-mongoc-server-stream.c b/src/libmongoc/tests/test-mongoc-server-stream.c index bc561eea599..c6d36640979 100644 --- a/src/libmongoc/tests/test-mongoc-server-stream.c +++ b/src/libmongoc/tests/test-mongoc-server-stream.c @@ -208,7 +208,8 @@ test_server_stream_ties_server_description_single (void *unused) /* Pass in a zeroed out error. */ memset (&error, 0, sizeof (bson_error_t)); tdmod = mc_tpld_modify_begin (client->topology); - mongoc_topology_description_handle_hello (tdmod.new_td, 1, tmp_bson (HELLO_SERVER_ONE), 0, &error); + mongoc_topology_description_handle_hello ( + tdmod.new_td, &client->topology->log_and_monitor, 1, tmp_bson (HELLO_SERVER_ONE), 0, &error); mc_tpld_modify_commit (tdmod); future = future_client_command_simple ( diff --git a/src/libmongoc/tests/test-mongoc-structured-log.c b/src/libmongoc/tests/test-mongoc-structured-log.c index 24c92fa9c1a..986241473fd 100644 --- a/src/libmongoc/tests/test-mongoc-structured-log.c +++ b/src/libmongoc/tests/test-mongoc-structured-log.c @@ -310,6 +310,9 @@ test_structured_log_json (void) void test_structured_log_oid (void) { + bson_oid_t oid; + bson_oid_init_from_string (&oid, "112233445566778899aabbcc"); + struct log_assumption assumption = { .expected_envelope.level = MONGOC_STRUCTURED_LOG_LEVEL_WARNING, .expected_envelope.component = MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, @@ -317,15 +320,16 @@ test_structured_log_oid (void) .expected_bson = BCON_NEW ("message", BCON_UTF8 ("Log entry with deferred OID-to-hex conversion"), "kOID", + BCON_OID (&oid), + "kNull1", + BCON_NULL, + "kOIDHex", BCON_UTF8 ("112233445566778899aabbcc"), - "kNull", + "kNull2", BCON_NULL), .expected_calls = 1, }; - bson_oid_t oid; - bson_oid_init_from_string (&oid, "112233445566778899aabbcc"); - mongoc_structured_log_opts_t *opts = mongoc_structured_log_opts_new (); mongoc_structured_log_opts_set_handler (opts, structured_log_func, &assumption); ASSERT (mongoc_structured_log_opts_set_max_document_length (opts, 10000)); @@ -338,8 +342,11 @@ test_structured_log_oid (void) MONGOC_STRUCTURED_LOG_LEVEL_WARNING, MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, "Log entry with deferred OID-to-hex conversion", - oid_as_hex ("kOID", &oid), - oid_as_hex ("kNull", NULL), + oid ("kOID", &oid), + oid ("kNull1", NULL), + oid (NULL, NULL), + oid_as_hex ("kOIDHex", &oid), + oid_as_hex ("kNull2", NULL), oid_as_hex (NULL, NULL)); mongoc_structured_log_instance_destroy (instance); diff --git a/src/libmongoc/tests/test-mongoc-topology-description.c b/src/libmongoc/tests/test-mongoc-topology-description.c index f5ea652321c..f8a38f102a6 100644 --- a/src/libmongoc/tests/test-mongoc-topology-description.c +++ b/src/libmongoc/tests/test-mongoc-topology-description.c @@ -120,14 +120,17 @@ test_get_servers (void) topology = mongoc_topology_new (uri, true /* single-threaded */); tdmod = mc_tpld_modify_begin (topology); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + /* servers "a" and "c" are mongos, but "b" remains unknown */ sd_a = _sd_for_host (tdmod.new_td, "a"); mongoc_topology_description_handle_hello ( - tdmod.new_td, sd_a->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); + tdmod.new_td, &log_and_monitor, sd_a->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); sd_c = _sd_for_host (tdmod.new_td, "c"); mongoc_topology_description_handle_hello ( - tdmod.new_td, sd_c->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); + tdmod.new_td, &log_and_monitor, sd_c->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); sds = mongoc_topology_description_get_servers (tdmod.new_td, &n); ASSERT_CMPSIZE_T ((size_t) 2, ==, n); @@ -145,6 +148,7 @@ test_get_servers (void) mc_tpld_modify_drop (tdmod); mongoc_topology_destroy (topology); mongoc_uri_destroy (uri); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } #define TV_1 "{ 'processId': { '$oid': 'AABBAABBAABBAABBAABBAABB' }, 'counter': 1 }" @@ -176,18 +180,26 @@ test_topology_version_equal (void) callbacks = mongoc_apm_callbacks_new (); mongoc_apm_set_topology_changed_cb (callbacks, _topology_changed); - mongoc_topology_set_apm_callbacks (topology, tdmod.new_td, callbacks, &num_calls); + mongoc_log_and_monitor_instance_set_apm_callbacks (&topology->log_and_monitor, callbacks, &num_calls); sd = _sd_for_host (tdmod.new_td, "host"); - mongoc_topology_description_handle_hello ( - tdmod.new_td, sd->id, tmp_bson ("{'ok': 1, 'topologyVersion': " TV_2 " }"), 100, NULL); + mongoc_topology_description_handle_hello (tdmod.new_td, + &topology->log_and_monitor, + sd->id, + tmp_bson ("{'ok': 1, 'topologyVersion': " TV_2 " }"), + 100, + NULL); ASSERT_CMPINT (num_calls, ==, 1); /* The subsequent hello has a topologyVersion that compares less, so the * hello skips. */ - mongoc_topology_description_handle_hello ( - tdmod.new_td, sd->id, tmp_bson ("{'ok': 1, 'topologyVersion': " TV_1 " }"), 100, NULL); + mongoc_topology_description_handle_hello (tdmod.new_td, + &topology->log_and_monitor, + sd->id, + tmp_bson ("{'ok': 1, 'topologyVersion': " TV_1 " }"), + 100, + NULL); ASSERT_CMPINT (num_calls, ==, 1); @@ -213,16 +225,19 @@ test_topology_description_new_copy (void) topology = mongoc_topology_new (uri, true /* single-threaded */); tdmod = mc_tpld_modify_begin (topology); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + td_copy = mongoc_topology_description_new_copy (tdmod.new_td); /* servers "a" and "c" are mongos, but "b" remains unknown */ sd_a = _sd_for_host (tdmod.new_td, "a"); mongoc_topology_description_handle_hello ( - tdmod.new_td, sd_a->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); + tdmod.new_td, &log_and_monitor, sd_a->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); sd_c = _sd_for_host (tdmod.new_td, "c"); mongoc_topology_description_handle_hello ( - tdmod.new_td, sd_c->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); + tdmod.new_td, &log_and_monitor, sd_c->id, tmp_bson ("{'ok': 1, 'msg': 'isdbgrid'}"), 100, NULL); /* td was copied before original was updated */ sds = mongoc_topology_description_get_servers (td_copy, &n); @@ -243,6 +258,7 @@ test_topology_description_new_copy (void) mongoc_server_descriptions_destroy_all (sds, n); mongoc_topology_description_destroy (td_copy); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } /* Test that _mongoc_topology_description_clear_connection_pool increments the diff --git a/src/libmongoc/tests/test-mongoc-topology-scanner.c b/src/libmongoc/tests/test-mongoc-topology-scanner.c index 64423043a5b..b5a30ec5c41 100644 --- a/src/libmongoc/tests/test-mongoc-topology-scanner.c +++ b/src/libmongoc/tests/test-mongoc-topology-scanner.c @@ -6,6 +6,7 @@ #include #include +#include "common-oid-private.h" #include "TestSuite.h" #include "mock_server/mock-server.h" @@ -49,7 +50,6 @@ static void _test_topology_scanner (bool with_ssl) { mock_server_t *servers[NSERVERS]; - mongoc_topology_scanner_t *topology_scanner; int i; bson_t q = BSON_INITIALIZER; int finished = NSERVERS * 3; @@ -59,7 +59,12 @@ _test_topology_scanner (bool with_ssl) mongoc_ssl_opt_t copt = {0}; #endif - topology_scanner = mongoc_topology_scanner_new (NULL, NULL, &test_topology_scanner_helper, &finished, TIMEOUT); + bson_oid_t topology_id; + mcommon_oid_set_zero (&topology_id); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + mongoc_topology_scanner_t *topology_scanner = mongoc_topology_scanner_new ( + NULL, &topology_id, &log_and_monitor, NULL, &test_topology_scanner_helper, &finished, TIMEOUT); #ifdef MONGOC_ENABLE_SSL if (with_ssl) { @@ -98,6 +103,7 @@ _test_topology_scanner (bool with_ssl) BSON_ASSERT (finished == 0); mongoc_topology_scanner_destroy (topology_scanner); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); bson_destroy (&q); @@ -463,8 +469,14 @@ test_topology_scanner_dns_testcase (dns_testcase_t *testcase) mongoc_socket_t *sock; mongoc_topology_scanner_node_t *node; + bson_oid_t topology_id; + mcommon_oid_set_zero (&topology_id); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + server = _mock_server_listening_on (testcase->server_bind_to); - ts = mongoc_topology_scanner_new (NULL, NULL, &_test_topology_scanner_dns_helper, testcase, TIMEOUT); + ts = mongoc_topology_scanner_new ( + NULL, &topology_id, &log_and_monitor, NULL, &_test_topology_scanner_dns_helper, testcase, TIMEOUT); host_str = bson_strdup_printf ("%s:%d", testcase->client_hostname, mock_server_get_port (server)); BSON_ASSERT (_mongoc_host_list_from_string (&host, host_str)); /* we should only have one host. */ @@ -493,6 +505,7 @@ test_topology_scanner_dns_testcase (dns_testcase_t *testcase) mongoc_topology_scanner_destroy (ts); mock_server_destroy (server); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } /* test when clients try connecting to servers varying the DNS results of the @@ -569,7 +582,13 @@ test_topology_retired_fails_to_initiate (void) server = mock_server_with_auto_hello (WIRE_VERSION_MAX); mock_server_run (server); - scanner = mongoc_topology_scanner_new (NULL, NULL, &_retired_fails_to_initiate_cb, NULL, TIMEOUT); + bson_oid_t topology_id; + mcommon_oid_set_zero (&topology_id); + mongoc_log_and_monitor_instance_t log_and_monitor; + mongoc_log_and_monitor_instance_init (&log_and_monitor); + + scanner = mongoc_topology_scanner_new ( + NULL, &topology_id, &log_and_monitor, NULL, &_retired_fails_to_initiate_cb, NULL, TIMEOUT); BSON_ASSERT (_mongoc_host_list_from_string (&host_list, mock_server_get_host_and_port (server))); @@ -590,6 +609,7 @@ test_topology_retired_fails_to_initiate (void) mongoc_topology_scanner_destroy (scanner); mock_server_destroy (server); + mongoc_log_and_monitor_instance_destroy_contents (&log_and_monitor); } static void diff --git a/src/libmongoc/tests/unified/entity-map.c b/src/libmongoc/tests/unified/entity-map.c index c15d50b8204..e12d25c384d 100644 --- a/src/libmongoc/tests/unified/entity-map.c +++ b/src/libmongoc/tests/unified/entity-map.c @@ -114,8 +114,10 @@ uri_apply_options (mongoc_uri_t *uri, bson_t *opts, bson_error_t *error) mongoc_uri_set_option_as_int64 (uri, key, bson_iter_int64 (&iter)); } else if (mongoc_uri_option_is_bool (key)) { mongoc_uri_set_option_as_bool (uri, key, bson_iter_bool (&iter)); - } else if (0 == bson_strcasecmp ("appname", key)) { + } else if (0 == bson_strcasecmp (MONGOC_URI_APPNAME, key)) { mongoc_uri_set_appname (uri, bson_iter_utf8 (&iter, NULL)); + } else if (0 == bson_strcasecmp (MONGOC_URI_SERVERMONITORINGMODE, key)) { + mongoc_uri_set_option_as_utf8 (uri, key, bson_iter_utf8 (&iter, NULL)); } else { test_set_error (error, "Unimplemented test runner support for URI option: %s", key); goto done; @@ -133,10 +135,14 @@ uri_apply_options (mongoc_uri_t *uri, bson_t *opts, bson_error_t *error) return ret; } +/* Consider refactoring the names, this is confusing. "type" has been the name of the specific event + * type. "eventType" is more like what's called the "component" in structured logging, but here it's + * named after the field in expectedEventsForClient. */ static event_t * -event_new (const char *type, bson_t *serialized, bool is_sensitive_command) +event_new (const char *type, const char *eventType, bson_t *serialized, bool is_sensitive_command) { BSON_ASSERT_PARAM (type); + BSON_ASSERT_PARAM (eventType); BSON_ASSERT_PARAM (serialized); const int64_t usecs = usecs_since_epoch (); @@ -146,13 +152,15 @@ event_new (const char *type, bson_t *serialized, bool is_sensitive_command) BSON_APPEND_UTF8 (serialized, "name", type); BSON_APPEND_DOUBLE (serialized, "observedAt", secs); - MONGOC_DEBUG ("new event: %s %s (%s)", + MONGOC_DEBUG ("new %s event: %s %s (%s)", + eventType, type, tmp_json (serialized), is_sensitive_command ? "marked SENSITIVE" : "not sensitive"); event_t *event = bson_malloc0 (sizeof *event); event->type = type; // Borrowed + event->eventType = eventType; // Borrowed event->serialized = serialized; // Takes ownership event->is_sensitive_command = is_sensitive_command; return event; @@ -169,6 +177,94 @@ event_destroy (event_t *event) bson_free (event); } +/** + * @brief Test whether a structured log entry is accepted by all active filters + * @returns true if all filters have returned true in response to this entry, or if no filters were active + * @param entity Client entity with the filter stack to query + * @param entry Borrowed constant reference to the log entry + * + * Filters will run in stack order, from most recently pushed to least. + * + * log_mutex must already be held. + */ +static bool +_entity_log_filter_accepts (const entity_t *entity, const mongoc_structured_log_entry_t *entry) +{ + for (log_filter_t *filter = entity->log_filters; filter; filter = filter->next) { + if (!filter->func || !filter->func (entry, filter->user_data)) { + return false; + } + } + return true; +} + +/** + * @brief Push a new structured log filter function onto the stack + * @param entity Client entity to modify the filter stack for + * @param func Filter function, returns true to accept a log or false to reject. May be NULL to reject all logs. + * @param user_data Optional user_data pointer, passed to 'func'. + * + * Must be paired with entity_log_filter_pop. + * + * Briefly acquires log_mutex. + */ +void +entity_log_filter_push (entity_t *entity, log_filter_func_t *func, void *user_data) +{ + BSON_ASSERT_PARAM (entity); + BSON_OPTIONAL_PARAM (func); + BSON_OPTIONAL_PARAM (user_data); + + log_filter_t *new_entry = bson_malloc0 (sizeof *new_entry); + bson_mutex_lock (&entity->log_mutex); + new_entry->next = entity->log_filters; + new_entry->func = func; + new_entry->user_data = user_data; + entity->log_filters = new_entry; + bson_mutex_unlock (&entity->log_mutex); +} + +/** + * @brief Pop the most recent structured log filter from the stack, which must match + * @param entity Client entity to modify the filter stack for + * @param func Filter function, must match the value given to entity_log_filter_push + * @param user_data Must match the corresponding user_data value from entity_log_filter_push + * + * Briefly acquires log_mutex. + */ +void +entity_log_filter_pop (entity_t *entity, log_filter_func_t *func, void *user_data) +{ + BSON_ASSERT_PARAM (entity); + BSON_OPTIONAL_PARAM (func); + BSON_OPTIONAL_PARAM (user_data); + + bson_mutex_lock (&entity->log_mutex); + log_filter_t *old_entry = entity->log_filters; + BSON_ASSERT (old_entry); + BSON_ASSERT (old_entry->func == func); + BSON_ASSERT (old_entry->user_data == user_data); + entity->log_filters = old_entry->next; + bson_mutex_unlock (&entity->log_mutex); + bson_free (old_entry); +} + +void +entity_map_log_filter_push (entity_map_t *entity_map, const char *entity_id, log_filter_func_t *func, void *user_data) +{ + entity_t *entity = entity_map_get (entity_map, entity_id, NULL); + BSON_ASSERT (entity); + entity_log_filter_push (entity, func, user_data); +} + +void +entity_map_log_filter_pop (entity_map_t *entity_map, const char *entity_id, log_filter_func_t *func, void *user_data) +{ + entity_t *entity = entity_map_get (entity_map, entity_id, NULL); + BSON_ASSERT (entity); + entity_log_filter_pop (entity, func, user_data); +} + static log_message_t * log_message_new (const mongoc_structured_log_entry_t *entry) { @@ -207,7 +303,7 @@ entity_new (entity_map_t *em, const char *type) entity->entity_map = em; _mongoc_array_init (&entity->observe_events, sizeof (observe_event_t)); _mongoc_array_init (&entity->store_events, sizeof (store_event_t)); - bson_mutex_init (&entity->log_messages_mutex); + bson_mutex_init (&entity->log_mutex); return entity; } @@ -216,12 +312,21 @@ structured_log_cb (const mongoc_structured_log_entry_t *entry, void *user_data) { BSON_ASSERT_PARAM (entry); BSON_ASSERT_PARAM (user_data); - if (!test_is_suppressing_structured_logs ()) { - entity_t *entity = (entity_t *) user_data; + entity_t *entity = (entity_t *) user_data; + + bson_mutex_lock (&entity->log_mutex); + if (_entity_log_filter_accepts (entity, entry)) { log_message_t *log_message = log_message_new (entry); - bson_mutex_lock (&entity->log_messages_mutex); LL_APPEND (entity->log_messages, log_message); - bson_mutex_unlock (&entity->log_messages_mutex); + bson_mutex_unlock (&entity->log_mutex); + } else { + bson_mutex_unlock (&entity->log_mutex); + bson_t *message_bson = mongoc_structured_log_entry_message_as_bson (entry); + MONGOC_DEBUG ("test IGNORED structured log: %s %s %s", + mongoc_structured_log_get_level_name (mongoc_structured_log_entry_get_level (entry)), + mongoc_structured_log_get_component_name (mongoc_structured_log_entry_get_component (entry)), + tmp_json (message_bson)); + bson_destroy (message_bson); } } @@ -326,7 +431,7 @@ command_started (const mongoc_apm_command_started_t *started) if (service_id, then (kv ("serviceId", oid (service_id)))), kv ("command", bson (*mongoc_apm_command_started_get_command (started)))); - event_store_or_destroy (entity, event_new ("commandStartedEvent", serialized, is_sensitive)); + event_store_or_destroy (entity, event_new ("commandStartedEvent", "command", serialized, is_sensitive)); } static void @@ -352,7 +457,7 @@ command_failed (const mongoc_apm_command_failed_t *failed) if (service_id, then (kv ("serviceId", oid (service_id)))), kv ("failure", cstr (error.message))); - event_store_or_destroy (entity, event_new ("commandFailedEvent", serialized, is_sensitive)); + event_store_or_destroy (entity, event_new ("commandFailedEvent", "command", serialized, is_sensitive)); } static void @@ -376,7 +481,7 @@ command_succeeded (const mongoc_apm_command_succeeded_t *succeeded) if (service_id, then (kv ("serviceId", oid (service_id)))), kv ("reply", bson (*mongoc_apm_command_succeeded_get_reply (succeeded)))); - event_store_or_destroy (entity, event_new ("commandSucceededEvent", serialized, is_sensitive)); + event_store_or_destroy (entity, event_new ("commandSucceededEvent", "command", serialized, is_sensitive)); } static void @@ -400,7 +505,7 @@ server_changed (const mongoc_apm_server_changed_t *changed) kv ("newDescription", doc (do ({ mongoc_server_description_append_contents_to_bson (new_sd, bsonBuildContext.doc, sd_flags); })))); - event_store_or_destroy (entity, event_new ("serverDescriptionChangedEvent", serialized, false)); + event_store_or_destroy (entity, event_new ("serverDescriptionChangedEvent", "sdam", serialized, false)); } static void @@ -427,9 +532,68 @@ topology_changed (const mongoc_apm_topology_changed_t *changed) new_td, bsonBuildContext.doc, td_flags, sd_flags); })))); - event_store_or_destroy (entity, event_new ("topologyDescriptionChangedEvent", serialized, false)); + event_store_or_destroy (entity, event_new ("topologyDescriptionChangedEvent", "sdam", serialized, false)); } +static void +topology_opening (const mongoc_apm_topology_opening_t *opening) +{ + entity_t *entity = (entity_t *) mongoc_apm_topology_opening_get_context (opening); + bson_oid_t topology_id; + mongoc_apm_topology_opening_get_topology_id (opening, &topology_id); + + bson_t *serialized = bson_new (); + bsonBuildAppend (*serialized, kv ("topologyId", oid (&topology_id))); + + event_store_or_destroy (entity, event_new ("topologyOpeningEvent", "sdam", serialized, false)); +} + +static void +topology_closed (const mongoc_apm_topology_closed_t *closed) +{ + entity_t *entity = (entity_t *) mongoc_apm_topology_closed_get_context (closed); + bson_oid_t topology_id; + mongoc_apm_topology_closed_get_topology_id (closed, &topology_id); + + bson_t *serialized = bson_new (); + bsonBuildAppend (*serialized, kv ("topologyId", oid (&topology_id))); + + event_store_or_destroy (entity, event_new ("topologyClosedEvent", "sdam", serialized, false)); +} + +static void +server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *started) +{ + entity_t *entity = (entity_t *) mongoc_apm_server_heartbeat_started_get_context (started); + bson_t *serialized = bson_new (); + + bsonBuildAppend (*serialized, kv ("awaited", boolean (mongoc_apm_server_heartbeat_started_get_awaited (started)))); + + event_store_or_destroy (entity, event_new ("serverHeartbeatStartedEvent", "sdam", serialized, false)); +} + +static void +server_heartbeat_succeeded (const mongoc_apm_server_heartbeat_succeeded_t *succeeded) +{ + entity_t *entity = (entity_t *) mongoc_apm_server_heartbeat_succeeded_get_context (succeeded); + bson_t *serialized = bson_new (); + + bsonBuildAppend (*serialized, + kv ("awaited", boolean (mongoc_apm_server_heartbeat_succeeded_get_awaited (succeeded)))); + + event_store_or_destroy (entity, event_new ("serverHeartbeatSucceededEvent", "sdam", serialized, false)); +} + +static void +server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *failed) +{ + entity_t *entity = (entity_t *) mongoc_apm_server_heartbeat_failed_get_context (failed); + bson_t *serialized = bson_new (); + + bsonBuildAppend (*serialized, kv ("awaited", boolean (mongoc_apm_server_heartbeat_failed_get_awaited (failed)))); + + event_store_or_destroy (entity, event_new ("serverHeartbeatFailedEvent", "sdam", serialized, false)); +} static void set_command_started_cb (mongoc_apm_callbacks_t *callbacks) @@ -461,6 +625,36 @@ set_topology_changed_cb (mongoc_apm_callbacks_t *callbacks) mongoc_apm_set_topology_changed_cb (callbacks, topology_changed); } +static void +set_topology_opening_cb (mongoc_apm_callbacks_t *callbacks) +{ + mongoc_apm_set_topology_opening_cb (callbacks, topology_opening); +} + +static void +set_topology_closed_cb (mongoc_apm_callbacks_t *callbacks) +{ + mongoc_apm_set_topology_closed_cb (callbacks, topology_closed); +} + +static void +set_server_heartbeat_started_cb (mongoc_apm_callbacks_t *callbacks) +{ + mongoc_apm_set_server_heartbeat_started_cb (callbacks, server_heartbeat_started); +} + +static void +set_server_heartbeat_succeeded_cb (mongoc_apm_callbacks_t *callbacks) +{ + mongoc_apm_set_server_heartbeat_succeeded_cb (callbacks, server_heartbeat_succeeded); +} + +static void +set_server_heartbeat_failed_cb (mongoc_apm_callbacks_t *callbacks) +{ + mongoc_apm_set_server_heartbeat_failed_cb (callbacks, server_heartbeat_failed); +} + /* Set a callback for the indicated event type in a mongoc_apm_callbacks_t. * Safe to call multiple times for the same event: callbacks for a specific * event type are always the same. Returns 'true' if the event is known and @@ -482,6 +676,11 @@ set_event_callback (mongoc_apm_callbacks_t *callbacks, const char *type) {.type = "commandSucceededEvent", .set = set_command_succeeded_cb}, {.type = "serverDescriptionChangedEvent", .set = set_server_changed_cb}, {.type = "topologyDescriptionChangedEvent", .set = set_topology_changed_cb}, + {.type = "topologyOpeningEvent", .set = set_topology_opening_cb}, + {.type = "topologyClosedEvent", .set = set_topology_closed_cb}, + {.type = "serverHeartbeatStartedEvent", .set = set_server_heartbeat_started_cb}, + {.type = "serverHeartbeatSucceededEvent", .set = set_server_heartbeat_succeeded_cb}, + {.type = "serverHeartbeatFailedEvent", .set = set_server_heartbeat_failed_cb}, {.type = NULL, .set = NULL}, }; @@ -1144,6 +1343,10 @@ entity_client_encryption_new (entity_map_t *entity_map, bson_t *bson, bson_error if (!client_entity) { goto ce_opts_done; } + if (!client_entity->value) { + test_set_error (error, "client '%s' is closed", client_id); + goto ce_opts_done; + } BSON_ASSERT ((client = (mongoc_client_t *) client_entity->value)); @@ -1279,6 +1482,10 @@ entity_database_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error if (!client_entity) { goto done; } + if (!client_entity) { + test_set_error (error, "client '%s' is closed", client_id); + goto done; + } client = (mongoc_client_t *) client_entity->value; db = mongoc_client_get_database (client, database_name); @@ -1471,6 +1678,7 @@ entity_session_new (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) } client = (mongoc_client_t *) client_entity->value; if (!client) { + test_set_error (error, "client '%s' is closed", client_id); goto done; } if (session_opts_bson) { @@ -1639,6 +1847,40 @@ entity_map_create (entity_map_t *entity_map, bson_t *bson, bson_error_t *error) return ret; } +static bool +entity_close (entity_t *entity, bson_error_t *error) +{ + BSON_ASSERT_PARAM (entity); + + /* Note that the unified test spec says tests SHOULD avoid using entities + * after close, but the SDAM tests do require access to clients after close + * for good reason: to check the log messages emitted over a full client + * life cycle. + * + * For the entity types that require 'close' support, the closed state is + * represented in this driver by value == NULL. */ + + if (0 == strcmp ("client", entity->type)) { + mongoc_client_t *client = (mongoc_client_t *) entity->value; + mongoc_client_destroy (client); + } else if (0 == strcmp ("changestream", entity->type)) { + mongoc_change_stream_t *changestream = (mongoc_change_stream_t *) entity->value; + mongoc_change_stream_destroy (changestream); + } else if (0 == strcmp ("findcursor", entity->type)) { + entity_findcursor_t *findcursor = (entity_findcursor_t *) entity->value; + if (findcursor) { + mongoc_cursor_destroy (findcursor->cursor); + bson_free (findcursor); + } + } else { + test_set_error (error, "Attempting to close unsupported entity type: %s, id: %s", entity->type, entity->id); + return false; + } + + entity->value = NULL; + return true; +} + static void entity_destroy (entity_t *entity) { @@ -1650,49 +1892,33 @@ entity_destroy (entity_t *entity) BSON_ASSERT (entity->type); - if (0 == strcmp ("client", entity->type)) { - mongoc_client_t *client = NULL; + // Note that entities which can be 'close'd chain their destructors via close, + // to avoid proliferating duplicates of the per-type finalization steps. - client = (mongoc_client_t *) entity->value; - mongoc_client_destroy (client); + if (0 == strcmp ("client", entity->type)) { + BSON_ASSERT (entity_close (entity, NULL)); } else if (0 == strcmp ("clientEncryption", entity->type)) { - mongoc_client_encryption_t *ce = NULL; - - ce = (mongoc_client_encryption_t *) entity->value; + mongoc_client_encryption_t *ce = (mongoc_client_encryption_t *) entity->value; mongoc_client_encryption_destroy (ce); } else if (0 == strcmp ("database", entity->type)) { - mongoc_database_t *db = NULL; - - db = (mongoc_database_t *) entity->value; + mongoc_database_t *db = (mongoc_database_t *) entity->value; mongoc_database_destroy (db); } else if (0 == strcmp ("collection", entity->type)) { - mongoc_collection_t *coll = NULL; - - coll = (mongoc_collection_t *) entity->value; + mongoc_collection_t *coll = (mongoc_collection_t *) entity->value; mongoc_collection_destroy (coll); } else if (0 == strcmp ("session", entity->type)) { - mongoc_client_session_t *sess = NULL; - - sess = (mongoc_client_session_t *) entity->value; + mongoc_client_session_t *sess = (mongoc_client_session_t *) entity->value; mongoc_client_session_destroy (sess); } else if (0 == strcmp ("changestream", entity->type)) { - mongoc_change_stream_t *changestream = NULL; - - changestream = (mongoc_change_stream_t *) entity->value; - mongoc_change_stream_destroy (changestream); + BSON_ASSERT (entity_close (entity, NULL)); } else if (0 == strcmp ("bson", entity->type)) { bson_val_t *value = entity->value; - bson_val_destroy (value); } else if (0 == strcmp ("bucket", entity->type)) { mongoc_gridfs_bucket_t *bucket = entity->value; - mongoc_gridfs_bucket_destroy (bucket); } else if (0 == strcmp ("findcursor", entity->type)) { - entity_findcursor_t *findcursor = entity->value; - - mongoc_cursor_destroy (findcursor->cursor); - bson_free (findcursor); + BSON_ASSERT (entity_close (entity, NULL)); } else if (0 == strcmp ("bson_array", entity->type)) { mongoc_array_t *array = entity->value; @@ -1706,8 +1932,10 @@ entity_destroy (entity_t *entity) bson_free (array); } else if (0 == strcmp ("size_t", entity->type)) { size_t *v = entity->value; - bson_free (v); + } else if (0 == strcmp ("topologyDescription", entity->type)) { + mongoc_topology_description_t *td = (mongoc_topology_description_t *) entity->value; + mongoc_topology_description_destroy (td); } else { test_error ("Attempting to destroy unrecognized entity type: %s, id: %s", entity->type, entity->id); } @@ -1746,7 +1974,8 @@ entity_destroy (entity_t *entity) _mongoc_array_destroy (&entity->store_events); } - bson_mutex_destroy (&entity->log_messages_mutex); + BSON_ASSERT (NULL == entity->log_filters); + bson_mutex_destroy (&entity->log_mutex); bson_destroy (entity->ignore_command_monitoring_events); bson_free (entity->type); bson_free (entity->id); @@ -1772,17 +2001,14 @@ entity_map_get (entity_map_t *entity_map, const char *id, bson_error_t *error) } bool -entity_map_delete (entity_map_t *em, const char *id, bson_error_t *error) +entity_map_close (entity_map_t *em, const char *id, bson_error_t *error) { entity_t *entity = entity_map_get (em, id, error); if (!entity) { return false; } - LL_DELETE (em->entities, entity); - entity_destroy (entity); - - return true; + return entity_close (entity, error); } static entity_t * @@ -1809,6 +2035,9 @@ entity_map_get_client (entity_map_t *entity_map, const char *id, bson_error_t *e if (!entity) { return NULL; } + if (!entity->value) { + test_set_error (error, "client '%s' is closed", id); + } return (mongoc_client_t *) entity->value; } @@ -1849,6 +2078,9 @@ entity_map_get_changestream (entity_map_t *entity_map, const char *id, bson_erro if (!entity) { return NULL; } + if (!entity->value) { + test_set_error (error, "changestream '%s' is closed", id); + } return (mongoc_change_stream_t *) entity->value; } @@ -1859,9 +2091,23 @@ entity_map_get_findcursor (entity_map_t *entity_map, const char *id, bson_error_ if (!entity) { return NULL; } + if (!entity->value) { + test_set_error (error, "findcursor '%s' is closed", id); + } return (entity_findcursor_t *) entity->value; } +mongoc_topology_description_t * +entity_map_get_topology_description (entity_map_t *entity_map, const char *id, bson_error_t *error) +{ + entity_t *entity = _entity_map_get_by_type (entity_map, id, "topologyDescription", error); + if (!entity) { + return NULL; + } + BSON_ASSERT (entity->value); + return (mongoc_topology_description_t *) entity->value; +} + bson_val_t * entity_map_get_bson (entity_map_t *entity_map, const char *id, bson_error_t *error) { @@ -1992,6 +2238,15 @@ entity_map_add_findcursor ( return _entity_map_add (em, id, "findcursor", (void *) findcursor, error); } +bool +entity_map_add_topology_description (entity_map_t *em, + const char *id, + mongoc_topology_description_t *td, + bson_error_t *error) +{ + return _entity_map_add (em, id, "topologyDescription", (void *) td, error); +} + bool entity_map_add_bson (entity_map_t *em, const char *id, bson_val_t *val, bson_error_t *error) { @@ -2188,8 +2443,9 @@ entity_map_disable_event_listeners (entity_map_t *em) { if (0 == strcmp (eiter->type, "client")) { mongoc_client_t *client = (mongoc_client_t *) eiter->value; - - mongoc_client_set_apm_callbacks (client, NULL, NULL); + if (client) { + mongoc_client_set_apm_callbacks (client, NULL, NULL); + } } } } diff --git a/src/libmongoc/tests/unified/entity-map.h b/src/libmongoc/tests/unified/entity-map.h index 2dd9bdc8f33..f01bc1b6904 100644 --- a/src/libmongoc/tests/unified/entity-map.h +++ b/src/libmongoc/tests/unified/entity-map.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include "bsonutil/bson-match.h" @@ -26,11 +27,14 @@ typedef struct _event_t { struct _event_t *next; - const char *type; // Non-owning + const char *type; // Non-owning + const char *eventType; // Non-owning bson_t *serialized; bool is_sensitive_command; } event_t; +typedef bool (log_filter_func_t) (const mongoc_structured_log_entry_t *entry, void *user_data); + typedef struct _log_message_t { struct _log_message_t *next; mongoc_structured_log_component_t component; @@ -38,6 +42,12 @@ typedef struct _log_message_t { bson_t *message; } log_message_t; +typedef struct _log_filter_t { + struct _log_filter_t *next; + log_filter_func_t *func; + void *user_data; +} log_filter_t; + typedef struct _observe_event_t { char *type; // Type of event to observe. } observe_event_t; @@ -55,8 +65,9 @@ typedef struct _entity_t { bool *observe_sensitive_commands; struct _entity_t *next; event_t *events; - bson_mutex_t log_messages_mutex; + bson_mutex_t log_mutex; log_message_t *log_messages; + log_filter_t *log_filters; struct _entity_map_t *entity_map; // Parent entity map. mongoc_array_t observe_events; // observe_event_t [N]. mongoc_array_t store_events; // store_event_t [N]. @@ -99,6 +110,13 @@ bool entity_map_add_findcursor ( entity_map_t *em, const char *id, mongoc_cursor_t *cursor, const bson_t *first_result, bson_error_t *error); +/* Steals ownership of td. */ +bool +entity_map_add_topology_description (entity_map_t *em, + const char *id, + mongoc_topology_description_t *td, + bson_error_t *error); + /* Copies val */ bool entity_map_add_bson (entity_map_t *em, const char *id, bson_val_t *val, bson_error_t *error); @@ -114,10 +132,11 @@ entity_map_add_size_t (entity_map_t *em, const char *id, size_t *value, bson_err entity_t * entity_map_get (entity_map_t *em, const char *id, bson_error_t *error); -/* Removes an entity from the entity map. Returns false and sets @error if @id - * does not map to an entry. */ +/* Implements the 'close' operation. Doesn't fully remove the entity. + * Returns false and sets @error if @id does not map to an entry, or + * if the entity type does not support 'close' operations. */ bool -entity_map_delete (entity_map_t *em, const char *id, bson_error_t *error); +entity_map_close (entity_map_t *em, const char *id, bson_error_t *error); mongoc_client_t * entity_map_get_client (entity_map_t *entity_map, const char *id, bson_error_t *error); @@ -137,6 +156,9 @@ entity_map_get_changestream (entity_map_t *entity_map, const char *id, bson_erro entity_findcursor_t * entity_map_get_findcursor (entity_map_t *entity_map, const char *id, bson_error_t *error); +mongoc_topology_description_t * +entity_map_get_topology_description (entity_map_t *entity_map, const char *id, bson_error_t *error); + void entity_findcursor_iterate_until_document_or_error (entity_findcursor_t *cursor, const bson_t **document, @@ -176,4 +198,18 @@ entity_map_set_reduced_heartbeat (entity_map_t *em, bool val); void entity_map_disable_event_listeners (entity_map_t *em); + +void +entity_log_filter_push (entity_t *entity, log_filter_func_t *func, void *user_data); + +void +entity_log_filter_pop (entity_t *entity, log_filter_func_t *func, void *user_data); + +void +entity_map_log_filter_push (entity_map_t *entity_map, const char *entity_id, log_filter_func_t *func, void *user_data); + +void +entity_map_log_filter_pop (entity_map_t *entity_map, const char *entity_id, log_filter_func_t *func, void *user_data); + + #endif /* UNIFIED_ENTITY_MAP_H */ diff --git a/src/libmongoc/tests/unified/operation.c b/src/libmongoc/tests/unified/operation.c index a2d533eab1d..b46a48570cd 100644 --- a/src/libmongoc/tests/unified/operation.c +++ b/src/libmongoc/tests/unified/operation.c @@ -105,6 +105,10 @@ operation_create_change_stream (test_t *test, operation_t *op, result_t *result, if (0 == strcmp (entity->type, "client")) { mongoc_client_t *client = (mongoc_client_t *) entity->value; + if (!client) { + test_set_error (error, "client '%s' is closed", entity->id); + goto done; + } changestream = mongoc_client_watch (client, pipeline, opts); } else if (0 == strcmp (entity->type, "database")) { mongoc_database_t *db = (mongoc_database_t *) entity->value; @@ -1304,10 +1308,12 @@ operation_run_command (test_t *test, operation_t *op, result_t *result, bson_err mongoc_write_concern_append (wc, opts); } - bson_destroy (&op_reply); mongoc_database_command_with_opts (db, command, rp, opts, &op_reply, &op_error); - result_from_val_and_reply (result, NULL, &op_reply, &op_error); + // For a generic command, the reply is also the result value + bson_val_t *op_reply_val = bson_val_from_bson (&op_reply); + result_from_val_and_reply (result, op_reply_val, &op_reply, &op_error); + bson_val_destroy (op_reply_val); ret = true; done: @@ -2432,13 +2438,10 @@ operation_close (test_t *test, operation_t *op, result_t *result, bson_error_t * goto done; } - if (0 != strcmp (entity->type, "findcursor") && 0 != strcmp (entity->type, "changestream")) { - test_set_error (error, "attempting to close an unsupported entity: %s", entity->type); + if (!entity_map_close (test->entity_map, op->object, error)) { goto done; } - entity_map_delete (test->entity_map, op->object, error); - result_from_ok (result); ret = true; @@ -2514,9 +2517,9 @@ operation_failpoint (test_t *test, operation_t *op, result_t *result, bson_error rp = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); bson_destroy (&op_reply); - test_begin_suppressing_structured_logs (); + entity_map_log_filter_push (test->entity_map, client_id, NULL, NULL); mongoc_client_command_simple (client, "admin", failpoint, rp, &op_reply, &op_error); - test_end_suppressing_structured_logs (); + entity_map_log_filter_pop (test->entity_map, client_id, NULL, NULL); result_from_val_and_reply (result, NULL /* value */, &op_reply, &op_error); /* Add failpoint to list of test_t's known failpoints */ @@ -2574,9 +2577,9 @@ operation_targeted_failpoint (test_t *test, operation_t *op, result_t *result, b rp = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); bson_destroy (&op_reply); - test_begin_suppressing_structured_logs (); + entity_map_log_filter_push (test->entity_map, client_id, NULL, NULL); mongoc_client_command_simple_with_server_id (client, "admin", failpoint, rp, server_id, &op_reply, &op_error); - test_end_suppressing_structured_logs (); + entity_map_log_filter_pop (test->entity_map, client_id, NULL, NULL); result_from_val_and_reply (result, NULL /* value */, &op_reply, &op_error); /* Add failpoint to list of test_t's known failpoints */ @@ -3847,6 +3850,60 @@ operation_create_entities (test_t *test, operation_t *op, result_t *result, bson #define WAIT_FOR_EVENT_TIMEOUT_MS (10 * 1000) // Specified by test runner spec #define WAIT_FOR_EVENT_TICK_MS 10 // Same tick size as used in non-unified json test +static bool +log_filter_hide_server_selection_operation (const mongoc_structured_log_entry_t *entry, void *user_data) +{ + BSON_ASSERT_PARAM (entry); + BSON_ASSERT_PARAM (user_data); + const char *expected_operation = (const char *) user_data; + + if (mongoc_structured_log_entry_get_component (entry) == MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION) { + bson_t *bson = mongoc_structured_log_entry_message_as_bson (entry); + bson_iter_t iter; + BSON_ASSERT (bson_iter_init_find (&iter, bson, "operation")); + BSON_ASSERT (BSON_ITER_HOLDS_UTF8 (&iter)); + BSON_ASSERT (0 == strcmp (expected_operation, bson_iter_utf8 (&iter, NULL))); + bson_destroy (bson); + return false; + } + return true; +} + +static void +_operation_hidden_wait (test_t *test, entity_t *client, const char *name) +{ + _mongoc_usleep (WAIT_FOR_EVENT_TICK_MS * 1000); + + // @todo Re-examine this once we have support for connection pools in the unified test + // runner. Without pooling, all events we could be waiting on would be coming + // from single-threaded (blocking) topology scans, or from lazily opening the topology + // description when it's first used. Request stream selection after blocking, to + // handle either of these cases. + // + // Structured logs can not be fully suppressed here, because we do need to emit topology + // lifecycle events. Filter out only the server selection operation here, and ASSERT + // that it's the waitForEvent we expect. + + entity_log_filter_push (client, log_filter_hide_server_selection_operation, (void *) name); + + mongoc_client_t *mc_client = entity_map_get_client (test->entity_map, client->id, NULL); + if (mc_client) { + const mongoc_ss_log_context_t ss_log_context = {.operation = name}; + mongoc_server_stream_t *stream = mongoc_cluster_stream_for_reads (&mc_client->cluster, + &ss_log_context, + NULL /* read_prefs */, + NULL /* client session */, + NULL /* deprioritized servers */, + NULL /* reply */, + NULL /* error */); + if (stream) { + mongoc_server_stream_cleanup (stream); + } + } + + entity_log_filter_pop (client, log_filter_hide_server_selection_operation, (void *) name); +} + static bool operation_wait_for_event (test_t *test, operation_t *op, result_t *result, bson_error_t *error) { @@ -3875,7 +3932,7 @@ operation_wait_for_event (test_t *test, operation_t *op, result_t *result, bson_ bson_iter_next (&iter); const char *expected_event_type = bson_iter_key (&iter); if (is_unsupported_event_type (expected_event_type)) { - MONGOC_DEBUG ("Skipping wait for unsupported event type '%s'", expected_event_type); + MONGOC_DEBUG ("SKIPPING waitForEvent for unsupported event type '%s'", expected_event_type); result_from_ok (result); ret = true; goto done; @@ -3906,23 +3963,240 @@ operation_wait_for_event (test_t *test, operation_t *op, result_t *result, bson_ goto done; }; - _mongoc_usleep (WAIT_FOR_EVENT_TICK_MS * 1000); + _operation_hidden_wait (test, client, "waitForEvent"); + } - // @todo Re-examine this once we have support for connection pools in the unified test - // runner. Without pooling, all events we could be waiting on would be coming - // from single-threaded (blocking) topology scans, or from lazily opening the topology - // description when it's first used. Request server selection after blocking, to - // handle either of these cases. - { - mongoc_client_t *mc_client = entity_map_get_client (test->entity_map, client_id, error); - if (mc_client) { - const mongoc_ss_log_context_t ss_log_context = {.operation = "waitForEvent"}; - test_begin_suppressing_structured_logs (); - mongoc_topology_select_server_id ( - mc_client->topology, MONGOC_SS_READ, &ss_log_context, NULL, NULL, NULL, error); - test_end_suppressing_structured_logs (); - } + result_from_ok (result); + ret = true; +done: + bson_parser_destroy_with_parsed_fields (bp); + return ret; +} + +/* Test for an event match document containing an unsupported event type as defined by is_unsupported_event_type(). If + * the match document has an unexpected format, returns false. */ +static bool +is_unsupported_event_match_document (const bson_t *event_match) +{ + BSON_ASSERT_PARAM (event_match); + + if (bson_count_keys (event_match) == 1) { + bson_iter_t iter; + bson_iter_init (&iter, event_match); + bson_iter_next (&iter); + return is_unsupported_event_type (bson_iter_key (&iter)); + } else { + return false; + } +} + +static bool +operation_assert_event_count (test_t *test, operation_t *op, result_t *result, bson_error_t *error) +{ + bool ret = false; + + bson_parser_t *bp = bson_parser_new (); + char *client_id; + bson_t *expected_event; + int64_t *expected_count; + bson_parser_utf8 (bp, "client", &client_id); + bson_parser_doc (bp, "event", &expected_event); + bson_parser_int (bp, "count", &expected_count); + if (!bson_parser_parse (bp, op->arguments, error)) { + goto done; + } + + if (is_unsupported_event_match_document (expected_event)) { + MONGOC_DEBUG ("SKIPPING assertEventCount for unsupported event %s", tmp_json (expected_event)); + result_from_ok (result); + ret = true; + goto done; + } + + entity_t *client = entity_map_get (test->entity_map, client_id, error); + if (!client) { + goto done; + } + + int64_t actual_count; + if (!test_count_matching_events_for_client (test, client, expected_event, error, &actual_count)) { + goto done; + } + if (actual_count != *expected_count) { + char *event_list_string = event_list_to_string (client->events); + test_diagnostics_error_info ("all captured events for client:\n%s", event_list_string); + bson_free (event_list_string); + test_diagnostics_error_info ("checking for expected event: %s\n", tmp_json (expected_event)); + test_set_error (error, + "assertEventCount found %" PRId64 " matches, required exactly %" PRId64 " matches", + actual_count, + *expected_count); + goto done; + } + + result_from_ok (result); + ret = true; +done: + bson_parser_destroy_with_parsed_fields (bp); + return ret; +} + +static const char * +tmp_topology_description_json (const mongoc_topology_description_t *td) +{ + bson_t bson = BSON_INITIALIZER; + BSON_ASSERT (mongoc_topology_description_append_contents_to_bson ( + td, + &bson, + MONGOC_TOPOLOGY_DESCRIPTION_CONTENT_FLAG_TYPE | MONGOC_TOPOLOGY_DESCRIPTION_CONTENT_FLAG_SERVERS, + MONGOC_SERVER_DESCRIPTION_CONTENT_FLAG_ADDRESS | MONGOC_SERVER_DESCRIPTION_CONTENT_FLAG_TYPE)); + const char *result = tmp_json (&bson); + bson_destroy (&bson); + return result; +} + +static bool +operation_record_topology_description (test_t *test, operation_t *op, result_t *result, bson_error_t *error) +{ + bool ret = false; + + bson_parser_t *bp = bson_parser_new (); + char *client_id, *td_id; + bson_parser_utf8 (bp, "client", &client_id); + bson_parser_utf8 (bp, "id", &td_id); + if (!bson_parser_parse (bp, op->arguments, error)) { + goto done; + } + + mongoc_client_t *client = entity_map_get_client (test->entity_map, client_id, error); + if (!client) { + goto done; + } + + mongoc_topology_description_t *td_copy = bson_malloc0 (sizeof *td_copy); + mc_shared_tpld td = mc_tpld_take_ref (client->topology); + _mongoc_topology_description_copy_to (td.ptr, td_copy); + mc_tpld_drop_ref (&td); + + MONGOC_DEBUG ("Recording topology description '%s': %s", td_id, tmp_topology_description_json (td_copy)); + + if (!entity_map_add_topology_description (test->entity_map, td_id, td_copy, error)) { + mongoc_topology_description_destroy (td_copy); + goto done; + } + + result_from_ok (result); + ret = true; +done: + bson_parser_destroy_with_parsed_fields (bp); + return ret; +} + +static bool +operation_assert_topology_type (test_t *test, operation_t *op, result_t *result, bson_error_t *error) +{ + bool ret = false; + + bson_parser_t *bp = bson_parser_new (); + char *td_id, *expected_topology_type; + bson_parser_utf8 (bp, "topologyDescription", &td_id); + bson_parser_utf8 (bp, "topologyType", &expected_topology_type); + if (!bson_parser_parse (bp, op->arguments, error)) { + goto done; + } + + // Pointer borrowed from entity + mongoc_topology_description_t *td = entity_map_get_topology_description (test->entity_map, td_id, error); + if (!td) { + goto done; + } + + // Static lifetime + const char *actual_topology_type = mongoc_topology_description_type (td); + + if (0 != strcmp (expected_topology_type, actual_topology_type)) { + test_set_error (error, + "assertTopologyType failed, expected '%s' but found type '%s' in topology description: %s", + expected_topology_type, + actual_topology_type, + tmp_topology_description_json (td)); + goto done; + } + + result_from_ok (result); + ret = true; +done: + bson_parser_destroy_with_parsed_fields (bp); + return ret; +} + +static bool +operation_wait_for_primary_change (test_t *test, operation_t *op, result_t *result, bson_error_t *error) +{ + bool ret = false; + + bson_parser_t *bp = bson_parser_new (); + char *client_id, *prior_td_id; + int64_t *optional_timeout_ms = NULL; + bson_parser_utf8 (bp, "client", &client_id); + bson_parser_utf8 (bp, "priorTopologyDescription", &prior_td_id); + bson_parser_int_optional (bp, "timeoutMS", &optional_timeout_ms); + if (!bson_parser_parse (bp, op->arguments, error)) { + goto done; + } + + int64_t timeout = INT64_C (1000) * (optional_timeout_ms ? *optional_timeout_ms : INT64_C (10000)); + int64_t start_time = bson_get_monotonic_time (); + + mongoc_client_t *mc_client = entity_map_get_client (test->entity_map, client_id, error); + if (!mc_client) { + goto done; + } + + entity_t *client = entity_map_get (test->entity_map, client_id, error); + BSON_ASSERT (client); + + // Pointer borrowed from entity + mongoc_topology_description_t *prior_td = entity_map_get_topology_description (test->entity_map, prior_td_id, error); + if (!prior_td) { + goto done; + } + + // Will be NULL when there's no primary + const mongoc_server_description_t *prior_primary = _mongoc_topology_description_has_primary (prior_td); + + while (true) { + mc_shared_tpld td = mc_tpld_take_ref (mc_client->topology); + const mongoc_server_description_t *primary = _mongoc_topology_description_has_primary (td.ptr); + + if (!prior_primary && primary) { + MONGOC_DEBUG ("waitForPrimaryChange succeeded by transitioning from none to any"); + mc_tpld_drop_ref (&td); + break; + } + + if (prior_primary && primary && !_mongoc_server_description_equal (prior_primary, primary)) { + MONGOC_DEBUG ("waitForPrimaryChange succeeded by switching to a different primary server"); + mc_tpld_drop_ref (&td); + break; + } + + int64_t duration = bson_get_monotonic_time () - start_time; + if (duration >= timeout) { + test_set_error (error, + "waitForPrimaryChange timed out. waited %fms (max %fms). \nprior topology description: " + "%s\ncurrent topology description: %s", + duration / 1000.0, + timeout / 1000.0, + tmp_topology_description_json (prior_td), + tmp_topology_description_json (td.ptr)); + + mc_tpld_drop_ref (&td); + goto done; } + mc_tpld_drop_ref (&td); + + _operation_hidden_wait (test, client, "waitForPrimaryChange"); } result_from_ok (result); @@ -3950,7 +4224,6 @@ operation_run (test_t *test, bson_t *op_bson, bson_error_t *error) {"listDatabases", operation_list_databases}, {"listDatabaseNames", operation_list_database_names}, {"clientBulkWrite", operation_client_bulkwrite}, - {"waitForEvent", operation_wait_for_event}, /* ClientEncryption operations */ {"createDataKey", operation_create_datakey}, @@ -4021,6 +4294,11 @@ operation_run (test_t *test, bson_t *op_bson, bson_error_t *error) {"loop", operation_loop}, {"assertNumberConnectionsCheckedOut", operation_assert_number_connections_checked_out}, {"wait", operation_wait}, + {"waitForEvent", operation_wait_for_event}, + {"assertEventCount", operation_assert_event_count}, + {"recordTopologyDescription", operation_record_topology_description}, + {"assertTopologyType", operation_assert_topology_type}, + {"waitForPrimaryChange", operation_wait_for_primary_change}, /* GridFS operations */ {"delete", operation_delete}, diff --git a/src/libmongoc/tests/unified/runner.c b/src/libmongoc/tests/unified/runner.c index 9c97c70ae1c..7f49d8b4ec1 100644 --- a/src/libmongoc/tests/unified/runner.c +++ b/src/libmongoc/tests/unified/runner.c @@ -39,30 +39,78 @@ typedef struct { skipped_unified_test_t SKIPPED_TESTS[] = { // CDRIVER-4001, DRIVERS-1781, and DRIVERS-1448: 5.0 cursor behavior {"poc-command-monitoring", "A successful find event with a getmore and the server kills the cursor"}, + // libmongoc does not have a distinct helper, so skip snapshot tests testing particular distinct functionality {"snapshot-sessions", "Distinct operation with snapshot"}, {"snapshot-sessions", "Mixed operation with snapshot"}, + // CDRIVER-3886: serverless testing (schema version 1.4) {"poc-crud", SKIP_ALL_TESTS}, {"db-aggregate", SKIP_ALL_TESTS}, {"mongos-unpin", SKIP_ALL_TESTS}, + // CDRIVER-2871: CMAP is not implemented {"assertNumberConnectionsCheckedOut", SKIP_ALL_TESTS}, {"entity-client-cmap-events", SKIP_ALL_TESTS}, {"expectedEventsForClient-eventType", SKIP_ALL_TESTS}, {"driver-connection-id", SKIP_ALL_TESTS}, + {"minPoolSize-error", SKIP_ALL_TESTS}, + {"pool-cleared-on-min-pool-size-population-error", SKIP_ALL_TESTS}, + {"insert-shutdown-error", SKIP_ALL_TESTS}, + {"standalone-logging", "Successful heartbeat"}, // requires driverConnectionId + {"standalone-logging", "Failing heartbeat"}, // requires driverConnectionId + {"replicaset-logging", SKIP_ALL_TESTS }, // requires driverConnectionId + {"sharded-logging", SKIP_ALL_TESTS }, // requires driverConnectionId + {"find-network-error", "Reset server and pool after network error on find"}, + {"insert-network-error", "Reset server and pool after network error on insert"}, + {"pool-clear-on-error-checkout", SKIP_ALL_TESTS}, + {"find-shutdown-error", "Concurrent shutdown error on find"}, + {"find-network-timeout-error", "Ignore network timeout error on find"}, + {"hello-timeout", SKIP_ALL_TESTS}, + {"hello-network-error", SKIP_ALL_TESTS}, + {"hello-command-error", SKIP_ALL_TESTS}, + {"interruptInUse", SKIP_ALL_TESTS}, + {"pool-clear-min-pool-size-error", SKIP_ALL_TESTS}, + {"pool-clear-checkout-error", SKIP_ALL_TESTS}, + {"pool-clear-application-error", SKIP_ALL_TESTS}, + {"pool-cleared-error", "PoolClearedError does not mark server unknown"}, // requires multithreaded runner + + // Requires streaming heartbeat support + {"rediscover-quickly-after-step-down", SKIP_ALL_TESTS}, + + // CDRIVER-5870: Spec compliant response to authentication errors + {"auth-error", "Reset server and pool after AuthenticationFailure error"}, + {"auth-network-error", "Reset server and pool after network error during authentication"}, + {"auth-misc-command-error", "Reset server and pool after misc command error"}, + {"auth-shutdown-error", "Reset server and pool after shutdown error during authentication"}, + {"auth-network-timeout-error", "Reset server and pool after network timeout error during authentication"}, + + // libmongoc unified tests do not support pooled connections or background server monitoring threads yet + {"serverMonitoringMode", SKIP_ALL_TESTS}, + // CDRIVER-4115: listCollections does not support batchSize. {"cursors are correctly pinned to connections for load-balanced clusters", "listCollections pins the cursor to a connection"}, + // CDRIVER-4116: listIndexes does not support batchSize. {"cursors are correctly pinned to connections for load-balanced clusters", "listIndexes pins the cursor to a connection"}, + // libmongoc does not pin connections to cursors. It cannot force an error from waitQueueTimeoutMS by creating cursors in load balanced mode. {"wait queue timeout errors include details about checked out connections", SKIP_ALL_TESTS}, + // libmongoc does not support the optional findOne helper. {"retryable reads handshake failures", "collection.findOne succeeds after retryable handshake network error"}, {"retryable reads handshake failures", "collection.findOne succeeds after retryable handshake server error (ShutdownInProgress)"}, + // libmongoc does not support the optional listIndexNames helper. {"retryable reads handshake failures", "collection.listIndexNames succeeds after retryable handshake network error"}, {"retryable reads handshake failures", "collection.listIndexNames succeeds after retryable handshake server error (ShutdownInProgress)"}, + + // libmongoc single-host non-replicaSet URI first transitions Unknown->Single, not Unknown->Unknown + {"standalone-emit-topology-description-changed-before-close", "Topology lifecycle"}, + + // libmongoc does not include insertId in InsertOneResult + {"cancel-server-check", SKIP_ALL_TESTS}, + {0}, }; // clang-format on @@ -142,8 +190,6 @@ cleanup_failpoints (test_t *test, bson_error_t *error) failpoint_t *iter = NULL; mongoc_read_prefs_t *rp = NULL; - test_begin_suppressing_structured_logs (); - rp = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); LL_FOREACH (test->failpoints, iter) @@ -158,12 +204,18 @@ cleanup_failpoints (test_t *test, bson_error_t *error) disable_cmd = tmp_bson ("{'configureFailPoint': '%s', 'mode': 'off' }", iter->name); if (iter->server_id != 0) { - if (!mongoc_client_command_simple_with_server_id ( - client, "admin", disable_cmd, rp, iter->server_id, NULL /* reply */, error)) { + entity_map_log_filter_push (test->entity_map, iter->client_id, NULL, NULL); + bool command_ok = mongoc_client_command_simple_with_server_id ( + client, "admin", disable_cmd, rp, iter->server_id, NULL /* reply */, error); + entity_map_log_filter_pop (test->entity_map, iter->client_id, NULL, NULL); + if (!command_ok) { goto done; } } else { - if (!mongoc_client_command_simple (client, "admin", disable_cmd, rp, NULL /* reply */, error)) { + entity_map_log_filter_push (test->entity_map, iter->client_id, NULL, NULL); + bool command_ok = mongoc_client_command_simple (client, "admin", disable_cmd, rp, NULL /* reply */, error); + entity_map_log_filter_pop (test->entity_map, iter->client_id, NULL, NULL); + if (!command_ok) { goto done; } } @@ -172,7 +224,6 @@ cleanup_failpoints (test_t *test, bson_error_t *error) ret = true; done: mongoc_read_prefs_destroy (rp); - test_end_suppressing_structured_logs (); return ret; } @@ -272,8 +323,6 @@ test_runner_terminate_open_transactions (test_runner_t *test_runner, bson_error_ bool cmd_ret = false; bson_error_t cmd_error = {0}; - test_begin_suppressing_structured_logs (); - if (test_framework_getenv_bool ("MONGOC_TEST_ATLAS")) { // Not applicable when running as test-atlas-executor. return true; @@ -326,7 +375,6 @@ test_runner_terminate_open_transactions (test_runner_t *test_runner, bson_error_ ret = true; done: - test_end_suppressing_structured_logs (); return ret; } @@ -999,6 +1047,7 @@ test_check_event (test_t *test, bson_t *expected, event_t *actual, bson_error_t char *expected_command_name = NULL; char *expected_database_name = NULL; bson_t *expected_reply = NULL; + bool *expected_awaited = NULL; bool *expected_has_service_id = NULL; bool *expected_has_server_connection_id = NULL; bson_t *expected_previous_description = NULL; @@ -1033,6 +1082,7 @@ test_check_event (test_t *test, bson_t *expected, event_t *actual, bson_error_t bson_parser_utf8_optional (bp, "commandName", &expected_command_name); bson_parser_utf8_optional (bp, "databaseName", &expected_database_name); bson_parser_doc_optional (bp, "reply", &expected_reply); + bson_parser_bool_optional (bp, "awaited", &expected_awaited); bson_parser_bool_optional (bp, "hasServiceId", &expected_has_service_id); bson_parser_bool_optional (bp, "hasServerConnectionId", &expected_has_server_connection_id); bson_parser_doc_optional (bp, "previousDescription", &expected_previous_description); @@ -1111,6 +1161,23 @@ test_check_event (test_t *test, bson_t *expected, event_t *actual, bson_error_t } } + if (expected_awaited) { + if (!bson_iter_init_find (&iter, actual->serialized, "awaited")) { + test_set_error (error, "event.awaited field expected but missing"); + goto done; + } + if (!BSON_ITER_HOLDS_BOOL (&iter)) { + test_set_error (error, "Unexpected type for event.awaited, should be boolean"); + goto done; + } + bool actual_awaited = bson_iter_bool (&iter); + if (*expected_awaited != actual_awaited) { + test_error ("expected event.awaited=%s, found event.awaited=%s", + *expected_awaited ? "true" : "false", + actual_awaited ? "true" : "false"); + } + } + if (expected_has_service_id) { if (!bson_iter_init_find (&iter, actual->serialized, "serviceId")) { test_set_error (error, "event.serviceId field expected but missing"); @@ -1198,6 +1265,14 @@ test_check_event (test_t *test, bson_t *expected, event_t *actual, bson_error_t return ret; } +static bool +event_matches_eventtype (const event_t *event, const char *eventType) +{ + BSON_ASSERT_PARAM (event); + BSON_OPTIONAL_PARAM (eventType); + return 0 == bson_strcasecmp (event->eventType, eventType ? eventType : "command"); +} + bool test_count_matching_events_for_client ( test_t *test, entity_t *client, bson_t *expected_event, bson_error_t *error, int64_t *count_out) @@ -1220,18 +1295,13 @@ static bool test_check_expected_events_for_client (test_t *test, bson_t *expected_events_for_client, bson_error_t *error) { bool ret = false; - bson_parser_t *bp; + entity_t *entity = NULL; + char *client_id; bson_t *expected_events; bool *ignore_extra_events; - entity_t *entity = NULL; - bson_iter_t iter; - event_t *eiter; - uint32_t expected_num_events; - uint32_t actual_num_events; char *event_type; - - bp = bson_parser_new (); + bson_parser_t *bp = bson_parser_new (); bson_parser_utf8 (bp, "client", &client_id); bson_parser_array (bp, "events", &expected_events); bson_parser_bool_optional (bp, "ignoreExtraEvents", &ignore_extra_events); @@ -1240,26 +1310,36 @@ test_check_expected_events_for_client (test_t *test, bson_t *expected_events_for goto done; } - if (event_type) { - if (0 == strcmp (event_type, "cmap")) { - /* TODO: (CDRIVER-3525) Explicitly ignore cmap events until CMAP is - * supported. */ - ret = true; - goto done; - } else if (0 != strcmp (event_type, "command")) { - test_set_error (error, "unexpected event type: %s", event_type); - goto done; - } - } - entity = entity_map_get (test->entity_map, client_id, error); + if (!entity) { + test_set_error (error, "missing entity '%s', expected client", client_id); + goto done; + } if (0 != strcmp (entity->type, "client")) { - test_set_error (error, "expected entity %s to be client, got: %s", entity->id, entity->type); + test_set_error (error, "expected entity '%s' to be client, got: %s", entity->id, entity->type); + goto done; + } + + if (event_type && 0 == strcmp (event_type, "cmap")) { + /* Full CMAP support (CDRIVER-3525) is not currently planned for this driver. + * Many tests that would otherwise need to be skipped can be partially executed + * by letting checks for CMAP events artificially pass. */ + MONGOC_DEBUG ("SKIPPING expectEvents check for unsupported \"cmap\" events\n"); + ret = true; goto done; } - expected_num_events = bson_count_keys (expected_events); - LL_COUNT (entity->events, eiter, actual_num_events); + uint32_t expected_num_events = bson_count_keys (expected_events); + uint32_t actual_num_events = 0; + + event_t *eiter; + LL_FOREACH (entity->events, eiter) + { + if (event_matches_eventtype (eiter, event_type)) { + actual_num_events++; + } + } + if (expected_num_events != actual_num_events) { bool too_many_events = actual_num_events > expected_num_events; if (ignore_extra_events && *ignore_extra_events) { @@ -1275,10 +1355,13 @@ test_check_expected_events_for_client (test_t *test, bson_t *expected_events_for } eiter = entity->events; + bson_iter_t iter; BSON_FOREACH (expected_events, iter) { + while (eiter && !event_matches_eventtype (eiter, event_type)) { + eiter = eiter->next; + } bson_t expected_event; - bson_iter_bson (&iter, &expected_event); if (!eiter) { test_set_error (error, "could not find event: %s", tmp_json (&expected_event)); @@ -1509,13 +1592,21 @@ test_check_expected_log_messages_for_client (test_t *test, goto done; } + /* Note: entity->value might be NULL and that's fine. + * The unified testing spec recommends that tests don't refer to closed clients, + * but some tests do for checking lifecycle logging. + * See /server_discovery_and_monitoring/unified/logging-standalone */ entity_t *entity = entity_map_get (test->entity_map, client_id, error); + if (!entity) { + test_set_error (error, "missing entity '%s', expected client", client_id); + goto done; + } if (0 != strcmp (entity->type, "client")) { - test_set_error (error, "expected entity %s to be client, got: %s", entity->id, entity->type); + test_set_error (error, "expected entity '%s' to be client, got: %s", entity->id, entity->type); goto done; } - locked = &entity->log_messages_mutex; + locked = &entity->log_mutex; bson_mutex_lock (locked); log_message_t *actual_message_iter = entity->log_messages; @@ -1526,6 +1617,7 @@ test_check_expected_log_messages_for_client (test_t *test, while (actual_message_iter || expected_message_iter_ok) { if (actual_message_iter && test_log_message_should_be_ignored (test, actual_message_iter, ignore_messages, error)) { + MONGOC_DEBUG ("log message ignored, %s", tmp_json (actual_message_iter->message)); actual_message_iter = actual_message_iter->next; continue; } @@ -1549,13 +1641,11 @@ test_check_expected_log_messages_for_client (test_t *test, bson_t expected_message; bson_iter_bson (&expected_message_iter, &expected_message); bool is_match = test_check_log_message (test, &expected_message, actual_message_iter, error); - if (!is_match) { - test_diagnostics_error_info ("expected log message: %s\nactual log message: %s, %s, %s", - tmp_json (&expected_message), - mongoc_structured_log_get_level_name (actual_message_iter->level), - mongoc_structured_log_get_component_name (actual_message_iter->component), - tmp_json (actual_message_iter->message)); - } + MONGOC_DEBUG ("log message check %s %s, expected: %s, actual: %s", + is_match ? "MATCHED" : "FAILED", + error && !is_match ? error->message : "", + tmp_json (&expected_message), + tmp_json (actual_message_iter->message)); bson_destroy (&expected_message); if (!is_match) { goto done; @@ -2130,4 +2220,6 @@ test_install_unified (TestSuite *suite) run_unified_tests (suite, JSON_DIR, "command-logging-and-monitoring"); run_unified_tests (suite, JSON_DIR, "server_selection/logging"); + + run_unified_tests (suite, JSON_DIR, "server_discovery_and_monitoring/unified"); } diff --git a/src/libmongoc/tests/unified/util.c b/src/libmongoc/tests/unified/util.c index 3cac301a545..c92b691ca43 100644 --- a/src/libmongoc/tests/unified/util.c +++ b/src/libmongoc/tests/unified/util.c @@ -115,8 +115,8 @@ test_bson_util_install (TestSuite *suite) TestSuite_Add (suite, "/unified/selftest/util/copy_and_sort", test_copy_and_sort); } -/* TODO (CDRIVER-3525) add test support for CMAP events once the C driver - * supports CMAP. */ +/* CMAP (CDRIVER-3525) isn't planned for implementation in this driver. Many tests that would otherwise require CMAP + * are used in partial form by skipping individual checks that involve unsupported events. */ bool is_unsupported_event_type (const char *event_type) {