From efa69e8716a7bc3ff3a6b39197899dbb9b5a2069 Mon Sep 17 00:00:00 2001 From: PatersonProjects Date: Thu, 7 May 2026 15:32:19 -0700 Subject: [PATCH 1/5] New tests for $or operator Signed-off-by: PatersonProjects --- .../logical/or/test_or_argument_handling.py | 104 ++++++ .../logical/or/test_or_command_contexts.py | 117 ++++++ .../query/logical/or/test_or_data_types.py | 345 ++++++++++++++++++ .../query/logical/or/test_or_edge_cases.py | 107 ++++++ .../query/logical/or/test_or_errors.py | 153 ++++++++ .../query/logical/or/test_or_field_lookup.py | 89 +++++ 6 files changed, 915 insertions(+) create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_errors.py create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_field_lookup.py diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py new file mode 100644 index 00000000..c7fedcf8 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py @@ -0,0 +1,104 @@ +""" +Tests for $or argument handling. + +Tests argument count variations, valid argument patterns, and deduplication +behavior when multiple clauses match the same document. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( + QueryTestCase, +) +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +DOCS = [ + {"_id": 1, "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, + {"_id": 2, "a": 2, "b": 2, "c": 3, "d": 4, "e": 5}, + {"_id": 3, "a": 1, "b": 3, "c": 3, "d": 4, "e": 5}, +] + +SUCCESS_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="single_expression", + filter={"$or": [{"a": 1}]}, + doc=DOCS, + expected=[ + {"_id": 1, "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, + {"_id": 3, "a": 1, "b": 3, "c": 3, "d": 4, "e": 5}, + ], + msg="$or with single expression matches documents satisfying it", + ), + QueryTestCase( + id="two_expressions", + filter={"$or": [{"a": 1}, {"a": 2}]}, + doc=DOCS, + expected=DOCS, + msg="$or with two expressions matches documents satisfying either", + ), + QueryTestCase( + id="five_expressions", + filter={"$or": [{"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}, {"e": 5}]}, + doc=DOCS, + expected=DOCS, + msg="$or with five expressions matches documents satisfying any", + ), + QueryTestCase( + id="empty_object_expression", + filter={"$or": [{}]}, + doc=DOCS, + expected=DOCS, + msg="$or with empty object matches all documents", + ), + QueryTestCase( + id="duplicate_same_field_same_value", + filter={"$or": [{"a": 1}, {"a": 1}, {"a": 1}]}, + doc=DOCS, + expected=[ + {"_id": 1, "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, + {"_id": 3, "a": 1, "b": 3, "c": 3, "d": 4, "e": 5}, + ], + msg="$or with repeated identical clauses does not duplicate results", + ), + QueryTestCase( + id="mutually_exclusive", + filter={"$or": [{"a": 1}, {"a": 2}]}, + doc=DOCS, + expected=DOCS, + msg="$or with mutually exclusive clauses matches union", + ), + QueryTestCase( + id="large_array_100_expressions", + filter={"$or": [{"a": 1}] * 100}, + doc=DOCS, + expected=[ + {"_id": 1, "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, + {"_id": 3, "a": 1, "b": 3, "c": 3, "d": 4, "e": 5}, + ], + msg="$or with 100 expressions does not hit a limit", + ), + QueryTestCase( + id="dedup_overlapping_clauses", + filter={"$or": [{"a": {"$gt": 0}}, {"a": {"$lt": 10}}]}, + doc=[{"_id": 1, "a": 5}], + expected=[{"_id": 1, "a": 5}], + msg="$or does not return duplicates when multiple clauses match same doc", + ), + QueryTestCase( + id="dedup_all_match_all", + filter={"$or": [{"a": {"$gte": 1}}, {"b": {"$gte": 2}}]}, + doc=DOCS, + expected=DOCS, + msg="$or where all clauses match all documents returns all without duplicates", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(SUCCESS_TESTS)) +def test_or_argument_success(collection, test): + """Test $or with valid argument variations.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg, ignore_doc_order=True) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py new file mode 100644 index 00000000..127a0b0b --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py @@ -0,0 +1,117 @@ +""" +Tests for $or in various command contexts. + +Tests $or with $expr, and in find, update, delete, findAndModify, +count, and distinct command filters. +""" + +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command + +DOCS = [ + {"_id": 1, "a": 5, "b": 3, "c": 1}, + {"_id": 2, "a": 1, "b": 3, "c": 2}, + {"_id": 3, "a": 5, "b": 3, "c": 3}, +] + + +def test_or_with_expr(collection): + """Test $or containing $expr clause.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + { + "find": collection.name, + "filter": {"$or": [{"$expr": {"$gt": ["$a", "$b"]}}, {"c": 2}]}, + }, + ) + assertSuccess( + result, + [DOCS[0], DOCS[1], DOCS[2]], + msg="$or with $expr matches docs where a > b or c=2", + ignore_doc_order=True, + ) + + +def test_or_inside_expr(collection): + """Test $or inside $expr.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + { + "find": collection.name, + "filter": {"$expr": {"$or": [{"$gt": ["$a", 4]}, {"$eq": ["$c", 2]}]}}, + }, + ) + assertSuccess( + result, + [DOCS[0], DOCS[1], DOCS[2]], + msg="$or inside $expr matches docs where a > 4 or c == 2", + ignore_doc_order=True, + ) + + +def test_or_in_update_filter(collection): + """Test $or in update command filter.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + { + "update": collection.name, + "updates": [ + {"q": {"$or": [{"a": 5}, {"c": 2}]}, "u": {"$set": {"x": 1}}, "multi": True} + ], + }, + ) + assertSuccess( + result, + {"n": 3, "nModified": 3, "ok": 1.0}, + raw_res=True, + msg="$or in update filter updates correct docs", + ) + + +def test_or_in_delete_filter(collection): + """Test $or in delete command filter.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + { + "delete": collection.name, + "deletes": [{"q": {"$or": [{"c": 1}, {"c": 3}]}, "limit": 0}], + }, + ) + assertSuccess( + result, {"n": 2, "ok": 1.0}, raw_res=True, msg="$or in delete filter deletes correct docs" + ) + + +def test_or_in_count(collection): + """Test $or in count command filter.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + {"count": collection.name, "query": {"$or": [{"a": 5}, {"c": 2}]}}, + ) + assertSuccess( + result, {"n": 3, "ok": 1.0}, raw_res=True, msg="$or in count returns correct count" + ) + + +def test_or_in_distinct(collection): + """Test $or in distinct command filter.""" + collection.insert_many(DOCS) + result = execute_command( + collection, + { + "distinct": collection.name, + "key": "c", + "query": {"$or": [{"a": 5}]}, + }, + ) + assertSuccess( + result, + {"values": [1, 3], "ok": 1.0}, + raw_res=True, + msg="$or in distinct returns correct values", + ) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py new file mode 100644 index 00000000..f3d4ea71 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py @@ -0,0 +1,345 @@ +""" +Tests for $or data type coverage and BSON type distinction. + +Tests that $or correctly matches documents with various BSON types +(including Regex, MinKey, MaxKey, Code), respects type distinctions +(e.g., bool vs int, null vs missing, 0.0 vs -0.0), and handles +special values (Infinity, NaN). +""" + +from datetime import datetime, timezone + +import pytest +from bson import Binary, Code, Decimal128, Int64, MaxKey, MinKey, ObjectId, Regex, Timestamp + +from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( + QueryTestCase, +) +from documentdb_tests.framework.assertions import assertSuccess, assertSuccessNaN +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params +from documentdb_tests.framework.test_constants import ( + DECIMAL128_INFINITY, + DECIMAL128_NAN, + FLOAT_INFINITY, + FLOAT_NAN, + FLOAT_NEGATIVE_INFINITY, +) + +TYPE_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="int32", + filter={"$or": [{"val": 42}]}, + doc=[{"_id": 1, "val": 42}, {"_id": 2, "val": 99}], + expected=[{"_id": 1, "val": 42}], + msg="$or matches int32 value", + ), + QueryTestCase( + id="int64", + filter={"$or": [{"val": Int64(123456789012345)}]}, + doc=[{"_id": 1, "val": Int64(123456789012345)}, {"_id": 2, "val": 0}], + expected=[{"_id": 1, "val": Int64(123456789012345)}], + msg="$or matches int64 value", + ), + QueryTestCase( + id="double", + filter={"$or": [{"val": 3.14}]}, + doc=[{"_id": 1, "val": 3.14}, {"_id": 2, "val": 2.71}], + expected=[{"_id": 1, "val": 3.14}], + msg="$or matches double value", + ), + QueryTestCase( + id="decimal128", + filter={"$or": [{"val": Decimal128("1.23")}]}, + doc=[{"_id": 1, "val": Decimal128("1.23")}, {"_id": 2, "val": Decimal128("4.56")}], + expected=[{"_id": 1, "val": Decimal128("1.23")}], + msg="$or matches decimal128 value", + ), + QueryTestCase( + id="string", + filter={"$or": [{"val": "hello"}]}, + doc=[{"_id": 1, "val": "hello"}, {"_id": 2, "val": "world"}], + expected=[{"_id": 1, "val": "hello"}], + msg="$or matches string value", + ), + QueryTestCase( + id="bool_true", + filter={"$or": [{"val": True}]}, + doc=[{"_id": 1, "val": True}, {"_id": 2, "val": False}], + expected=[{"_id": 1, "val": True}], + msg="$or matches boolean true", + ), + QueryTestCase( + id="bool_false", + filter={"$or": [{"val": False}]}, + doc=[{"_id": 1, "val": True}, {"_id": 2, "val": False}], + expected=[{"_id": 2, "val": False}], + msg="$or matches boolean false", + ), + QueryTestCase( + id="date", + filter={"$or": [{"val": datetime(2024, 1, 1, tzinfo=timezone.utc)}]}, + doc=[ + {"_id": 1, "val": datetime(2024, 1, 1, tzinfo=timezone.utc)}, + {"_id": 2, "val": datetime(2025, 1, 1, tzinfo=timezone.utc)}, + ], + expected=[{"_id": 1, "val": datetime(2024, 1, 1, tzinfo=timezone.utc)}], + msg="$or matches date value", + ), + QueryTestCase( + id="null", + filter={"$or": [{"val": None}]}, + doc=[{"_id": 1, "val": None}, {"_id": 2, "val": 1}], + expected=[{"_id": 1, "val": None}], + msg="$or matches null value", + ), + QueryTestCase( + id="object", + filter={"$or": [{"val": {"x": 1}}]}, + doc=[{"_id": 1, "val": {"x": 1}}, {"_id": 2, "val": {"x": 2}}], + expected=[{"_id": 1, "val": {"x": 1}}], + msg="$or matches embedded object", + ), + QueryTestCase( + id="array", + filter={"$or": [{"val": [1, 2, 3]}]}, + doc=[{"_id": 1, "val": [1, 2, 3]}, {"_id": 2, "val": [4, 5]}], + expected=[{"_id": 1, "val": [1, 2, 3]}], + msg="$or matches array value", + ), + QueryTestCase( + id="objectid", + filter={"$or": [{"val": ObjectId("507f1f77bcf86cd799439011")}]}, + doc=[ + {"_id": 1, "val": ObjectId("507f1f77bcf86cd799439011")}, + {"_id": 2, "val": ObjectId("507f1f77bcf86cd799439012")}, + ], + expected=[{"_id": 1, "val": ObjectId("507f1f77bcf86cd799439011")}], + msg="$or matches ObjectId value", + ), + QueryTestCase( + id="timestamp", + filter={"$or": [{"val": Timestamp(1, 1)}]}, + doc=[{"_id": 1, "val": Timestamp(1, 1)}, {"_id": 2, "val": Timestamp(2, 1)}], + expected=[{"_id": 1, "val": Timestamp(1, 1)}], + msg="$or matches Timestamp value", + ), + QueryTestCase( + id="binary", + filter={"$or": [{"val": Binary(b"\x01\x02")}]}, + doc=[{"_id": 1, "val": Binary(b"\x01\x02")}, {"_id": 2, "val": Binary(b"\x03")}], + expected=[{"_id": 1, "val": b"\x01\x02"}], + msg="$or matches Binary value", + ), + QueryTestCase( + id="regex", + filter={"$or": [{"val": Regex("^hello")}]}, + doc=[{"_id": 1, "val": "hello world"}, {"_id": 2, "val": "world"}], + expected=[{"_id": 1, "val": "hello world"}], + msg="$or matches Regex value", + ), + QueryTestCase( + id="minkey", + filter={"$or": [{"val": MinKey()}]}, + doc=[{"_id": 1, "val": MinKey()}, {"_id": 2, "val": 1}], + expected=[{"_id": 1, "val": MinKey()}], + msg="$or matches MinKey value", + ), + QueryTestCase( + id="maxkey", + filter={"$or": [{"val": MaxKey()}]}, + doc=[{"_id": 1, "val": MaxKey()}, {"_id": 2, "val": 1}], + expected=[{"_id": 1, "val": MaxKey()}], + msg="$or matches MaxKey value", + ), + QueryTestCase( + id="javascript_code", + filter={"$or": [{"val": Code("function() { return true; }")}]}, + doc=[ + {"_id": 1, "val": Code("function() { return true; }")}, + {"_id": 2, "val": Code("function() { return false; }")}, + ], + expected=[{"_id": 1, "val": Code("function() { return true; }")}], + msg="$or matches JavaScript Code value", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(TYPE_TESTS)) +def test_or_data_type(collection, test): + """Test $or matching with various BSON data types.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg) + + +BSON_DISTINCTION_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="false_not_zero", + filter={"$or": [{"val": False}]}, + doc=[{"_id": 1, "val": 0}], + expected=[], + msg="bool false does not match int 0", + ), + QueryTestCase( + id="zero_not_false", + filter={"$or": [{"val": 0}]}, + doc=[{"_id": 1, "val": False}], + expected=[], + msg="int 0 does not match bool false", + ), + QueryTestCase( + id="true_not_one", + filter={"$or": [{"val": True}]}, + doc=[{"_id": 1, "val": 1}], + expected=[], + msg="bool true does not match int 1", + ), + QueryTestCase( + id="empty_string_not_null", + filter={"$or": [{"val": ""}]}, + doc=[{"_id": 1, "val": None}], + expected=[], + msg="empty string does not match null", + ), + QueryTestCase( + id="numeric_equivalence_int_long", + filter={"$or": [{"val": 1}]}, + doc=[{"_id": 1, "val": Int64(1)}], + expected=[{"_id": 1, "val": Int64(1)}], + msg="int 1 matches long 1 (numeric equivalence)", + ), + QueryTestCase( + id="numeric_equivalence_int_double", + filter={"$or": [{"val": 1.0}]}, + doc=[{"_id": 1, "val": 1}], + expected=[{"_id": 1, "val": 1}], + msg="double 1.0 matches int 1 (numeric equivalence)", + ), + QueryTestCase( + id="numeric_equivalence_int_decimal128", + filter={"$or": [{"val": Decimal128("1")}]}, + doc=[{"_id": 1, "val": 1}], + expected=[{"_id": 1, "val": 1}], + msg="Decimal128('1') matches int 1 (numeric equivalence)", + ), + QueryTestCase( + id="null_matches_missing", + filter={"$or": [{"val": None}]}, + doc=[{"_id": 1}], + expected=[{"_id": 1}], + msg="null query matches document with missing field", + ), + QueryTestCase( + id="null_no_match_non_null", + filter={"$or": [{"val": None}]}, + doc=[{"_id": 1, "val": 1}], + expected=[], + msg="null query does not match non-null field", + ), + QueryTestCase( + id="positive_zero_matches_negative_zero", + filter={"$or": [{"val": 0.0}]}, + doc=[{"_id": 1, "val": -0.0}], + expected=[{"_id": 1, "val": -0.0}], + msg="0.0 matches -0.0 (numeric equivalence)", + ), + QueryTestCase( + id="negative_zero_matches_positive_zero", + filter={"$or": [{"val": -0.0}]}, + doc=[{"_id": 1, "val": 0.0}], + expected=[{"_id": 1, "val": 0.0}], + msg="-0.0 matches 0.0 (numeric equivalence)", + ), + QueryTestCase( + id="negative_zero_matches_int_zero", + filter={"$or": [{"val": -0.0}]}, + doc=[{"_id": 1, "val": 0}], + expected=[{"_id": 1, "val": 0}], + msg="-0.0 matches int 0 (numeric equivalence)", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(BSON_DISTINCTION_TESTS)) +def test_or_bson_type_distinction(collection, test): + """Test $or respects BSON type distinctions.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg) + + +SPECIAL_VALUE_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="float_infinity", + filter={"$or": [{"val": FLOAT_INFINITY}]}, + doc=[{"_id": 1, "val": FLOAT_INFINITY}, {"_id": 2, "val": 1.0}], + expected=[{"_id": 1, "val": FLOAT_INFINITY}], + msg="$or matches float Infinity", + ), + QueryTestCase( + id="float_neg_infinity", + filter={"$or": [{"val": FLOAT_NEGATIVE_INFINITY}]}, + doc=[{"_id": 1, "val": FLOAT_NEGATIVE_INFINITY}, {"_id": 2, "val": 1.0}], + expected=[{"_id": 1, "val": FLOAT_NEGATIVE_INFINITY}], + msg="$or matches float -Infinity", + ), + QueryTestCase( + id="decimal128_infinity", + filter={"$or": [{"val": DECIMAL128_INFINITY}]}, + doc=[ + {"_id": 1, "val": DECIMAL128_INFINITY}, + {"_id": 2, "val": Decimal128("1")}, + ], + expected=[{"_id": 1, "val": DECIMAL128_INFINITY}], + msg="$or matches Decimal128 Infinity", + ), + QueryTestCase( + id="cross_type_infinity", + filter={"$or": [{"val": FLOAT_INFINITY}]}, + doc=[{"_id": 1, "val": DECIMAL128_INFINITY}, {"_id": 2, "val": 1.0}], + expected=[{"_id": 1, "val": DECIMAL128_INFINITY}], + msg="Float Infinity matches Decimal128 Infinity (numeric equivalence)", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(SPECIAL_VALUE_TESTS)) +def test_or_special_values(collection, test): + """Test $or with Infinity special values.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg) + + +NAN_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="float_nan", + filter={"$or": [{"val": FLOAT_NAN}]}, + doc=[{"_id": 1, "val": FLOAT_NAN}, {"_id": 2, "val": 1.0}], + expected=[{"_id": 1, "val": FLOAT_NAN}], + msg="$or matches float NaN", + ), + QueryTestCase( + id="decimal128_nan", + filter={"$or": [{"val": DECIMAL128_NAN}]}, + doc=[{"_id": 1, "val": DECIMAL128_NAN}, {"_id": 2, "val": Decimal128("1")}], + expected=[{"_id": 1, "val": DECIMAL128_NAN}], + msg="$or matches Decimal128 NaN", + ), + QueryTestCase( + id="cross_type_nan", + filter={"$or": [{"val": FLOAT_NAN}]}, + doc=[{"_id": 1, "val": DECIMAL128_NAN}, {"_id": 2, "val": 1.0}], + expected=[{"_id": 1, "val": DECIMAL128_NAN}], + msg="Float NaN matches Decimal128 NaN", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(NAN_TESTS)) +def test_or_nan_values(collection, test): + """Test $or with NaN values.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccessNaN(result, test.expected, msg=test.msg) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py new file mode 100644 index 00000000..f0dd576e --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py @@ -0,0 +1,107 @@ +""" +Tests for $or edge cases. + +Tests empty collection, no-match, single-document, null/missing field handling, +$exists behavior, and nested $or nesting. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( + QueryTestCase, +) +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +ALL_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="no_clause_matches", + filter={"$or": [{"a": 99}, {"b": 99}]}, + doc=[{"_id": 1, "a": 1, "b": 2}, {"_id": 2, "a": 2, "b": 3}], + expected=[], + msg="$or where no clause matches returns empty", + ), + QueryTestCase( + id="empty_collection", + filter={"$or": [{"a": 1}, {"b": 2}]}, + doc=[], + expected=[], + msg="$or on empty collection returns empty", + ), + QueryTestCase( + id="single_document_match", + filter={"$or": [{"a": 1}, {"b": 99}]}, + doc=[{"_id": 1, "a": 1, "b": 2}], + expected=[{"_id": 1, "a": 1, "b": 2}], + msg="$or on single-document collection matches correctly", + ), + QueryTestCase( + id="single_document_no_match", + filter={"$or": [{"a": 99}, {"b": 99}]}, + doc=[{"_id": 1, "a": 1, "b": 2}], + expected=[], + msg="$or on single-document collection returns empty when not matched", + ), + QueryTestCase( + id="null_field_matches", + filter={"$or": [{"a": None}, {"b": 1}]}, + doc=[{"_id": 1, "a": None}, {"_id": 2, "b": 1}, {"_id": 3, "a": 1}], + expected=[{"_id": 1, "a": None}, {"_id": 2, "b": 1}], + msg="$or with null clause matches null field", + ), + QueryTestCase( + id="missing_field_matches_null", + filter={"$or": [{"a": None}, {"b": 1}]}, + doc=[{"_id": 1}, {"_id": 2, "b": 1}, {"_id": 3, "a": 1}], + expected=[{"_id": 1}, {"_id": 2, "b": 1}], + msg="$or with null clause matches missing field", + ), + QueryTestCase( + id="exists_true_matches", + filter={"$or": [{"a": {"$exists": True}}, {"b": 1}]}, + doc=[{"_id": 1, "a": 1}, {"_id": 2, "b": 1}, {"_id": 3, "c": 1}], + expected=[{"_id": 1, "a": 1}, {"_id": 2, "b": 1}], + msg="$or with $exists:true matches docs with field present", + ), + QueryTestCase( + id="exists_true_no_match", + filter={"$or": [{"a": {"$exists": True}}, {"b": 1}]}, + doc=[{"_id": 1, "c": 1}], + expected=[], + msg="$or with $exists:true does not match when no clause satisfied", + ), + QueryTestCase( + id="nested_or", + filter={"$or": [{"$or": [{"a": 1}, {"b": 2}]}, {"c": 3}]}, + doc=[ + {"_id": 1, "a": 1}, + {"_id": 2, "b": 2}, + {"_id": 3, "c": 3}, + {"_id": 4, "d": 4}, + ], + expected=[{"_id": 1, "a": 1}, {"_id": 2, "b": 2}, {"_id": 3, "c": 3}], + msg="Nested $or matches documents satisfying any inner or outer clause", + ), + QueryTestCase( + id="three_level_nesting", + filter={"$or": [{"$or": [{"$or": [{"a": 1}]}, {"b": 2}]}, {"c": 3}]}, + doc=[ + {"_id": 1, "a": 1}, + {"_id": 2, "b": 2}, + {"_id": 3, "c": 3}, + {"_id": 4, "d": 4}, + ], + expected=[{"_id": 1, "a": 1}, {"_id": 2, "b": 2}, {"_id": 3, "c": 3}], + msg="Three-level nested $or matches correctly", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(ALL_TESTS)) +def test_or_edge_cases(collection, test): + """Test $or edge cases.""" + if test.doc: + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg, ignore_doc_order=True) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_errors.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_errors.py new file mode 100644 index 00000000..6225fe0a --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_errors.py @@ -0,0 +1,153 @@ +""" +Tests for $or error cases and invalid argument handling. + +Tests that $or returns correct error codes for malformed expressions, +invalid argument types, and invalid element types at various positions. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( + QueryTestCase, +) +from documentdb_tests.framework.assertions import assertFailureCode +from documentdb_tests.framework.error_codes import BAD_VALUE_ERROR +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +ERROR_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="empty_array", + filter={"$or": []}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with empty array errors", + ), + QueryTestCase( + id="not_array_object", + filter={"$or": {"a": 1}}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with object instead of array errors", + ), + QueryTestCase( + id="not_array_int", + filter={"$or": 1}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with integer errors", + ), + QueryTestCase( + id="not_array_string", + filter={"$or": "string"}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with string errors", + ), + QueryTestCase( + id="not_array_null", + filter={"$or": None}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with null errors", + ), + QueryTestCase( + id="element_int", + filter={"$or": [1]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with integer element errors", + ), + QueryTestCase( + id="element_string", + filter={"$or": ["string"]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with string element errors", + ), + QueryTestCase( + id="element_null", + filter={"$or": [None]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with null element errors", + ), + QueryTestCase( + id="element_bool", + filter={"$or": [True]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with boolean element errors", + ), + QueryTestCase( + id="non_object_position_0", + filter={"$or": [1, {"a": 1}]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with non-object at position 0 errors", + ), + QueryTestCase( + id="non_object_position_1", + filter={"$or": [{"a": 1}, 1]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with non-object at position 1 errors", + ), + QueryTestCase( + id="non_object_position_2", + filter={"$or": [{"a": 1}, {"b": 2}, 1]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with non-object at position 2 errors", + ), + QueryTestCase( + id="null_position_0", + filter={"$or": [None, {"a": 1}]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with null at position 0 errors", + ), + QueryTestCase( + id="null_position_1", + filter={"$or": [{"a": 1}, None]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with null at position 1 errors", + ), + QueryTestCase( + id="string_position_0", + filter={"$or": ["x", {"a": 1}]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with string at position 0 errors", + ), + QueryTestCase( + id="array_position_1", + filter={"$or": [{"a": 1}, [1, 2]]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with array at position 1 errors", + ), + QueryTestCase( + id="all_non_objects", + filter={"$or": [1, 2, 3]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with all non-object elements errors", + ), + QueryTestCase( + id="unknown_operator", + filter={"$or": [{"$invalidOp": 1}]}, + expected=None, + error_code=BAD_VALUE_ERROR, + msg="$or with unknown query operator errors", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(ERROR_TESTS)) +def test_or_errors(collection, test): + """Test $or with invalid arguments returns correct error code.""" + collection.insert_one({"_id": 1, "a": 1}) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertFailureCode(result, test.error_code, msg=test.msg) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_field_lookup.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_field_lookup.py new file mode 100644 index 00000000..246d0871 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_field_lookup.py @@ -0,0 +1,89 @@ +""" +Tests for $or with array and embedded document field lookups. + +Tests dot notation, array element matching, and deeply nested paths. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( + QueryTestCase, +) +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +ALL_TESTS: list[QueryTestCase] = [ + QueryTestCase( + id="array_element_match", + filter={"$or": [{"arr": 1}, {"arr": 2}]}, + doc=[ + {"_id": 1, "arr": [1, 3]}, + {"_id": 2, "arr": [2, 4]}, + {"_id": 3, "arr": [5, 6]}, + ], + expected=[{"_id": 1, "arr": [1, 3]}, {"_id": 2, "arr": [2, 4]}], + msg="$or matches docs where array contains either value", + ), + QueryTestCase( + id="dot_notation_array_index", + filter={"$or": [{"arr.0": 1}, {"arr.1": 2}]}, + doc=[ + {"_id": 1, "arr": [1, 9]}, + {"_id": 2, "arr": [9, 2]}, + {"_id": 3, "arr": [9, 9]}, + ], + expected=[{"_id": 1, "arr": [1, 9]}, {"_id": 2, "arr": [9, 2]}], + msg="$or with dot notation into array positions", + ), + QueryTestCase( + id="dot_notation_embedded_doc", + filter={"$or": [{"a.b": 1}, {"a.c": 2}]}, + doc=[ + {"_id": 1, "a": {"b": 1, "c": 9}}, + {"_id": 2, "a": {"b": 9, "c": 2}}, + {"_id": 3, "a": {"b": 9, "c": 9}}, + ], + expected=[ + {"_id": 1, "a": {"b": 1, "c": 9}}, + {"_id": 2, "a": {"b": 9, "c": 2}}, + ], + msg="$or with dot notation into embedded document", + ), + QueryTestCase( + id="deeply_nested_paths", + filter={"$or": [{"a.b.c": 1}, {"x.y.z": 2}]}, + doc=[ + {"_id": 1, "a": {"b": {"c": 1}}}, + {"_id": 2, "x": {"y": {"z": 2}}}, + {"_id": 3, "a": {"b": {"c": 9}}}, + ], + expected=[ + {"_id": 1, "a": {"b": {"c": 1}}}, + {"_id": 2, "x": {"y": {"z": 2}}}, + ], + msg="$or with deeply nested dot notation paths", + ), + QueryTestCase( + id="array_of_objects_dot_notation", + filter={"$or": [{"a.b": 1}, {"a.c": 2}]}, + doc=[ + {"_id": 1, "a": [{"b": 1}, {"c": 9}]}, + {"_id": 2, "a": [{"b": 9}, {"c": 2}]}, + {"_id": 3, "a": [{"b": 9}, {"c": 9}]}, + ], + expected=[ + {"_id": 1, "a": [{"b": 1}, {"c": 9}]}, + {"_id": 2, "a": [{"b": 9}, {"c": 2}]}, + ], + msg="$or with dot notation into array of objects", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(ALL_TESTS)) +def test_or_field_lookup(collection, test): + """Test $or with array and embedded document field lookups.""" + collection.insert_many(test.doc) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg, ignore_doc_order=True) From 74709223142f1948efd60e509af560a331b36849 Mon Sep 17 00:00:00 2001 From: PatersonProjects Date: Thu, 7 May 2026 16:13:26 -0700 Subject: [PATCH 2/5] Removed out of scope tests, moved tests to query level file Rebased to prevent conflict with and tests Signed-off-by: PatersonProjects --- .../logical/or/test_or_command_contexts.py | 117 ------------------ 1 file changed, 117 deletions(-) delete mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py deleted file mode 100644 index 127a0b0b..00000000 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_command_contexts.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -Tests for $or in various command contexts. - -Tests $or with $expr, and in find, update, delete, findAndModify, -count, and distinct command filters. -""" - -from documentdb_tests.framework.assertions import assertSuccess -from documentdb_tests.framework.executor import execute_command - -DOCS = [ - {"_id": 1, "a": 5, "b": 3, "c": 1}, - {"_id": 2, "a": 1, "b": 3, "c": 2}, - {"_id": 3, "a": 5, "b": 3, "c": 3}, -] - - -def test_or_with_expr(collection): - """Test $or containing $expr clause.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - { - "find": collection.name, - "filter": {"$or": [{"$expr": {"$gt": ["$a", "$b"]}}, {"c": 2}]}, - }, - ) - assertSuccess( - result, - [DOCS[0], DOCS[1], DOCS[2]], - msg="$or with $expr matches docs where a > b or c=2", - ignore_doc_order=True, - ) - - -def test_or_inside_expr(collection): - """Test $or inside $expr.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - { - "find": collection.name, - "filter": {"$expr": {"$or": [{"$gt": ["$a", 4]}, {"$eq": ["$c", 2]}]}}, - }, - ) - assertSuccess( - result, - [DOCS[0], DOCS[1], DOCS[2]], - msg="$or inside $expr matches docs where a > 4 or c == 2", - ignore_doc_order=True, - ) - - -def test_or_in_update_filter(collection): - """Test $or in update command filter.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - { - "update": collection.name, - "updates": [ - {"q": {"$or": [{"a": 5}, {"c": 2}]}, "u": {"$set": {"x": 1}}, "multi": True} - ], - }, - ) - assertSuccess( - result, - {"n": 3, "nModified": 3, "ok": 1.0}, - raw_res=True, - msg="$or in update filter updates correct docs", - ) - - -def test_or_in_delete_filter(collection): - """Test $or in delete command filter.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - { - "delete": collection.name, - "deletes": [{"q": {"$or": [{"c": 1}, {"c": 3}]}, "limit": 0}], - }, - ) - assertSuccess( - result, {"n": 2, "ok": 1.0}, raw_res=True, msg="$or in delete filter deletes correct docs" - ) - - -def test_or_in_count(collection): - """Test $or in count command filter.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - {"count": collection.name, "query": {"$or": [{"a": 5}, {"c": 2}]}}, - ) - assertSuccess( - result, {"n": 3, "ok": 1.0}, raw_res=True, msg="$or in count returns correct count" - ) - - -def test_or_in_distinct(collection): - """Test $or in distinct command filter.""" - collection.insert_many(DOCS) - result = execute_command( - collection, - { - "distinct": collection.name, - "key": "c", - "query": {"$or": [{"a": 5}]}, - }, - ) - assertSuccess( - result, - {"values": [1, 3], "ok": 1.0}, - raw_res=True, - msg="$or in distinct returns correct values", - ) From c30de80d276b10a4dcf558dd95dc0b3e9b9053ab Mon Sep 17 00:00:00 2001 From: PatersonProjects Date: Fri, 8 May 2026 11:05:00 -0700 Subject: [PATCH 3/5] Moved tests, renamed for clarity Signed-off-by: PatersonProjects --- .../operator/query/logical/or/__init__.py | 0 .../logical/or/test_or_argument_handling.py | 4 +-- .../query/logical/or/test_or_data_types.py | 25 +++++-------------- 3 files changed, 8 insertions(+), 21 deletions(-) create mode 100644 documentdb_tests/compatibility/tests/core/operator/query/logical/or/__init__.py diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/__init__.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py index c7fedcf8..83ca821d 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py @@ -80,14 +80,14 @@ msg="$or with 100 expressions does not hit a limit", ), QueryTestCase( - id="dedup_overlapping_clauses", + id="no_duplicate_results_overlapping_clauses", filter={"$or": [{"a": {"$gt": 0}}, {"a": {"$lt": 10}}]}, doc=[{"_id": 1, "a": 5}], expected=[{"_id": 1, "a": 5}], msg="$or does not return duplicates when multiple clauses match same doc", ), QueryTestCase( - id="dedup_all_match_all", + id="no_duplicate_results_all_match_all", filter={"$or": [{"a": {"$gte": 1}}, {"b": {"$gte": 2}}]}, doc=DOCS, expected=DOCS, diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py index f3d4ea71..00117adf 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py @@ -165,14 +165,6 @@ ] -@pytest.mark.parametrize("test", pytest_params(TYPE_TESTS)) -def test_or_data_type(collection, test): - """Test $or matching with various BSON data types.""" - collection.insert_many(test.doc) - result = execute_command(collection, {"find": collection.name, "filter": test.filter}) - assertSuccess(result, test.expected, msg=test.msg) - - BSON_DISTINCTION_TESTS: list[QueryTestCase] = [ QueryTestCase( id="false_not_zero", @@ -261,14 +253,6 @@ def test_or_data_type(collection, test): ] -@pytest.mark.parametrize("test", pytest_params(BSON_DISTINCTION_TESTS)) -def test_or_bson_type_distinction(collection, test): - """Test $or respects BSON type distinctions.""" - collection.insert_many(test.doc) - result = execute_command(collection, {"find": collection.name, "filter": test.filter}) - assertSuccess(result, test.expected, msg=test.msg) - - SPECIAL_VALUE_TESTS: list[QueryTestCase] = [ QueryTestCase( id="float_infinity", @@ -304,9 +288,12 @@ def test_or_bson_type_distinction(collection, test): ] -@pytest.mark.parametrize("test", pytest_params(SPECIAL_VALUE_TESTS)) -def test_or_special_values(collection, test): - """Test $or with Infinity special values.""" +ALL_TESTS = TYPE_TESTS + BSON_DISTINCTION_TESTS + SPECIAL_VALUE_TESTS + + +@pytest.mark.parametrize("test", pytest_params(ALL_TESTS)) +def test_or_data_types(collection, test): + """Test $or data type coverage, BSON type distinctions, and special values.""" collection.insert_many(test.doc) result = execute_command(collection, {"find": collection.name, "filter": test.filter}) assertSuccess(result, test.expected, msg=test.msg) From 814f94818e7cef75249bd2cc9628b0254431e23c Mon Sep 17 00:00:00 2001 From: PatersonProjects Date: Fri, 8 May 2026 12:23:20 -0700 Subject: [PATCH 4/5] Removed AssertSuccessNaN Signed-off-by: PatersonProjects --- .../query/logical/or/test_or_data_types.py | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py index 00117adf..e44f5175 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py @@ -15,7 +15,7 @@ from documentdb_tests.compatibility.tests.core.operator.query.utils.query_test_case import ( QueryTestCase, ) -from documentdb_tests.framework.assertions import assertSuccess, assertSuccessNaN +from documentdb_tests.framework.assertions import assertSuccess from documentdb_tests.framework.executor import execute_command from documentdb_tests.framework.parametrize import pytest_params from documentdb_tests.framework.test_constants import ( @@ -288,23 +288,12 @@ ] -ALL_TESTS = TYPE_TESTS + BSON_DISTINCTION_TESTS + SPECIAL_VALUE_TESTS - - -@pytest.mark.parametrize("test", pytest_params(ALL_TESTS)) -def test_or_data_types(collection, test): - """Test $or data type coverage, BSON type distinctions, and special values.""" - collection.insert_many(test.doc) - result = execute_command(collection, {"find": collection.name, "filter": test.filter}) - assertSuccess(result, test.expected, msg=test.msg) - - NAN_TESTS: list[QueryTestCase] = [ QueryTestCase( id="float_nan", filter={"$or": [{"val": FLOAT_NAN}]}, doc=[{"_id": 1, "val": FLOAT_NAN}, {"_id": 2, "val": 1.0}], - expected=[{"_id": 1, "val": FLOAT_NAN}], + expected=[{"_id": 1, "val": pytest.approx(FLOAT_NAN, nan_ok=True)}], msg="$or matches float NaN", ), QueryTestCase( @@ -324,9 +313,12 @@ def test_or_data_types(collection, test): ] -@pytest.mark.parametrize("test", pytest_params(NAN_TESTS)) -def test_or_nan_values(collection, test): - """Test $or with NaN values.""" +ALL_TESTS = TYPE_TESTS + BSON_DISTINCTION_TESTS + SPECIAL_VALUE_TESTS + NAN_TESTS + + +@pytest.mark.parametrize("test", pytest_params(ALL_TESTS)) +def test_or_data_types(collection, test): + """Test $or data type coverage, BSON type distinctions, and special values.""" collection.insert_many(test.doc) result = execute_command(collection, {"find": collection.name, "filter": test.filter}) - assertSuccessNaN(result, test.expected, msg=test.msg) + assertSuccess(result, test.expected, msg=test.msg) From 8a5166740263146546ec3a728f9b477fcccfb12a Mon Sep 17 00:00:00 2001 From: PatersonProjects Date: Fri, 8 May 2026 14:40:18 -0700 Subject: [PATCH 5/5] Removed Duplicate Test Cases Signed-off-by: PatersonProjects --- .../operator/query/logical/or/test_or_argument_handling.py | 7 ------- .../core/operator/query/logical/or/test_or_data_types.py | 6 +++--- .../core/operator/query/logical/or/test_or_edge_cases.py | 7 ------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py index 83ca821d..d877ed5d 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_argument_handling.py @@ -62,13 +62,6 @@ ], msg="$or with repeated identical clauses does not duplicate results", ), - QueryTestCase( - id="mutually_exclusive", - filter={"$or": [{"a": 1}, {"a": 2}]}, - doc=DOCS, - expected=DOCS, - msg="$or with mutually exclusive clauses matches union", - ), QueryTestCase( id="large_array_100_expressions", filter={"$or": [{"a": 1}] * 100}, diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py index e44f5175..712a87f6 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_data_types.py @@ -217,10 +217,10 @@ ), QueryTestCase( id="null_matches_missing", - filter={"$or": [{"val": None}]}, - doc=[{"_id": 1}], + filter={"$or": [{"a": None}]}, + doc=[{"_id": 1}, {"_id": 2, "a": 1}], expected=[{"_id": 1}], - msg="null query matches document with missing field", + msg="$or with null clause matches missing field", ), QueryTestCase( id="null_no_match_non_null", diff --git a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py index f0dd576e..1f52d31e 100644 --- a/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py +++ b/documentdb_tests/compatibility/tests/core/operator/query/logical/or/test_or_edge_cases.py @@ -50,13 +50,6 @@ expected=[{"_id": 1, "a": None}, {"_id": 2, "b": 1}], msg="$or with null clause matches null field", ), - QueryTestCase( - id="missing_field_matches_null", - filter={"$or": [{"a": None}, {"b": 1}]}, - doc=[{"_id": 1}, {"_id": 2, "b": 1}, {"_id": 3, "a": 1}], - expected=[{"_id": 1}, {"_id": 2, "b": 1}], - msg="$or with null clause matches missing field", - ), QueryTestCase( id="exists_true_matches", filter={"$or": [{"a": {"$exists": True}}, {"b": 1}]},