Skip to content

Commit 9ac2689

Browse files
committed
CDRIVER-4374 only allow extra fields when matching root docs
1 parent 1841a0e commit 9ac2689

File tree

5 files changed

+42
-28
lines changed

5 files changed

+42
-28
lines changed

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

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ bson_matcher_match (bson_matcher_t *matcher,
369369
const bson_val_t *expected,
370370
const bson_val_t *actual,
371371
const char *path,
372-
bool allow_extra,
372+
bool array_of_root_docs,
373373
bson_error_t *error)
374374
{
375375
bool ret = false;
@@ -437,12 +437,8 @@ bson_matcher_match (bson_matcher_t *matcher,
437437
}
438438

439439
path_child = bson_strdup_printf ("%s.%s", path, key);
440-
if (!bson_matcher_match (matcher,
441-
expected_val,
442-
actual_val,
443-
path_child,
444-
allow_extra,
445-
error)) {
440+
if (!bson_matcher_match (
441+
matcher, expected_val, actual_val, path_child, false, error)) {
446442
bson_val_destroy (expected_val);
447443
bson_val_destroy (actual_val);
448444
bson_free (path_child);
@@ -455,14 +451,20 @@ bson_matcher_match (bson_matcher_t *matcher,
455451

456452
expected_keys = bson_count_keys (expected_bson);
457453
actual_keys = bson_count_keys (actual_bson);
458-
if (!is_root) {
459-
if (expected_keys < actual_keys && !allow_extra) {
460-
MATCH_ERR ("expected %" PRIu32 " keys in document, got: %" PRIu32,
461-
expected_keys,
462-
actual_keys);
463-
goto done;
464-
}
454+
455+
/* Unified test format spec: "When matching root-level documents, test
456+
* runners MUST permit the actual document to contain additional fields
457+
* not present in the expected document.""
458+
*
459+
* This logic must also handle the case where `expected` is one of any
460+
* number of root documents within an array (i.e. cursor result). */
461+
if (!(is_root || array_of_root_docs) && expected_keys < actual_keys) {
462+
MATCH_ERR ("expected %" PRIu32 " keys in document, got: %" PRIu32,
463+
expected_keys,
464+
actual_keys);
465+
goto done;
465466
}
467+
466468
ret = true;
467469
goto done;
468470
}
@@ -483,8 +485,8 @@ bson_matcher_match (bson_matcher_t *matcher,
483485

484486
actual_bson = bson_val_to_array (actual);
485487
actual_keys = bson_count_keys (actual_bson);
486-
if ((expected_keys > actual_keys) ||
487-
(expected_keys < actual_keys && !allow_extra)) {
488+
489+
if (expected_keys != actual_keys) {
488490
MATCH_ERR ("expected array of size %" PRIu32
489491
", but got array of size: %" PRIu32,
490492
expected_keys,
@@ -514,7 +516,7 @@ bson_matcher_match (bson_matcher_t *matcher,
514516
expected_val,
515517
actual_val,
516518
path_child,
517-
allow_extra,
519+
(is_root && array_of_root_docs),
518520
error)) {
519521
bson_val_destroy (expected_val);
520522
bson_val_destroy (actual_val);
@@ -555,12 +557,12 @@ bson_matcher_match (bson_matcher_t *matcher,
555557
bool
556558
bson_match (const bson_val_t *expected,
557559
const bson_val_t *actual,
558-
bool allow_extra,
560+
bool array_of_root_docs,
559561
bson_error_t *error)
560562
{
561563
bson_matcher_t *matcher = bson_matcher_new ();
562-
bool matched =
563-
bson_matcher_match (matcher, expected, actual, "", allow_extra, error);
564+
bool matched = bson_matcher_match (
565+
matcher, expected, actual, "", array_of_root_docs, error);
564566
bson_matcher_destroy (matcher);
565567
return matched;
566568
}

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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,7 +1819,7 @@ bool
18191819
entity_map_match (entity_map_t *em,
18201820
const bson_val_t *expected,
18211821
const bson_val_t *actual,
1822-
bool allow_extra,
1822+
bool array_of_root_docs,
18231823
bson_error_t *error)
18241824
{
18251825
bson_matcher_t *matcher;
@@ -1830,7 +1830,8 @@ entity_map_match (entity_map_t *em,
18301830
matcher, "$$sessionLsid", special_session_lsid, em);
18311831
bson_matcher_add_special (
18321832
matcher, "$$matchesEntity", special_matches_entity, em);
1833-
ret = bson_matcher_match (matcher, expected, actual, "", allow_extra, error);
1833+
ret = bson_matcher_match (
1834+
matcher, expected, actual, "", array_of_root_docs, error);
18341835
bson_matcher_destroy (matcher);
18351836
return ret;
18361837
}

src/libmongoc/tests/unified/result.c

Lines changed: 13 additions & 2 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,7 +363,11 @@ 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,
366372
"expectResult mismatch:\nExpected: %s\nActual: %s\n",
367373
bson_val_to_json (expect_result),
@@ -528,7 +534,12 @@ result_check (result_t *result,
528534
goto done;
529535
}
530536

531-
if (!bson_match (error_expect_result, result->value, true, error)) {
537+
/* TODO: expectError.expectResult is not used for cursor-bearing
538+
* operations, so array_of_root_docs should always be false */
539+
if (!bson_match (error_expect_result,
540+
result->value,
541+
result->array_of_root_docs,
542+
error)) {
532543
test_diagnostics_error_info (
533544
"error.expectResult mismatch:\nExpected: %s\nActual: %s\n",
534545
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
@@ -1110,7 +1110,7 @@ test_check_event (test_t *test,
11101110
actual_val = bson_val_from_bson (actual->command);
11111111

11121112
if (!entity_map_match (
1113-
test->entity_map, expected_val, actual_val, true, error)) {
1113+
test->entity_map, expected_val, actual_val, false, error)) {
11141114
bson_val_destroy (expected_val);
11151115
bson_val_destroy (actual_val);
11161116
goto done;
@@ -1141,7 +1141,7 @@ test_check_event (test_t *test,
11411141
bson_val_t *expected_val = bson_val_from_bson (expected_reply);
11421142
bson_val_t *actual_val = bson_val_from_bson (actual->reply);
11431143
if (!entity_map_match (
1144-
test->entity_map, expected_val, actual_val, true, error)) {
1144+
test->entity_map, expected_val, actual_val, false, error)) {
11451145
bson_val_destroy (expected_val);
11461146
bson_val_destroy (actual_val);
11471147
goto done;

0 commit comments

Comments
 (0)