@@ -130,6 +130,120 @@ test_server_selection_try_once_option (void)
130
130
}
131
131
}
132
132
133
+ static void
134
+ _test_server_selection (bool try_once )
135
+ {
136
+ mock_server_t * server ;
137
+ char * secondary_response ;
138
+ char * primary_response ;
139
+ mongoc_uri_t * uri ;
140
+ mongoc_client_t * client ;
141
+ mongoc_read_prefs_t * primary_pref ;
142
+ future_t * future ;
143
+ bson_error_t error ;
144
+ request_t * request ;
145
+ mongoc_server_description_t * sd ;
146
+
147
+ server = mock_server_new ();
148
+ mock_server_set_request_timeout_msec (server , 600 );
149
+ mock_server_run (server );
150
+
151
+ secondary_response = bson_strdup_printf (
152
+ "{'ok': 1, "
153
+ " 'ismaster': false,"
154
+ " 'secondary': true,"
155
+ " 'setName': 'rs',"
156
+ " 'hosts': ['%s']}" ,
157
+ mock_server_get_host_and_port (server ));
158
+
159
+ primary_response = bson_strdup_printf (
160
+ "{'ok': 1, "
161
+ " 'ismaster': true,"
162
+ " 'setName': 'rs',"
163
+ " 'hosts': ['%s']}" ,
164
+ mock_server_get_host_and_port (server ));
165
+
166
+ uri = mongoc_uri_copy (mock_server_get_uri (server ));
167
+ mongoc_uri_set_option_as_utf8 (uri , "replicaSet" , "rs" );
168
+ mongoc_uri_set_option_as_int32 (uri , "heartbeatFrequencyMS" , 500 );
169
+ mongoc_uri_set_option_as_int32 (uri , "serverSelectionTimeoutMS" , 100 );
170
+ if (!try_once ) {
171
+ /* serverSelectionTryOnce is on by default */
172
+ mongoc_uri_set_option_as_bool (uri , "serverSelectionTryOnce" , false);
173
+ }
174
+
175
+ client = mongoc_client_new_from_uri (uri );
176
+ primary_pref = mongoc_read_prefs_new (MONGOC_READ_PRIMARY );
177
+
178
+ /* no primary, selection fails after one try */
179
+ future = future_topology_select (client -> topology , MONGOC_SS_READ ,
180
+ primary_pref , 15 , & error );
181
+ assert (request = mock_server_receives_ismaster (server ));
182
+ mock_server_replies_simple (request , secondary_response );
183
+
184
+ if (try_once ) {
185
+ /* selection fails without another ismaster call */
186
+ assert (!mock_server_receives_ismaster (server ));
187
+ } else {
188
+ /* TODO: SPEC-289 the driver thinks there's time for one more check
189
+ * but there isn't, since selection time remaining < heartbeat.
190
+ * the test works until SPEC-289 is resolved and implemented.
191
+ */
192
+ assert (request = mock_server_receives_ismaster (server ));
193
+ mock_server_replies_simple (request , secondary_response );
194
+ request_destroy (request );
195
+ }
196
+
197
+ /* selection fails */
198
+ assert (!future_get_mongoc_server_description_ptr (future ));
199
+ ASSERT_CMPINT (error .domain , = = , MONGOC_ERROR_SERVER_SELECTION );
200
+ ASSERT_CMPINT (error .code , = = , MONGOC_ERROR_SERVER_SELECTION_FAILURE );
201
+
202
+ if (try_once ) {
203
+ ASSERT_CMPSTR ("No suitable servers found" , error .message );
204
+ } else {
205
+ ASSERT_CMPSTR ("Timed out trying to select a server" , error .message );
206
+ }
207
+
208
+ assert (client -> topology -> stale );
209
+ future_destroy (future );
210
+
211
+ _mongoc_usleep (510 * 1000 ); /* one heartbeat, plus a few milliseconds */
212
+
213
+ /* second selection, now we try ismaster again */
214
+ future = future_topology_select (client -> topology , MONGOC_SS_READ ,
215
+ primary_pref , 15 , & error );
216
+ assert (request = mock_server_receives_ismaster (server ));
217
+
218
+ /* the secondary is now primary, selection succeeds */
219
+ mock_server_replies_simple (request , primary_response );
220
+ sd = future_get_mongoc_server_description_ptr (future );
221
+ assert (sd );
222
+ assert (!client -> topology -> stale );
223
+ request_destroy (request );
224
+ future_destroy (future );
225
+
226
+ mongoc_server_description_destroy (sd );
227
+ mongoc_read_prefs_destroy (primary_pref );
228
+ mongoc_client_destroy (client );
229
+ mongoc_uri_destroy (uri );
230
+ bson_free (secondary_response );
231
+ bson_free (primary_response );
232
+ mock_server_destroy (server );
233
+ }
234
+
235
+ static void
236
+ test_server_selection_try_once (void )
237
+ {
238
+ _test_server_selection (true);
239
+ }
240
+
241
+ static void
242
+ test_server_selection_try_once_false (void )
243
+ {
244
+ _test_server_selection (false);
245
+ }
246
+
133
247
static void
134
248
test_topology_invalidate_server (void )
135
249
{
@@ -356,7 +470,8 @@ test_cooldown_rs (void)
356
470
}
357
471
358
472
uri_str = bson_strdup_printf (
359
- "mongodb://localhost:%hu/?replicaSet=rs&serverSelectionTimeoutMS=1000" ,
473
+ "mongodb://localhost:%hu/?replicaSet=rs&serverSelectionTimeoutMS=1000"
474
+ "&serverSelectionTryOnce=false" ,
360
475
mock_server_get_port (servers [0 ]));
361
476
362
477
client = mongoc_client_new (uri_str );
@@ -440,10 +555,9 @@ test_topology_install (TestSuite *suite)
440
555
{
441
556
TestSuite_Add (suite , "/Topology/client_creation" , test_topology_client_creation );
442
557
TestSuite_Add (suite , "/Topology/client_pool_creation" , test_topology_client_pool_creation );
443
- TestSuite_Add (suite ,
444
- "/Topology/server_selection_try_once_option" ,
445
- test_server_selection_try_once_option );
446
-
558
+ TestSuite_Add (suite , "/Topology/server_selection_try_once_option" , test_server_selection_try_once_option );
559
+ TestSuite_Add (suite , "/Topology/server_selection_try_once" , test_server_selection_try_once );
560
+ TestSuite_Add (suite , "/Topology/server_selection_try_once_false" , test_server_selection_try_once_false );
447
561
TestSuite_Add (suite , "/Topology/invalidate_server" , test_topology_invalidate_server );
448
562
TestSuite_Add (suite , "/Topology/invalid_cluster_node" , test_invalid_cluster_node );
449
563
TestSuite_Add (suite , "/Topology/max_wire_version_race_condition" , test_max_wire_version_race_condition );
0 commit comments