Skip to content

Commit dcde207

Browse files
committed
CDRIVER-4374 only allow extra fields when matching root docs
1 parent 757cd18 commit dcde207

File tree

5 files changed

+46
-31
lines changed

5 files changed

+46
-31
lines changed

src/libmongoc/tests/bsonutil/bson-match.c

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ bson_matcher_match (bson_matcher_t *matcher,
353353
const bson_val_t *expected,
354354
const bson_val_t *actual,
355355
const char *path,
356-
bool allow_extra,
356+
bool array_of_root_docs,
357357
bson_error_t *error)
358358
{
359359
bool ret = false;
@@ -421,12 +421,8 @@ bson_matcher_match (bson_matcher_t *matcher,
421421
}
422422

423423
path_child = bson_strdup_printf ("%s.%s", path, key);
424-
if (!bson_matcher_match (matcher,
425-
expected_val,
426-
actual_val,
427-
path_child,
428-
allow_extra,
429-
error)) {
424+
if (!bson_matcher_match (
425+
matcher, expected_val, actual_val, path_child, false, error)) {
430426
bson_val_destroy (expected_val);
431427
bson_val_destroy (actual_val);
432428
bson_free (path_child);
@@ -439,14 +435,20 @@ bson_matcher_match (bson_matcher_t *matcher,
439435

440436
expected_keys = bson_count_keys (expected_bson);
441437
actual_keys = bson_count_keys (actual_bson);
442-
if (!is_root) {
443-
if (expected_keys < actual_keys && !allow_extra) {
444-
MATCH_ERR ("expected %" PRIu32 " keys in document, got: %" PRIu32,
445-
expected_keys,
446-
actual_keys);
447-
goto done;
448-
}
438+
439+
/* Unified test format spec: "When matching root-level documents, test
440+
* runners MUST permit the actual document to contain additional fields
441+
* not present in the expected document.""
442+
*
443+
* This logic must also handle the case where `expected` is one of any
444+
* number of root documents within an array (i.e. cursor result). */
445+
if (!(is_root || array_of_root_docs) && expected_keys < actual_keys) {
446+
MATCH_ERR ("expected %" PRIu32 " keys in document, got: %" PRIu32,
447+
expected_keys,
448+
actual_keys);
449+
goto done;
449450
}
451+
450452
ret = true;
451453
goto done;
452454
}
@@ -467,8 +469,8 @@ bson_matcher_match (bson_matcher_t *matcher,
467469

468470
actual_bson = bson_val_to_array (actual);
469471
actual_keys = bson_count_keys (actual_bson);
470-
if ((expected_keys > actual_keys) ||
471-
(expected_keys < actual_keys && !allow_extra)) {
472+
473+
if (expected_keys != actual_keys) {
472474
MATCH_ERR ("expected array of size %" PRIu32
473475
", but got array of size: %" PRIu32,
474476
expected_keys,
@@ -498,7 +500,7 @@ bson_matcher_match (bson_matcher_t *matcher,
498500
expected_val,
499501
actual_val,
500502
path_child,
501-
allow_extra,
503+
(is_root && array_of_root_docs),
502504
error)) {
503505
bson_val_destroy (expected_val);
504506
bson_val_destroy (actual_val);
@@ -539,12 +541,12 @@ bson_matcher_match (bson_matcher_t *matcher,
539541
bool
540542
bson_match (const bson_val_t *expected,
541543
const bson_val_t *actual,
542-
bool allow_extra,
544+
bool array_of_root_docs,
543545
bson_error_t *error)
544546
{
545547
bson_matcher_t *matcher = bson_matcher_new ();
546-
bool matched =
547-
bson_matcher_match (matcher, expected, actual, "", allow_extra, error);
548+
bool matched = bson_matcher_match (
549+
matcher, expected, actual, "", array_of_root_docs, error);
548550
bson_matcher_destroy (matcher);
549551
return matched;
550552
}

src/libmongoc/tests/bsonutil/bson-match.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
bool
2525
bson_match (const bson_val_t *expected,
2626
const bson_val_t *actual,
27-
bool allow_extra,
27+
bool array_of_root_docs,
2828
bson_error_t *error);
2929

3030
/* A bson_matcher_t may be used to extend the default matching behavior. */
@@ -58,7 +58,7 @@ bson_matcher_match (bson_matcher_t *matcher,
5858
const bson_val_t *expected,
5959
const bson_val_t *actual,
6060
const char *path,
61-
bool allow_extra,
61+
bool array_of_root_docs,
6262
bson_error_t *error);
6363

6464
void

src/libmongoc/tests/unified/entity-map.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ entity_client_new (entity_map_t *em, bson_t *bson, bson_error_t *error)
353353
}
354354
} else if (use_multiple_mongoses != NULL) {
355355
if (!test_framework_uri_apply_multi_mongos (
356-
uri, *use_multiple_mongoses, error)) {
356+
uri, *use_multiple_mongoses, error)) {
357357
goto done;
358358
}
359359
}
@@ -396,7 +396,8 @@ entity_client_new (entity_map_t *em, bson_t *bson, bson_error_t *error)
396396
} else if (0 == strcmp (event_type, "commandSucceededEvent")) {
397397
mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
398398
} else if (is_unsupported_event_type (event_type)) {
399-
MONGOC_DEBUG ("Skipping observing unsupported event type: %s", event_type);
399+
MONGOC_DEBUG ("Skipping observing unsupported event type: %s",
400+
event_type);
400401
continue;
401402
} else {
402403
test_set_error (error, "Unexpected event type: %s", event_type);
@@ -1288,7 +1289,7 @@ bool
12881289
entity_map_match (entity_map_t *em,
12891290
const bson_val_t *expected,
12901291
const bson_val_t *actual,
1291-
bool allow_extra,
1292+
bool array_of_root_docs,
12921293
bson_error_t *error)
12931294
{
12941295
bson_matcher_t *matcher;
@@ -1299,7 +1300,8 @@ entity_map_match (entity_map_t *em,
12991300
matcher, "$$sessionLsid", special_session_lsid, em);
13001301
bson_matcher_add_special (
13011302
matcher, "$$matchesEntity", special_matches_entity, em);
1302-
ret = bson_matcher_match (matcher, expected, actual, "", allow_extra, error);
1303+
ret = bson_matcher_match (
1304+
matcher, expected, actual, "", array_of_root_docs, error);
13031305
bson_matcher_destroy (matcher);
13041306
return ret;
13051307
}

src/libmongoc/tests/unified/result.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct _result_t {
3333
For a read operation, reply is an optional server reply. */
3434
bson_t *reply;
3535
char *str;
36+
bool array_of_root_docs;
3637
};
3738

3839
result_t *
@@ -305,6 +306,7 @@ result_from_cursor (result_t *result, mongoc_cursor_t *cursor)
305306
val = bson_val_from_array (documents);
306307

307308
_result_init (result, val, (bson_t *) reply, &error);
309+
result->array_of_root_docs = true;
308310
bson_destroy (documents);
309311
bson_val_destroy (val);
310312
}
@@ -361,9 +363,13 @@ result_check (result_t *result,
361363
error, "expected result, but got error: %s", result->error.message);
362364
goto done;
363365
}
364-
if (!entity_map_match (em, expect_result, result->value, false, error)) {
366+
if (!entity_map_match (em,
367+
expect_result,
368+
result->value,
369+
result->array_of_root_docs,
370+
error)) {
365371
test_set_error (error,
366-
"checking expectResult: %s",
372+
"checking expectResult: %s\n",
367373
bson_val_to_json (expect_result));
368374
goto done;
369375
}
@@ -527,7 +533,12 @@ result_check (result_t *result,
527533
goto done;
528534
}
529535

530-
if (!bson_match (error_expect_result, result->value, true, error)) {
536+
/* TODO: expectError.expectResult is not used for cursor-bearing
537+
* operations, so array_of_root_docs should always be false */
538+
if (!bson_match (error_expect_result,
539+
result->value,
540+
result->array_of_root_docs,
541+
error)) {
531542
test_diagnostics_error_info (
532543
"checking error.expectResult: %s",
533544
bson_val_to_json (error_expect_result));

src/libmongoc/tests/unified/runner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ test_check_event (test_t *test,
10731073
actual_val = bson_val_from_bson (actual->command);
10741074

10751075
if (!entity_map_match (
1076-
test->entity_map, expected_val, actual_val, true, error)) {
1076+
test->entity_map, expected_val, actual_val, false, error)) {
10771077
bson_val_destroy (expected_val);
10781078
bson_val_destroy (actual_val);
10791079
goto done;
@@ -1104,7 +1104,7 @@ test_check_event (test_t *test,
11041104
bson_val_t *expected_val = bson_val_from_bson (expected_reply);
11051105
bson_val_t *actual_val = bson_val_from_bson (actual->reply);
11061106
if (!entity_map_match (
1107-
test->entity_map, expected_val, actual_val, true, error)) {
1107+
test->entity_map, expected_val, actual_val, false, error)) {
11081108
bson_val_destroy (expected_val);
11091109
bson_val_destroy (actual_val);
11101110
goto done;

0 commit comments

Comments
 (0)