Skip to content

Commit 57b3497

Browse files
committed
CDRIVER-2558 more tests of network errs in txns
1 parent 53d3ec4 commit 57b3497

File tree

5 files changed

+137
-71
lines changed

5 files changed

+137
-71
lines changed

src/libmongoc/tests/mock_server/mock-server.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,12 +1938,14 @@ mock_server_set_bind_opts (mock_server_t *server, mock_server_bind_opts_t *opts)
19381938
}
19391939

19401940
void
1941-
rs_response_to_ismaster (mock_server_t *server, bool primary, int has_tags, ...)
1941+
rs_response_to_ismaster (
1942+
mock_server_t *server, int max_wire_version, bool primary, int has_tags, ...)
19421943
{
19431944
va_list ap;
19441945
bson_string_t *hosts;
19451946
bool first;
19461947
mock_server_t *host;
1948+
const char *session_timeout;
19471949
char *ismaster_response;
19481950

19491951
hosts = bson_string_new ("");
@@ -1964,19 +1966,29 @@ rs_response_to_ismaster (mock_server_t *server, bool primary, int has_tags, ...)
19641966

19651967
va_end (ap);
19661968

1969+
if (max_wire_version >= 6) {
1970+
session_timeout = ", 'logicalSessionTimeoutMinutes': 30";
1971+
mock_server_auto_endsessions (server);
1972+
} else {
1973+
session_timeout = "";
1974+
}
1975+
19671976
ismaster_response = bson_strdup_printf ("{'ok': 1, "
19681977
" 'setName': 'rs',"
19691978
" 'ismaster': %s,"
19701979
" 'secondary': %s,"
19711980
" 'tags': {%s},"
19721981
" 'minWireVersion': 3,"
1973-
" 'maxWireVersion': 6,"
1982+
" 'maxWireVersion': %d,"
19741983
" 'hosts': [%s]"
1984+
" %s"
19751985
"}",
19761986
primary ? "true" : "false",
19771987
primary ? "false" : "true",
19781988
has_tags ? "'key': 'value'" : "",
1979-
hosts->str);
1989+
max_wire_version,
1990+
hosts->str,
1991+
session_timeout);
19801992

19811993
mock_server_auto_ismaster (server, "%s", ismaster_response);
19821994

src/libmongoc/tests/mock_server/mock-server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ mock_server_destroy (mock_server_t *server);
211211

212212
void
213213
rs_response_to_ismaster (mock_server_t *server,
214+
int max_wire_version,
214215
bool primary,
215216
int has_tags,
216217
...);

src/libmongoc/tests/test-mongoc-topology-reconcile.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ _test_topology_reconcile_rs (bool pooled)
110110
mock_server_run (server1);
111111

112112
/* secondary, no tags */
113-
RS_RESPONSE_TO_ISMASTER (server0, false, false, server0, server1);
113+
RS_RESPONSE_TO_ISMASTER (server0, 6, false, false, server0, server1);
114114
/* primary, no tags */
115-
RS_RESPONSE_TO_ISMASTER (server1, true, false, server0, server1);
115+
RS_RESPONSE_TO_ISMASTER (server1, 6, true, false, server0, server1);
116116

117117
/* provide secondary in seed list */
118118
uri_str = bson_strdup_printf ("mongodb://%s/?replicaSet=rs",
@@ -151,7 +151,8 @@ _test_topology_reconcile_rs (bool pooled)
151151
/*
152152
* remove server1 from set. server0 is the primary, with tags.
153153
*/
154-
RS_RESPONSE_TO_ISMASTER (server0, true, true, server0); /* server1 absent */
154+
RS_RESPONSE_TO_ISMASTER (
155+
server0, 6, true, true, server0); /* server1 absent */
155156

156157
BSON_ASSERT (selects_server (client, tag_read_prefs, server0));
157158
BSON_ASSERT (!client->topology->stale);
@@ -163,8 +164,8 @@ _test_topology_reconcile_rs (bool pooled)
163164
/*
164165
* server1 returns as a secondary. its scanner node is un-retired.
165166
*/
166-
RS_RESPONSE_TO_ISMASTER (server0, true, true, server0, server1);
167-
RS_RESPONSE_TO_ISMASTER (server1, false, false, server0, server1);
167+
RS_RESPONSE_TO_ISMASTER (server0, 6, true, true, server0, server1);
168+
RS_RESPONSE_TO_ISMASTER (server1, 6, false, false, server0, server1);
168169

169170
BSON_ASSERT (selects_server (client, secondary_read_prefs, server1));
170171

@@ -475,8 +476,8 @@ _test_topology_reconcile_retire (bool pooled)
475476
mock_server_run (secondary);
476477
mock_server_run (primary);
477478

478-
RS_RESPONSE_TO_ISMASTER (primary, true, false, secondary, primary);
479-
RS_RESPONSE_TO_ISMASTER (secondary, false, false, secondary, primary);
479+
RS_RESPONSE_TO_ISMASTER (primary, 6, true, false, secondary, primary);
480+
RS_RESPONSE_TO_ISMASTER (secondary, 6, false, false, secondary, primary);
480481

481482
/* selection timeout must be > MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS,
482483
* otherwise we skip second scan in pooled mode and don't hit the assert */
@@ -505,7 +506,7 @@ _test_topology_reconcile_retire (bool pooled)
505506

506507
/* remove secondary from primary's config */
507508
mongoc_mutex_lock (&topology->mutex);
508-
RS_RESPONSE_TO_ISMASTER (primary, true, false, primary);
509+
RS_RESPONSE_TO_ISMASTER (primary, 6, true, false, primary);
509510

510511
/* step 2: cluster opens new stream to primary - force new stream in single
511512
* mode by disconnecting scanner nodes (also includes step 6) */
@@ -523,7 +524,7 @@ _test_topology_reconcile_retire (bool pooled)
523524
future = future_client_read_command_with_opts (
524525
client, "admin", tmp_bson ("{'ping': 1}"), NULL, NULL, NULL, &error);
525526
request = mock_server_receives_msg (
526-
primary, MONGOC_QUERY_NONE, tmp_bson("{'ping': 1}"));
527+
primary, MONGOC_QUERY_NONE, tmp_bson ("{'ping': 1}"));
527528
mock_server_replies_ok_and_destroys (request);
528529
ASSERT_OR_PRINT (future_get_bool (future), error);
529530

@@ -620,8 +621,8 @@ _test_topology_reconcile_add (bool pooled)
620621
mock_server_run (primary);
621622

622623
/* omit secondary from primary's ismaster, to start with */
623-
RS_RESPONSE_TO_ISMASTER (primary, true, false, primary);
624-
RS_RESPONSE_TO_ISMASTER (secondary, false, false, secondary, primary);
624+
RS_RESPONSE_TO_ISMASTER (primary, 6, true, false, primary);
625+
RS_RESPONSE_TO_ISMASTER (secondary, 6, false, false, secondary, primary);
625626

626627
/* selection timeout must be > MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS,
627628
* otherwise we skip second scan in pooled mode and don't hit the assert */
@@ -647,7 +648,7 @@ _test_topology_reconcile_add (bool pooled)
647648
BSON_ASSERT (selects_server (client, primary_read_prefs, primary));
648649

649650
/* add secondary to primary's config */
650-
RS_RESPONSE_TO_ISMASTER (primary, true, false, primary, secondary);
651+
RS_RESPONSE_TO_ISMASTER (primary, 6, true, false, primary, secondary);
651652

652653
/* step 2: cluster opens new stream to primary - force new stream in single
653654
* mode by disconnecting primary scanner node */
@@ -662,7 +663,7 @@ _test_topology_reconcile_add (bool pooled)
662663
future = future_client_read_command_with_opts (
663664
client, "admin", tmp_bson ("{'ping': 1}"), NULL, NULL, NULL, &error);
664665
request = mock_server_receives_msg (
665-
primary, MONGOC_QUERY_NONE, tmp_bson("{'ping': 1}"));
666+
primary, MONGOC_QUERY_NONE, tmp_bson ("{'ping': 1}"));
666667
mock_server_replies_ok_and_destroys (request);
667668
ASSERT_OR_PRINT (future_get_bool (future), error);
668669

src/libmongoc/tests/test-mongoc-topology.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,8 +1700,8 @@ _test_request_scan_on_error (bool pooled,
17001700
mock_server_run (secondary);
17011701
read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
17021702

1703-
RS_RESPONSE_TO_ISMASTER (primary, true, false, primary, secondary);
1704-
RS_RESPONSE_TO_ISMASTER (secondary, false, false, primary, secondary);
1703+
RS_RESPONSE_TO_ISMASTER (primary, 6, true, false, primary, secondary);
1704+
RS_RESPONSE_TO_ISMASTER (secondary, 6, false, false, primary, secondary);
17051705

17061706
/* set a high heartbeatFrequency. Only the first and requested scans run. */
17071707
uri_str = bson_strdup_printf (

src/libmongoc/tests/test-mongoc-transactions.c

Lines changed: 105 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,23 @@ test_transactions_supported (void *ctx)
108108
}
109109

110110

111+
static bool
112+
hangup_except_ismaster (request_t *request, void *data)
113+
{
114+
if (!bson_strcasecmp (request->command_name, "ismaster")) {
115+
/* allow default response */
116+
return false;
117+
}
118+
119+
mock_server_hangs_up (request);
120+
return true;
121+
}
122+
123+
111124
static void
112-
test_server_selection_error (void)
125+
_test_transient_txn_err (bool hangup)
113126
{
114-
mock_rs_t *rs;
127+
mock_server_t *server;
115128
mongoc_client_t *client;
116129
mongoc_client_session_t *session;
117130
mongoc_collection_t *collection;
@@ -127,13 +140,14 @@ test_server_selection_error (void)
127140
bson_t reply;
128141
bool r;
129142

130-
rs = mock_rs_with_autoismaster (7 /* wire version */,
131-
true /* has primary */,
132-
0 /* secondaries */,
133-
0 /* arbiters */);
143+
server = mock_server_new ();
144+
mock_server_run (server);
145+
rs_response_to_ismaster (
146+
server, 7, true /* primary */, false /* tags */, server, NULL);
134147

135-
mock_rs_run (rs);
136-
client = mongoc_client_new_from_uri (mock_rs_get_uri (rs));
148+
client = mongoc_client_new_from_uri (mock_server_get_uri (server));
149+
/* allow fast reconnect */
150+
client->topology->min_heartbeat_frequency_msec = 0;
137151
session = mongoc_client_start_session (client, NULL, &error);
138152
ASSERT_OR_PRINT (session, error);
139153
r = mongoc_client_session_start_transaction (session, NULL, &error);
@@ -142,8 +156,15 @@ test_server_selection_error (void)
142156
ASSERT_OR_PRINT (r, error);
143157
collection = mongoc_client_get_collection (client, "db", "collection");
144158

145-
/* stop responding */
146-
mock_rs_destroy (rs);
159+
if (hangup) {
160+
/* test that network errors have TransientTransactionError */
161+
mock_server_autoresponds (server, hangup_except_ismaster, NULL, NULL);
162+
} else {
163+
/* test server selection errors have TransientTransactionError */
164+
mock_server_destroy (server);
165+
server = NULL;
166+
}
167+
147168
/* warnings when trying to abort the transaction and later, end sessions */
148169
capture_logs (true);
149170

@@ -157,81 +178,110 @@ test_server_selection_error (void)
157178
} \
158179
} while (0)
159180

160-
#define TEST_SS_ERR(_expr) \
181+
#define TEST_CMD_ERR(_expr) \
182+
do { \
183+
r = (_expr); \
184+
BSON_ASSERT (!r); \
185+
ASSERT_TRANSIENT_LABEL (&reply, _expr); \
186+
bson_destroy (&reply); \
187+
/* clean slate for next test */ \
188+
memset (&reply, 0, sizeof (reply)); \
189+
} while (0)
190+
191+
192+
#define TEST_WRITE_ERR(_expr) \
161193
do { \
162194
r = (_expr); \
163-
BSON_ASSERT (!r); \
164195
ASSERT_TRANSIENT_LABEL (&reply, _expr); \
165196
bson_destroy (&reply); \
166197
/* clean slate for next test */ \
167198
memset (&reply, 0, sizeof (reply)); \
168199
} while (0)
169200

170-
#define TEST_SS_ERR_CURSOR(_cursor_expr) \
171-
do { \
172-
cursor = (_cursor_expr); \
173-
r = mongoc_cursor_next (cursor, &doc_out); \
174-
BSON_ASSERT (!r); \
175-
r = !mongoc_cursor_error_document (cursor, &error, &error_doc); \
176-
BSON_ASSERT (!r); \
177-
BSON_ASSERT (error_doc); \
178-
ASSERT_TRANSIENT_LABEL (error_doc, _cursor_expr); \
179-
mongoc_cursor_destroy (cursor); \
201+
#define TEST_CURSOR_ERR(_cursor_expr) \
202+
do { \
203+
cursor = (_cursor_expr); \
204+
r = mongoc_cursor_next (cursor, &doc_out); \
205+
BSON_ASSERT (!r); \
206+
r = !mongoc_cursor_error_document (cursor, &error, &error_doc); \
207+
BSON_ASSERT (!r); \
208+
BSON_ASSERT (error_doc); \
209+
ASSERT_TRANSIENT_LABEL (error_doc, _cursor_expr); \
210+
mongoc_cursor_destroy (cursor); \
180211
} while (0)
181212

182213
b = tmp_bson ("{'x': 1}");
183214
u = tmp_bson ("{'$inc': {'x': 1}}");
184215

185-
TEST_SS_ERR (mongoc_client_command_with_opts (
216+
TEST_CMD_ERR (mongoc_client_command_with_opts (
186217
client, "db", b, NULL, &opts, &reply, NULL));
187-
TEST_SS_ERR (mongoc_client_read_command_with_opts (
218+
TEST_CMD_ERR (mongoc_client_read_command_with_opts (
188219
client, "db", b, NULL, &opts, &reply, NULL));
189-
TEST_SS_ERR (mongoc_client_write_command_with_opts (
220+
TEST_CMD_ERR (mongoc_client_write_command_with_opts (
190221
client, "db", b, &opts, &reply, NULL));
191-
TEST_SS_ERR (mongoc_client_read_write_command_with_opts (
222+
TEST_CMD_ERR (mongoc_client_read_write_command_with_opts (
192223
client, "db", b, NULL, &opts, &reply, NULL));
193-
TEST_SS_ERR (
224+
TEST_CMD_ERR (0 < mongoc_collection_count_documents (
225+
collection, b, &opts, NULL, &reply, NULL));
226+
227+
BEGIN_IGNORE_DEPRECATIONS;
228+
TEST_CMD_ERR (mongoc_collection_create_index_with_opts (
229+
collection, b, NULL, &opts, &reply, NULL));
230+
END_IGNORE_DEPRECATIONS
231+
232+
fam = mongoc_find_and_modify_opts_new ();
233+
mongoc_find_and_modify_opts_append (fam, &opts);
234+
TEST_CMD_ERR (mongoc_collection_find_and_modify_with_opts (
235+
collection, b, fam, &reply, NULL));
236+
237+
TEST_WRITE_ERR (
194238
mongoc_collection_insert_one (collection, b, &opts, &reply, NULL));
195-
TEST_SS_ERR (mongoc_collection_insert_many (
239+
TEST_WRITE_ERR (mongoc_collection_insert_many (
196240
collection, (const bson_t **) &b, 1, &opts, &reply, NULL));
197-
TEST_SS_ERR (
241+
TEST_WRITE_ERR (
198242
mongoc_collection_update_one (collection, b, u, &opts, &reply, NULL));
199-
TEST_SS_ERR (
243+
TEST_WRITE_ERR (
200244
mongoc_collection_update_many (collection, b, u, &opts, &reply, NULL));
201-
TEST_SS_ERR (
245+
TEST_WRITE_ERR (
202246
mongoc_collection_replace_one (collection, b, b, &opts, &reply, NULL));
203-
TEST_SS_ERR (
247+
TEST_WRITE_ERR (
204248
mongoc_collection_delete_one (collection, b, &opts, &reply, NULL));
205-
TEST_SS_ERR (
249+
TEST_WRITE_ERR (
206250
mongoc_collection_delete_many (collection, b, &opts, &reply, NULL));
207-
TEST_SS_ERR (0 < mongoc_collection_count_documents (
208-
collection, b, &opts, NULL, &reply, NULL));
209-
210-
TEST_SS_ERR_CURSOR (mongoc_collection_aggregate (
211-
collection, MONGOC_QUERY_NONE, tmp_bson ("[{}]"), &opts, NULL));
212-
TEST_SS_ERR_CURSOR (
213-
mongoc_collection_find_with_opts (collection, b, &opts, NULL));
214251

215252
bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
216253
mongoc_bulk_operation_insert (bulk, b);
217-
TEST_SS_ERR (mongoc_bulk_operation_execute (bulk, &reply, NULL));
254+
TEST_WRITE_ERR (mongoc_bulk_operation_execute (bulk, &reply, NULL));
218255

219-
fam = mongoc_find_and_modify_opts_new ();
220-
mongoc_find_and_modify_opts_append (fam, &opts);
221-
TEST_SS_ERR (mongoc_collection_find_and_modify_with_opts (
222-
collection, b, fam, &reply, NULL));
223-
224-
BEGIN_IGNORE_DEPRECATIONS;
225-
TEST_SS_ERR (mongoc_collection_create_index_with_opts (
226-
collection, b, NULL, &opts, &reply, NULL));
227-
END_IGNORE_DEPRECATIONS
256+
TEST_CURSOR_ERR (mongoc_collection_aggregate (
257+
collection, MONGOC_QUERY_NONE, tmp_bson ("[{}]"), &opts, NULL));
258+
TEST_CURSOR_ERR (
259+
mongoc_collection_find_with_opts (collection, b, &opts, NULL));
228260

229261
mongoc_find_and_modify_opts_destroy (fam);
230262
mongoc_bulk_operation_destroy (bulk);
231263
bson_destroy (&opts);
232264
mongoc_collection_destroy (collection);
233265
mongoc_client_session_destroy (session);
234266
mongoc_client_destroy (client);
267+
268+
if (server) {
269+
mock_server_destroy (server);
270+
}
271+
}
272+
273+
274+
static void
275+
test_server_selection_error (void)
276+
{
277+
_test_transient_txn_err (false /* hangup */);
278+
}
279+
280+
281+
static void
282+
test_network_error (void)
283+
{
284+
_test_transient_txn_err (true /* hangup */);
235285
}
236286

237287

@@ -242,9 +292,7 @@ test_transactions_install (TestSuite *suite)
242292

243293
ASSERT (realpath (JSON_DIR "/transactions", resolved));
244294
install_json_test_suite_with_check (
245-
suite,
246-
resolved,
247-
test_transactions_cb,test_framework_skip_if_no_txns);
295+
suite, resolved, test_transactions_cb, test_framework_skip_if_no_txns);
248296

249297
/* skip mongos for now - txn support coming in 4.1.0 */
250298
TestSuite_AddFull (suite,
@@ -259,4 +307,8 @@ test_transactions_install (TestSuite *suite)
259307
"/transactions/server_selection_err",
260308
test_server_selection_error,
261309
test_framework_skip_if_no_crypto);
310+
TestSuite_AddMockServerTest (suite,
311+
"/transactions/network_err",
312+
test_network_error,
313+
test_framework_skip_if_no_crypto);
262314
}

0 commit comments

Comments
 (0)