From 913a1aef8d66e2c8cb9a17d29692ecef6c705f63 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 16 Jun 2026 12:41:36 -0700 Subject: [PATCH 1/7] inital generated tests Signed-off-by: Alina (Xi) Li --- .../diagnostic/commands/top/__init__.py | 0 .../top/test_top_argument_handling.py | 140 ++++++++++++ .../commands/top/test_top_consistency.py | 211 +++++++++++++++++ .../commands/top/test_top_core_behavior.py | 213 ++++++++++++++++++ .../commands/top/test_top_errors.py | 69 ++++++ .../top/test_top_response_structure.py | 91 ++++++++ 6 files changed, 724 insertions(+) create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/__init__.py create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py create mode 100644 documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/__init__.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py new file mode 100644 index 000000000..0deb75a0b --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py @@ -0,0 +1,140 @@ +"""Tests for top command argument handling. + +Validates that top accepts any BSON type as its argument value and +handles unrecognized fields. +""" + +from datetime import datetime, timezone + +import pytest +from bson import Binary, Code, Decimal128, Int64, MaxKey, MinKey, ObjectId, Regex, Timestamp + +from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import ( + DiagnosticTestCase, +) +from documentdb_tests.framework.assertions import assertProperties +from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params +from documentdb_tests.framework.property_checks import Eq + +pytestmark = pytest.mark.admin + + +# Property [BSON Type Acceptance]: top accepts any non-deprecated BSON type as command value. +ARGUMENT_TYPE_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "int_1", command={"top": 1}, checks={"ok": Eq(1.0)}, msg="Should accept int 1" + ), + DiagnosticTestCase( + "int_0", command={"top": 0}, checks={"ok": Eq(1.0)}, msg="Should accept int 0" + ), + DiagnosticTestCase( + "int_neg1", command={"top": -1}, checks={"ok": Eq(1.0)}, msg="Should accept int -1" + ), + DiagnosticTestCase( + "bool_true", command={"top": True}, checks={"ok": Eq(1.0)}, msg="Should accept true" + ), + DiagnosticTestCase( + "bool_false", + command={"top": False}, + checks={"ok": Eq(1.0)}, + msg="Should accept false", + ), + DiagnosticTestCase( + "string", command={"top": "hello"}, checks={"ok": Eq(1.0)}, msg="Should accept string" + ), + DiagnosticTestCase( + "null", command={"top": None}, checks={"ok": Eq(1.0)}, msg="Should accept null" + ), + DiagnosticTestCase( + "empty_object", + command={"top": {}}, + checks={"ok": Eq(1.0)}, + msg="Should accept empty object", + ), + DiagnosticTestCase( + "empty_array", + command={"top": []}, + checks={"ok": Eq(1.0)}, + msg="Should accept empty array", + ), + DiagnosticTestCase( + "double", command={"top": 1.5}, checks={"ok": Eq(1.0)}, msg="Should accept double" + ), + DiagnosticTestCase( + "int64", command={"top": Int64(1)}, checks={"ok": Eq(1.0)}, msg="Should accept int64" + ), + DiagnosticTestCase( + "decimal128", + command={"top": Decimal128("1")}, + checks={"ok": Eq(1.0)}, + msg="Should accept decimal128", + ), + DiagnosticTestCase( + "decimal128_nan", + command={"top": Decimal128("NaN")}, + checks={"ok": Eq(1.0)}, + msg="Should accept decimal128 NaN", + ), + DiagnosticTestCase( + "infinity", + command={"top": float("inf")}, + checks={"ok": Eq(1.0)}, + msg="Should accept infinity", + ), + DiagnosticTestCase( + "date", + command={"top": datetime(2024, 1, 1, tzinfo=timezone.utc)}, + checks={"ok": Eq(1.0)}, + msg="Should accept date", + ), + DiagnosticTestCase( + "binData", + command={"top": Binary(b"")}, + checks={"ok": Eq(1.0)}, + msg="Should accept binData", + ), + DiagnosticTestCase( + "objectId", + command={"top": ObjectId()}, + checks={"ok": Eq(1.0)}, + msg="Should accept objectId", + ), + DiagnosticTestCase( + "regex", + command={"top": Regex("test")}, + checks={"ok": Eq(1.0)}, + msg="Should accept regex", + ), + DiagnosticTestCase( + "timestamp", + command={"top": Timestamp(0, 0)}, + checks={"ok": Eq(1.0)}, + msg="Should accept timestamp", + ), + DiagnosticTestCase( + "minKey", + command={"top": MinKey()}, + checks={"ok": Eq(1.0)}, + msg="Should accept minKey", + ), + DiagnosticTestCase( + "maxKey", + command={"top": MaxKey()}, + checks={"ok": Eq(1.0)}, + msg="Should accept maxKey", + ), + DiagnosticTestCase( + "code", + command={"top": Code("function(){}")}, + checks={"ok": Eq(1.0)}, + msg="Should accept JavaScript code", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(ARGUMENT_TYPE_TESTS)) +def test_top_argument_types(collection, test): + """Test that top accepts various BSON types as argument value.""" + result = execute_admin_command(collection, test.command) + assertProperties(result, test.checks, msg=test.msg, raw_res=True) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py new file mode 100644 index 000000000..445567e54 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -0,0 +1,211 @@ +"""Tests for top command consistency, visibility, and special collection types. + +Validates idempotency, namespace visibility, format, admin database requirement, +and behavior with capped collections and views. +""" + +import pytest + +from documentdb_tests.framework.assertions import ( + assertFailureCode, + assertProperties, + assertSuccessPartial, +) +from documentdb_tests.framework.error_codes import UNAUTHORIZED_ERROR +from documentdb_tests.framework.executor import execute_admin_command, execute_command +from documentdb_tests.framework.property_checks import Exists, Gte, IsType + +pytestmark = pytest.mark.admin + + +# ---------- Consistency and Idempotency ---------- + + +def test_top_repeated_calls_succeed(collection): + """Test that calling top 5 times in a row all succeed.""" + for _ in range(5): + result = execute_admin_command(collection, {"top": 1}) + assertSuccessPartial(result, {"ok": 1.0}, msg="Repeated top call should succeed") + + +def test_top_counters_non_decreasing_count(collection): + """Test that total.count is non-decreasing across two consecutive calls.""" + collection.insert_one({"_id": 1}) + ns = f"{collection.database.name}.{collection.name}" + result1 = execute_admin_command(collection, {"top": 1}) + count1 = result1["totals"][ns]["total"]["count"] + result2 = execute_admin_command(collection, {"top": 1}) + ns_data2 = result2["totals"][ns] + assertProperties( + ns_data2, + {"total.count": Gte(count1)}, + msg="total.count should be non-decreasing", + raw_res=True, + ) + + +def test_top_counters_non_decreasing_time(collection): + """Test that total.time is non-decreasing across two consecutive calls.""" + collection.insert_one({"_id": 1}) + ns = f"{collection.database.name}.{collection.name}" + result1 = execute_admin_command(collection, {"top": 1}) + time1 = result1["totals"][ns]["total"]["time"] + result2 = execute_admin_command(collection, {"top": 1}) + ns_data2 = result2["totals"][ns] + assertProperties( + ns_data2, + {"total.time": Gte(time1)}, + msg="total.time should be non-decreasing", + raw_res=True, + ) + + +# ---------- Collection Visibility and Namespace Format ---------- + + +def test_top_newly_created_collection_appears(collection): + """Test that a newly created collection appears in top totals.""" + collection.insert_one({"_id": 1}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + # Look up namespace directly — dotted path traversal can't handle keys with dots. + ns_data = result["totals"].get(ns) + assertProperties( + {"ns_entry": ns_data}, + {"ns_entry": Exists()}, + msg=f"Namespace {ns} should appear in top totals", + raw_res=True, + ) + + +def test_top_multiple_collections_appear(database_client): + """Test that multiple collections appear in top totals.""" + coll1 = database_client.create_collection("top_multi_coll_1") + coll2 = database_client.create_collection("top_multi_coll_2") + coll1.insert_one({"_id": 1}) + coll2.insert_one({"_id": 1}) + result = execute_admin_command(coll1, {"top": 1}) + ns1 = f"{database_client.name}.{coll1.name}" + ns2 = f"{database_client.name}.{coll2.name}" + # Look up namespaces directly — dotted path traversal can't handle keys with dots. + assertProperties( + {"ns1": result["totals"].get(ns1), "ns2": result["totals"].get(ns2)}, + {"ns1": Exists(), "ns2": Exists()}, + msg="Both namespaces should appear in top totals", + raw_res=True, + ) + + +def test_top_namespace_format_db_dot_collection(collection): + """Test that namespace keys in totals are formatted as db.collection.""" + collection.insert_one({"_id": 1}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + # Look up namespace directly — dotted path traversal can't handle keys with dots. + ns_data = result["totals"].get(ns) + assertProperties( + {"ns_entry": ns_data}, + {"ns_entry": Exists()}, + msg=f"Namespace key should be '{ns}' (db.collection format)", + raw_res=True, + ) + + +def test_top_returns_totals_even_with_no_user_operations(collection): + """Test that top returns totals object even with minimal operations.""" + result = execute_admin_command(collection, {"top": 1}) + assertProperties( + result, + {"totals": IsType("object")}, + msg="totals should be an object even with no user operations", + raw_res=True, + ) + + +# ---------- Admin Database Requirement ---------- + + +def test_top_admin_db_succeeds(collection): + """Test that top succeeds when run on admin database.""" + result = execute_admin_command(collection, {"top": 1}) + assertSuccessPartial(result, {"ok": 1.0}, msg="top should succeed on admin db") + + +def test_top_non_admin_db_fails(collection): + """Test that top fails when run on a non-admin database.""" + result = execute_command(collection, {"top": 1}) + assertFailureCode(result, UNAUTHORIZED_ERROR, msg="top should fail on non-admin db") + + +# ---------- System Collections ---------- + + +def test_top_system_collections_have_event_structure(collection): + """Test that system namespaces in totals have the expected event field structure.""" + collection.insert_one({"_id": 1}) + result = execute_admin_command(collection, {"top": 1}) + # Find any system namespace in totals + system_ns = None + for ns_key in result["totals"]: + if ".system." in ns_key or ns_key.startswith("admin.") or ns_key.startswith("local."): + system_ns = ns_key + break + if system_ns is None: + pytest.skip("No system namespace found in top totals") + ns_data = result["totals"][system_ns] + checks = {} + for event in [ + "total", + "readLock", + "writeLock", + "queries", + "getmore", + "insert", + "update", + "remove", + "commands", + ]: + checks[event] = IsType("object") + checks[f"{event}.time"] = Gte(0) + checks[f"{event}.count"] = Gte(0) + assertProperties( + ns_data, + checks, + msg=f"System namespace {system_ns} should have all event fields with time/count", + raw_res=True, + ) + + +# ---------- Special Collection Types ---------- + + +def test_top_tracks_capped_collection(database_client): + """Test that a capped collection appears in top totals with expected structure.""" + coll = database_client.create_collection("top_capped_test", capped=True, size=4096) + coll.insert_one({"_id": 1}) + result = execute_admin_command(coll, {"top": 1}) + ns = f"{database_client.name}.{coll.name}" + # Look up namespace directly — dotted path traversal can't handle keys with dots. + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"total": IsType("object"), "total.time": Gte(0), "total.count": Gte(0)}, + msg="Capped collection should appear in top totals with expected structure", + raw_res=True, + ) + + +def test_top_tracks_view(database_client): + """Test whether a view namespace appears in top totals.""" + source_coll = database_client.create_collection("top_view_source") + source_coll.insert_one({"_id": 1}) + database_client.command("create", "top_view_test", viewOn="top_view_source", pipeline=[]) + result = execute_admin_command(source_coll, {"top": 1}) + # Views may or may not appear in top totals depending on implementation. + # This test documents the actual behavior — verifies totals is present regardless. + assertProperties( + result, + {"totals": IsType("object")}, + msg="top should return totals even when views exist", + raw_res=True, + ) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py new file mode 100644 index 000000000..96ed98c87 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py @@ -0,0 +1,213 @@ +"""Tests for top command core behavior. + +Validates that counters reflect operations and cross-lock consistency invariants hold. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertProperties +from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.property_checks import Gt, Gte + +pytestmark = pytest.mark.admin + + +# ---------- Counter Behavior — Statistics Reflect Operations ---------- + + +def test_top_insert_increments_insert_count(collection): + """Test that inserting documents increments the insert count.""" + collection.insert_many([{"_id": i} for i in range(5)]) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"insert.count": Gte(1)}, + msg="insert.count should be >= 1 after inserts", + raw_res=True, + ) + + +def test_top_insert_increments_writeLock_count(collection): + """Test that inserting documents increments the writeLock count.""" + collection.insert_many([{"_id": i} for i in range(5)]) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"writeLock.count": Gte(1)}, + msg="writeLock.count should be >= 1 after inserts", + raw_res=True, + ) + + +def test_top_query_increments_queries_count(collection): + """Test that running a find query increments the queries count.""" + collection.insert_one({"_id": 1}) + list(collection.find()) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"queries.count": Gte(1)}, msg="queries.count should be >= 1", raw_res=True + ) + + +def test_top_query_increments_readLock_count(collection): + """Test that running a find query increments the readLock count.""" + collection.insert_one({"_id": 1}) + list(collection.find()) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"readLock.count": Gte(1)}, msg="readLock.count should be >= 1", raw_res=True + ) + + +def test_top_update_increments_update_count(collection): + """Test that running an update increments the update count.""" + collection.insert_one({"_id": 1, "a": 1}) + collection.update_one({"_id": 1}, {"$set": {"a": 2}}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"update.count": Gte(1)}, msg="update.count should be >= 1", raw_res=True + ) + + +def test_top_update_increments_writeLock_count(collection): + """Test that running an update increments the writeLock count.""" + collection.insert_one({"_id": 1, "a": 1}) + collection.update_one({"_id": 1}, {"$set": {"a": 2}}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"writeLock.count": Gte(1)}, + msg="writeLock.count should be >= 1 after update", + raw_res=True, + ) + + +def test_top_remove_increments_remove_count(collection): + """Test that running a delete increments the remove count.""" + collection.insert_one({"_id": 1}) + collection.delete_one({"_id": 1}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"remove.count": Gte(1)}, msg="remove.count should be >= 1", raw_res=True + ) + + +def test_top_remove_increments_writeLock_count(collection): + """Test that running a delete increments the writeLock count.""" + collection.insert_one({"_id": 1}) + collection.delete_one({"_id": 1}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"writeLock.count": Gte(1)}, + msg="writeLock.count should be >= 1 after delete", + raw_res=True, + ) + + +def test_top_insert_time_positive_after_inserts(collection): + """Test that insert.time is positive after inserting documents.""" + collection.insert_many([{"_id": i} for i in range(10)]) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"insert.time": Gt(0)}, msg="insert.time should be > 0 after inserts", raw_res=True + ) + + +def test_top_query_time_positive_after_query(collection): + """Test that queries.time is positive after running a find query.""" + collection.insert_one({"_id": 1}) + list(collection.find()) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, {"queries.time": Gt(0)}, msg="queries.time should be > 0 after query", raw_res=True + ) + + +# ---------- Cross-Lock Consistency Invariants ---------- + + +def _setup_mixed_operations(collection): + """Insert, query, update, and delete on the collection to populate all counters.""" + collection.insert_many([{"_id": i, "a": i} for i in range(5)]) + list(collection.find()) + collection.update_one({"_id": 0}, {"$set": {"a": 99}}) + collection.delete_one({"_id": 4}) + + +def test_top_readLock_count_gte_queries_count(collection): + """Test that readLock.count >= queries.count.""" + _setup_mixed_operations(collection) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"readLock.count": Gte(ns_data["queries"]["count"])}, + msg="readLock.count should be >= queries.count", + raw_res=True, + ) + + +def test_top_readLock_time_gte_queries_time(collection): + """Test that readLock.time >= queries.time.""" + _setup_mixed_operations(collection) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties( + ns_data, + {"readLock.time": Gte(ns_data["queries"]["time"])}, + msg="readLock.time should be >= queries.time", + raw_res=True, + ) + + +def test_top_writeLock_count_gte_insert_update_remove(collection): + """Test that writeLock.count >= insert.count + update.count + remove.count.""" + _setup_mixed_operations(collection) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + write_sum = ns_data["insert"]["count"] + ns_data["update"]["count"] + ns_data["remove"]["count"] + assertProperties( + ns_data, + {"writeLock.count": Gte(write_sum)}, + msg="writeLock.count should be >= insert+update+remove count", + raw_res=True, + ) + + +def test_top_writeLock_time_gte_insert_update_remove(collection): + """Test that writeLock.time >= insert.time + update.time + remove.time.""" + _setup_mixed_operations(collection) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + write_sum = ns_data["insert"]["time"] + ns_data["update"]["time"] + ns_data["remove"]["time"] + assertProperties( + ns_data, + {"writeLock.time": Gte(write_sum)}, + msg="writeLock.time should be >= insert+update+remove time", + raw_res=True, + ) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py new file mode 100644 index 000000000..fac5b0fac --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py @@ -0,0 +1,69 @@ +"""Tests for top command error conditions. + +Validates that invalid usages of top produce appropriate errors. +""" + +import pytest + +from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import ( + DiagnosticTestCase, +) +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import COMMAND_NOT_FOUND_ERROR +from documentdb_tests.framework.executor import execute_admin_command, execute_command +from documentdb_tests.framework.parametrize import pytest_params + +pytestmark = pytest.mark.admin + + +# Property [Case Sensitivity]: command names are case-sensitive. +CASE_SENSITIVITY_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id="case_sensitive_Top", + command={"Top": 1}, + use_admin=True, + error_code=COMMAND_NOT_FOUND_ERROR, + msg="'Top' (capitalized) should not be recognized", + ), + DiagnosticTestCase( + id="case_sensitive_TOP", + command={"TOP": 1}, + use_admin=True, + error_code=COMMAND_NOT_FOUND_ERROR, + msg="'TOP' (all caps) should not be recognized", + ), + DiagnosticTestCase( + id="case_sensitive_tOP", + command={"tOP": 1}, + use_admin=True, + error_code=COMMAND_NOT_FOUND_ERROR, + msg="'tOP' (mixed case) should not be recognized", + ), +] + +ERROR_TESTS = CASE_SENSITIVITY_TESTS + + +@pytest.mark.parametrize("test", pytest_params(ERROR_TESTS)) +def test_top_error_conditions(collection, test): + """Test that invalid top command usages produce appropriate errors.""" + if test.use_admin: + result = execute_admin_command(collection, test.command) + else: + result = execute_command(collection, test.command) + assertFailureCode(result, test.error_code, msg=test.msg) + + +def test_top_unrecognized_field(collection): + """Test top behavior with an unrecognized field.""" + result = execute_admin_command(collection, {"top": 1, "unknownField": 1}) + # MongoDB may accept or reject unrecognized fields for top. + # Verify actual behavior — placeholder assertion until run against MongoDB. + assertSuccessPartial(result, {"ok": 1.0}, msg="top with unrecognized field") + + +def test_top_multiple_unrecognized_fields(collection): + """Test top behavior with multiple unrecognized fields.""" + result = execute_admin_command(collection, {"top": 1, "foo": 1, "bar": "baz", "qux": []}) + # Same behavior expectation as single unrecognized field. + assertSuccessPartial(result, {"ok": 1.0}, msg="top with multiple unrecognized fields") diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py new file mode 100644 index 000000000..8a78a0247 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py @@ -0,0 +1,91 @@ +"""Tests for top command response structure. + +Validates top-level response fields and per-collection event field structure. +""" + +import pytest + +from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import ( + DiagnosticTestCase, +) +from documentdb_tests.framework.assertions import assertProperties +from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params +from documentdb_tests.framework.property_checks import Eq, Gte, IsType + +pytestmark = pytest.mark.admin + + +# Property [Top-Level Fields]: top response contains totals and ok fields. +TOP_LEVEL_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id="response_has_totals", + checks={"totals": IsType("object")}, + msg="'totals' field should be an object", + ), + DiagnosticTestCase( + id="response_has_ok", + checks={"ok": Eq(1.0)}, + msg="'ok' field should be 1.0", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(TOP_LEVEL_TESTS)) +def test_top_response_top_level(collection, test): + """Test that top response contains expected top-level fields.""" + result = execute_admin_command(collection, {"top": 1}) + assertProperties(result, test.checks, msg=test.msg, raw_res=True) + + +# Property [Per-Collection Event Fields]: each namespace entry has 9 event fields with time/count. +_EVENT_NAMES = [ + "total", + "readLock", + "writeLock", + "queries", + "getmore", + "insert", + "update", + "remove", + "commands", +] + +EVENT_EXISTS_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id=f"event_{name}_exists", + checks={name: IsType("object")}, + msg=f"'{name}' event field should be an object", + ) + for name in _EVENT_NAMES +] + +EVENT_TIME_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id=f"event_{name}_time_gte_0", + checks={f"{name}.time": Gte(0)}, + msg=f"'{name}.time' should be >= 0", + ) + for name in _EVENT_NAMES +] + +EVENT_COUNT_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id=f"event_{name}_count_gte_0", + checks={f"{name}.count": Gte(0)}, + msg=f"'{name}.count' should be >= 0", + ) + for name in _EVENT_NAMES +] + +EVENT_FIELD_TESTS = EVENT_EXISTS_TESTS + EVENT_TIME_TESTS + EVENT_COUNT_TESTS + + +@pytest.mark.parametrize("test", pytest_params(EVENT_FIELD_TESTS)) +def test_top_event_field_structure(collection, test): + """Test that per-collection event fields have expected structure.""" + collection.insert_one({"_id": "event_structure_probe"}) + result = execute_admin_command(collection, {"top": 1}) + ns = f"{collection.database.name}.{collection.name}" + ns_data = result["totals"][ns] + assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) From 2e7a59ca1851b14e5194420e4e68a6f0672f6298 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 16 Jun 2026 12:48:03 -0700 Subject: [PATCH 2/7] update from style guide Signed-off-by: Alina (Xi) Li --- .../top/test_top_argument_handling.py | 27 +++++++++++- .../commands/top/test_top_consistency.py | 41 ++++++------------- .../commands/top/test_top_core_behavior.py | 4 +- .../commands/top/test_top_errors.py | 33 +++++++-------- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py index 0deb75a0b..56b662805 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py @@ -1,7 +1,7 @@ """Tests for top command argument handling. Validates that top accepts any BSON type as its argument value and -handles unrecognized fields. +accepts unrecognized fields. """ from datetime import datetime, timezone @@ -19,7 +19,6 @@ pytestmark = pytest.mark.admin - # Property [BSON Type Acceptance]: top accepts any non-deprecated BSON type as command value. ARGUMENT_TYPE_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( @@ -138,3 +137,27 @@ def test_top_argument_types(collection, test): """Test that top accepts various BSON types as argument value.""" result = execute_admin_command(collection, test.command) assertProperties(result, test.checks, msg=test.msg, raw_res=True) + + +# Property [Unrecognized Fields]: top accepts and ignores unrecognized fields. +UNRECOGNIZED_FIELD_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "single_unrecognized_field", + command={"top": 1, "unknownField": 1}, + checks={"ok": Eq(1.0)}, + msg="top should accept a single unrecognized field", + ), + DiagnosticTestCase( + "multiple_unrecognized_fields", + command={"top": 1, "foo": 1, "bar": "baz", "qux": []}, + checks={"ok": Eq(1.0)}, + msg="top should accept multiple unrecognized fields", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(UNRECOGNIZED_FIELD_TESTS)) +def test_top_unrecognized_fields(collection, test): + """Test that top accepts unrecognized fields.""" + result = execute_admin_command(collection, test.command) + assertProperties(result, test.checks, msg=test.msg, raw_res=True) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py index 445567e54..0937bf054 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -6,26 +6,22 @@ import pytest -from documentdb_tests.framework.assertions import ( - assertFailureCode, - assertProperties, - assertSuccessPartial, -) -from documentdb_tests.framework.error_codes import UNAUTHORIZED_ERROR -from documentdb_tests.framework.executor import execute_admin_command, execute_command +from documentdb_tests.framework.assertions import assertProperties, assertSuccessPartial +from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.property_checks import Exists, Gte, IsType pytestmark = pytest.mark.admin -# ---------- Consistency and Idempotency ---------- +# Property [Idempotency]: repeated top calls succeed and counters are non-decreasing. -def test_top_repeated_calls_succeed(collection): - """Test that calling top 5 times in a row all succeed.""" +def test_top_repeated_calls_return_ok(collection): + """Test that calling top returns ok after multiple calls.""" for _ in range(5): - result = execute_admin_command(collection, {"top": 1}) - assertSuccessPartial(result, {"ok": 1.0}, msg="Repeated top call should succeed") + execute_admin_command(collection, {"top": 1}) + result = execute_admin_command(collection, {"top": 1}) + assertSuccessPartial(result, {"ok": 1.0}, msg="top should succeed after repeated calls") def test_top_counters_non_decreasing_count(collection): @@ -60,7 +56,7 @@ def test_top_counters_non_decreasing_time(collection): ) -# ---------- Collection Visibility and Namespace Format ---------- +# Property [Collection Visibility]: active collections appear in totals as db.collection keys. def test_top_newly_created_collection_appears(collection): @@ -68,7 +64,6 @@ def test_top_newly_created_collection_appears(collection): collection.insert_one({"_id": 1}) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" - # Look up namespace directly — dotted path traversal can't handle keys with dots. ns_data = result["totals"].get(ns) assertProperties( {"ns_entry": ns_data}, @@ -87,7 +82,6 @@ def test_top_multiple_collections_appear(database_client): result = execute_admin_command(coll1, {"top": 1}) ns1 = f"{database_client.name}.{coll1.name}" ns2 = f"{database_client.name}.{coll2.name}" - # Look up namespaces directly — dotted path traversal can't handle keys with dots. assertProperties( {"ns1": result["totals"].get(ns1), "ns2": result["totals"].get(ns2)}, {"ns1": Exists(), "ns2": Exists()}, @@ -101,7 +95,6 @@ def test_top_namespace_format_db_dot_collection(collection): collection.insert_one({"_id": 1}) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" - # Look up namespace directly — dotted path traversal can't handle keys with dots. ns_data = result["totals"].get(ns) assertProperties( {"ns_entry": ns_data}, @@ -122,7 +115,7 @@ def test_top_returns_totals_even_with_no_user_operations(collection): ) -# ---------- Admin Database Requirement ---------- +# Property [Admin Database]: top succeeds when run on admin database. def test_top_admin_db_succeeds(collection): @@ -131,20 +124,13 @@ def test_top_admin_db_succeeds(collection): assertSuccessPartial(result, {"ok": 1.0}, msg="top should succeed on admin db") -def test_top_non_admin_db_fails(collection): - """Test that top fails when run on a non-admin database.""" - result = execute_command(collection, {"top": 1}) - assertFailureCode(result, UNAUTHORIZED_ERROR, msg="top should fail on non-admin db") - - -# ---------- System Collections ---------- +# Property [System Collections]: system namespaces have the standard event field structure. def test_top_system_collections_have_event_structure(collection): """Test that system namespaces in totals have the expected event field structure.""" collection.insert_one({"_id": 1}) result = execute_admin_command(collection, {"top": 1}) - # Find any system namespace in totals system_ns = None for ns_key in result["totals"]: if ".system." in ns_key or ns_key.startswith("admin.") or ns_key.startswith("local."): @@ -176,7 +162,7 @@ def test_top_system_collections_have_event_structure(collection): ) -# ---------- Special Collection Types ---------- +# Property [Special Collection Types]: capped collections and views are handled by top. def test_top_tracks_capped_collection(database_client): @@ -185,7 +171,6 @@ def test_top_tracks_capped_collection(database_client): coll.insert_one({"_id": 1}) result = execute_admin_command(coll, {"top": 1}) ns = f"{database_client.name}.{coll.name}" - # Look up namespace directly — dotted path traversal can't handle keys with dots. ns_data = result["totals"][ns] assertProperties( ns_data, @@ -201,8 +186,6 @@ def test_top_tracks_view(database_client): source_coll.insert_one({"_id": 1}) database_client.command("create", "top_view_test", viewOn="top_view_source", pipeline=[]) result = execute_admin_command(source_coll, {"top": 1}) - # Views may or may not appear in top totals depending on implementation. - # This test documents the actual behavior — verifies totals is present regardless. assertProperties( result, {"totals": IsType("object")}, diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py index 96ed98c87..09bde2a44 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py @@ -12,7 +12,7 @@ pytestmark = pytest.mark.admin -# ---------- Counter Behavior — Statistics Reflect Operations ---------- +# Property [Counter Behavior]: operations increment the corresponding event counters. def test_top_insert_increments_insert_count(collection): @@ -144,7 +144,7 @@ def test_top_query_time_positive_after_query(collection): ) -# ---------- Cross-Lock Consistency Invariants ---------- +# Property [Cross-Lock Invariants]: aggregate lock counters are >= the sum of their components. def _setup_mixed_operations(collection): diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py index fac5b0fac..f7a2e50ba 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_errors.py @@ -8,14 +8,13 @@ from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import ( DiagnosticTestCase, ) -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial -from documentdb_tests.framework.error_codes import COMMAND_NOT_FOUND_ERROR +from documentdb_tests.framework.assertions import assertFailureCode +from documentdb_tests.framework.error_codes import COMMAND_NOT_FOUND_ERROR, UNAUTHORIZED_ERROR from documentdb_tests.framework.executor import execute_admin_command, execute_command from documentdb_tests.framework.parametrize import pytest_params pytestmark = pytest.mark.admin - # Property [Case Sensitivity]: command names are case-sensitive. CASE_SENSITIVITY_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( @@ -41,7 +40,18 @@ ), ] -ERROR_TESTS = CASE_SENSITIVITY_TESTS +# Property [Admin Database Required]: top fails on non-admin database. +ADMIN_DB_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + id="non_admin_db", + command={"top": 1}, + use_admin=False, + error_code=UNAUTHORIZED_ERROR, + msg="top should fail on non-admin db", + ), +] + +ERROR_TESTS = CASE_SENSITIVITY_TESTS + ADMIN_DB_TESTS @pytest.mark.parametrize("test", pytest_params(ERROR_TESTS)) @@ -52,18 +62,3 @@ def test_top_error_conditions(collection, test): else: result = execute_command(collection, test.command) assertFailureCode(result, test.error_code, msg=test.msg) - - -def test_top_unrecognized_field(collection): - """Test top behavior with an unrecognized field.""" - result = execute_admin_command(collection, {"top": 1, "unknownField": 1}) - # MongoDB may accept or reject unrecognized fields for top. - # Verify actual behavior — placeholder assertion until run against MongoDB. - assertSuccessPartial(result, {"ok": 1.0}, msg="top with unrecognized field") - - -def test_top_multiple_unrecognized_fields(collection): - """Test top behavior with multiple unrecognized fields.""" - result = execute_admin_command(collection, {"top": 1, "foo": 1, "bar": "baz", "qux": []}) - # Same behavior expectation as single unrecognized field. - assertSuccessPartial(result, {"ok": 1.0}, msg="top with multiple unrecognized fields") From 8d3ef2df146172f34cea8433190bbd5773f150bc Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 22 Jun 2026 11:10:51 -0700 Subject: [PATCH 3/7] update with style guide Signed-off-by: Alina (Xi) Li --- .../commands/top/test_top_consistency.py | 25 +++++----- .../commands/top/test_top_core_behavior.py | 27 +++++++---- .../top/test_top_response_structure.py | 48 +++++++++++++------ 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py index 0937bf054..c28c20327 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -73,15 +73,16 @@ def test_top_newly_created_collection_appears(collection): ) -def test_top_multiple_collections_appear(database_client): +def test_top_multiple_collections_appear(collection): """Test that multiple collections appear in top totals.""" - coll1 = database_client.create_collection("top_multi_coll_1") - coll2 = database_client.create_collection("top_multi_coll_2") + db = collection.database + coll1 = db.create_collection(f"{collection.name}_multi1") + coll2 = db.create_collection(f"{collection.name}_multi2") coll1.insert_one({"_id": 1}) coll2.insert_one({"_id": 1}) result = execute_admin_command(coll1, {"top": 1}) - ns1 = f"{database_client.name}.{coll1.name}" - ns2 = f"{database_client.name}.{coll2.name}" + ns1 = f"{db.name}.{coll1.name}" + ns2 = f"{db.name}.{coll2.name}" assertProperties( {"ns1": result["totals"].get(ns1), "ns2": result["totals"].get(ns2)}, {"ns1": Exists(), "ns2": Exists()}, @@ -165,12 +166,13 @@ def test_top_system_collections_have_event_structure(collection): # Property [Special Collection Types]: capped collections and views are handled by top. -def test_top_tracks_capped_collection(database_client): +def test_top_tracks_capped_collection(collection): """Test that a capped collection appears in top totals with expected structure.""" - coll = database_client.create_collection("top_capped_test", capped=True, size=4096) + db = collection.database + coll = db.create_collection(f"{collection.name}_capped", capped=True, size=4096) coll.insert_one({"_id": 1}) result = execute_admin_command(coll, {"top": 1}) - ns = f"{database_client.name}.{coll.name}" + ns = f"{db.name}.{coll.name}" ns_data = result["totals"][ns] assertProperties( ns_data, @@ -180,11 +182,12 @@ def test_top_tracks_capped_collection(database_client): ) -def test_top_tracks_view(database_client): +def test_top_tracks_view(collection): """Test whether a view namespace appears in top totals.""" - source_coll = database_client.create_collection("top_view_source") + db = collection.database + source_coll = db.create_collection(f"{collection.name}_view_src") source_coll.insert_one({"_id": 1}) - database_client.command("create", "top_view_test", viewOn="top_view_source", pipeline=[]) + db.command("create", f"{collection.name}_view", viewOn=source_coll.name, pipeline=[]) result = execute_admin_command(source_coll, {"top": 1}) assertProperties( result, diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py index 09bde2a44..c73017964 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py @@ -121,6 +121,9 @@ def test_top_remove_increments_writeLock_count(collection): ) +# Property [Time Tracking]: time metrics are positive after corresponding operations. + + def test_top_insert_time_positive_after_inserts(collection): """Test that insert.time is positive after inserting documents.""" collection.insert_many([{"_id": i} for i in range(10)]) @@ -147,17 +150,12 @@ def test_top_query_time_positive_after_query(collection): # Property [Cross-Lock Invariants]: aggregate lock counters are >= the sum of their components. -def _setup_mixed_operations(collection): - """Insert, query, update, and delete on the collection to populate all counters.""" +def test_top_readLock_count_gte_queries_count(collection): + """Test that readLock.count >= queries.count.""" collection.insert_many([{"_id": i, "a": i} for i in range(5)]) list(collection.find()) collection.update_one({"_id": 0}, {"$set": {"a": 99}}) collection.delete_one({"_id": 4}) - - -def test_top_readLock_count_gte_queries_count(collection): - """Test that readLock.count >= queries.count.""" - _setup_mixed_operations(collection) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] @@ -171,7 +169,10 @@ def test_top_readLock_count_gte_queries_count(collection): def test_top_readLock_time_gte_queries_time(collection): """Test that readLock.time >= queries.time.""" - _setup_mixed_operations(collection) + collection.insert_many([{"_id": i, "a": i} for i in range(5)]) + list(collection.find()) + collection.update_one({"_id": 0}, {"$set": {"a": 99}}) + collection.delete_one({"_id": 4}) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] @@ -185,7 +186,10 @@ def test_top_readLock_time_gte_queries_time(collection): def test_top_writeLock_count_gte_insert_update_remove(collection): """Test that writeLock.count >= insert.count + update.count + remove.count.""" - _setup_mixed_operations(collection) + collection.insert_many([{"_id": i, "a": i} for i in range(5)]) + list(collection.find()) + collection.update_one({"_id": 0}, {"$set": {"a": 99}}) + collection.delete_one({"_id": 4}) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] @@ -200,7 +204,10 @@ def test_top_writeLock_count_gte_insert_update_remove(collection): def test_top_writeLock_time_gte_insert_update_remove(collection): """Test that writeLock.time >= insert.time + update.time + remove.time.""" - _setup_mixed_operations(collection) + collection.insert_many([{"_id": i, "a": i} for i in range(5)]) + list(collection.find()) + collection.update_one({"_id": 0}, {"$set": {"a": 99}}) + collection.delete_one({"_id": 4}) result = execute_admin_command(collection, {"top": 1}) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py index 8a78a0247..0bcba39cd 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py @@ -39,25 +39,23 @@ def test_top_response_top_level(collection, test): # Property [Per-Collection Event Fields]: each namespace entry has 9 event fields with time/count. -_EVENT_NAMES = [ - "total", - "readLock", - "writeLock", - "queries", - "getmore", - "insert", - "update", - "remove", - "commands", -] - EVENT_EXISTS_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( id=f"event_{name}_exists", checks={name: IsType("object")}, msg=f"'{name}' event field should be an object", ) - for name in _EVENT_NAMES + for name in [ + "total", + "readLock", + "writeLock", + "queries", + "getmore", + "insert", + "update", + "remove", + "commands", + ] ] EVENT_TIME_TESTS: list[DiagnosticTestCase] = [ @@ -66,7 +64,17 @@ def test_top_response_top_level(collection, test): checks={f"{name}.time": Gte(0)}, msg=f"'{name}.time' should be >= 0", ) - for name in _EVENT_NAMES + for name in [ + "total", + "readLock", + "writeLock", + "queries", + "getmore", + "insert", + "update", + "remove", + "commands", + ] ] EVENT_COUNT_TESTS: list[DiagnosticTestCase] = [ @@ -75,7 +83,17 @@ def test_top_response_top_level(collection, test): checks={f"{name}.count": Gte(0)}, msg=f"'{name}.count' should be >= 0", ) - for name in _EVENT_NAMES + for name in [ + "total", + "readLock", + "writeLock", + "queries", + "getmore", + "insert", + "update", + "remove", + "commands", + ] ] EVENT_FIELD_TESTS = EVENT_EXISTS_TESTS + EVENT_TIME_TESTS + EVENT_COUNT_TESTS From 47b5b1a0152be87f12640a2b0aa05c5730f5d252 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 22 Jun 2026 11:15:53 -0700 Subject: [PATCH 4/7] remove duplicate test cases Signed-off-by: Alina (Xi) Li --- .../commands/top/test_top_consistency.py | 36 +------------------ 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py index c28c20327..48b7f1b6f 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -1,6 +1,6 @@ """Tests for top command consistency, visibility, and special collection types. -Validates idempotency, namespace visibility, format, admin database requirement, +Validates idempotency, namespace visibility, system namespace structure, and behavior with capped collections and views. """ @@ -91,40 +91,6 @@ def test_top_multiple_collections_appear(collection): ) -def test_top_namespace_format_db_dot_collection(collection): - """Test that namespace keys in totals are formatted as db.collection.""" - collection.insert_one({"_id": 1}) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"].get(ns) - assertProperties( - {"ns_entry": ns_data}, - {"ns_entry": Exists()}, - msg=f"Namespace key should be '{ns}' (db.collection format)", - raw_res=True, - ) - - -def test_top_returns_totals_even_with_no_user_operations(collection): - """Test that top returns totals object even with minimal operations.""" - result = execute_admin_command(collection, {"top": 1}) - assertProperties( - result, - {"totals": IsType("object")}, - msg="totals should be an object even with no user operations", - raw_res=True, - ) - - -# Property [Admin Database]: top succeeds when run on admin database. - - -def test_top_admin_db_succeeds(collection): - """Test that top succeeds when run on admin database.""" - result = execute_admin_command(collection, {"top": 1}) - assertSuccessPartial(result, {"ok": 1.0}, msg="top should succeed on admin db") - - # Property [System Collections]: system namespaces have the standard event field structure. From 5e5f8d71dc73028d7885f52352f674eff6c45e90 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 22 Jun 2026 12:05:03 -0700 Subject: [PATCH 5/7] convert to use DiagnosticTestCase Signed-off-by: Alina (Xi) Li --- .../commands/top/test_top_core_behavior.py | 218 +++++++++--------- .../diagnostic/utils/diagnostic_test_case.py | 4 +- 2 files changed, 108 insertions(+), 114 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py index c73017964..00d45010d 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py @@ -5,146 +5,138 @@ import pytest +from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import ( + DiagnosticTestCase, +) from documentdb_tests.framework.assertions import assertProperties from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params from documentdb_tests.framework.property_checks import Gt, Gte pytestmark = pytest.mark.admin -# Property [Counter Behavior]: operations increment the corresponding event counters. - - -def test_top_insert_increments_insert_count(collection): - """Test that inserting documents increments the insert count.""" - collection.insert_many([{"_id": i} for i in range(5)]) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, - {"insert.count": Gte(1)}, +# Property [Counter Behavior — Insert]: insert operations increment insert and writeLock counters. +INSERT_COUNTER_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "insert_increments_insert_count", + command={"top": 1}, + checks={"insert.count": Gte(1)}, msg="insert.count should be >= 1 after inserts", - raw_res=True, - ) - - -def test_top_insert_increments_writeLock_count(collection): - """Test that inserting documents increments the writeLock count.""" - collection.insert_many([{"_id": i} for i in range(5)]) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, - {"writeLock.count": Gte(1)}, + ), + DiagnosticTestCase( + "insert_increments_writeLock_count", + command={"top": 1}, + checks={"writeLock.count": Gte(1)}, msg="writeLock.count should be >= 1 after inserts", - raw_res=True, - ) - - -def test_top_query_increments_queries_count(collection): - """Test that running a find query increments the queries count.""" - collection.insert_one({"_id": 1}) - list(collection.find()) - result = execute_admin_command(collection, {"top": 1}) + ), + DiagnosticTestCase( + "insert_time_positive", + command={"top": 1}, + checks={"insert.time": Gt(0)}, + msg="insert.time should be > 0 after inserts", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(INSERT_COUNTER_TESTS)) +def test_top_insert_counters(collection, test): + """Test that insert operations increment the expected counters.""" + collection.insert_many([{"_id": i} for i in range(10)]) + result = execute_admin_command(collection, test.command) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] - assertProperties( - ns_data, {"queries.count": Gte(1)}, msg="queries.count should be >= 1", raw_res=True - ) - - -def test_top_query_increments_readLock_count(collection): - """Test that running a find query increments the readLock count.""" + assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) + + +# Property [Counter Behavior — Query]: find operations increment queries and readLock counters. +QUERY_COUNTER_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "query_increments_queries_count", + command={"top": 1}, + checks={"queries.count": Gte(1)}, + msg="queries.count should be >= 1 after query", + ), + DiagnosticTestCase( + "query_increments_readLock_count", + command={"top": 1}, + checks={"readLock.count": Gte(1)}, + msg="readLock.count should be >= 1 after query", + ), + DiagnosticTestCase( + "query_time_positive", + command={"top": 1}, + checks={"queries.time": Gt(0)}, + msg="queries.time should be > 0 after query", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(QUERY_COUNTER_TESTS)) +def test_top_query_counters(collection, test): + """Test that find operations increment the expected counters.""" collection.insert_one({"_id": 1}) list(collection.find()) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, {"readLock.count": Gte(1)}, msg="readLock.count should be >= 1", raw_res=True - ) - - -def test_top_update_increments_update_count(collection): - """Test that running an update increments the update count.""" - collection.insert_one({"_id": 1, "a": 1}) - collection.update_one({"_id": 1}, {"$set": {"a": 2}}) - result = execute_admin_command(collection, {"top": 1}) + result = execute_admin_command(collection, test.command) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] - assertProperties( - ns_data, {"update.count": Gte(1)}, msg="update.count should be >= 1", raw_res=True - ) + assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) + + +# Property [Counter Behavior — Update]: update operations increment update and writeLock counters. +UPDATE_COUNTER_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "update_increments_update_count", + command={"top": 1}, + checks={"update.count": Gte(1)}, + msg="update.count should be >= 1 after update", + ), + DiagnosticTestCase( + "update_increments_writeLock_count", + command={"top": 1}, + checks={"writeLock.count": Gte(1)}, + msg="writeLock.count should be >= 1 after update", + ), +] -def test_top_update_increments_writeLock_count(collection): - """Test that running an update increments the writeLock count.""" +@pytest.mark.parametrize("test", pytest_params(UPDATE_COUNTER_TESTS)) +def test_top_update_counters(collection, test): + """Test that update operations increment the expected counters.""" collection.insert_one({"_id": 1, "a": 1}) collection.update_one({"_id": 1}, {"$set": {"a": 2}}) - result = execute_admin_command(collection, {"top": 1}) + result = execute_admin_command(collection, test.command) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] - assertProperties( - ns_data, - {"writeLock.count": Gte(1)}, - msg="writeLock.count should be >= 1 after update", - raw_res=True, - ) - - -def test_top_remove_increments_remove_count(collection): - """Test that running a delete increments the remove count.""" - collection.insert_one({"_id": 1}) - collection.delete_one({"_id": 1}) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, {"remove.count": Gte(1)}, msg="remove.count should be >= 1", raw_res=True - ) - - -def test_top_remove_increments_writeLock_count(collection): - """Test that running a delete increments the writeLock count.""" - collection.insert_one({"_id": 1}) - collection.delete_one({"_id": 1}) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, - {"writeLock.count": Gte(1)}, + assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) + + +# Property [Counter Behavior — Remove]: delete operations increment remove and writeLock counters. +REMOVE_COUNTER_TESTS: list[DiagnosticTestCase] = [ + DiagnosticTestCase( + "remove_increments_remove_count", + command={"top": 1}, + checks={"remove.count": Gte(1)}, + msg="remove.count should be >= 1 after delete", + ), + DiagnosticTestCase( + "remove_increments_writeLock_count", + command={"top": 1}, + checks={"writeLock.count": Gte(1)}, msg="writeLock.count should be >= 1 after delete", - raw_res=True, - ) - - -# Property [Time Tracking]: time metrics are positive after corresponding operations. - - -def test_top_insert_time_positive_after_inserts(collection): - """Test that insert.time is positive after inserting documents.""" - collection.insert_many([{"_id": i} for i in range(10)]) - result = execute_admin_command(collection, {"top": 1}) - ns = f"{collection.database.name}.{collection.name}" - ns_data = result["totals"][ns] - assertProperties( - ns_data, {"insert.time": Gt(0)}, msg="insert.time should be > 0 after inserts", raw_res=True - ) + ), +] -def test_top_query_time_positive_after_query(collection): - """Test that queries.time is positive after running a find query.""" +@pytest.mark.parametrize("test", pytest_params(REMOVE_COUNTER_TESTS)) +def test_top_remove_counters(collection, test): + """Test that delete operations increment the expected counters.""" collection.insert_one({"_id": 1}) - list(collection.find()) - result = execute_admin_command(collection, {"top": 1}) + collection.delete_one({"_id": 1}) + result = execute_admin_command(collection, test.command) ns = f"{collection.database.name}.{collection.name}" ns_data = result["totals"][ns] - assertProperties( - ns_data, {"queries.time": Gt(0)}, msg="queries.time should be > 0 after query", raw_res=True - ) + assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) # Property [Cross-Lock Invariants]: aggregate lock counters are >= the sum of their components. diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/utils/diagnostic_test_case.py b/documentdb_tests/compatibility/tests/system/diagnostic/utils/diagnostic_test_case.py index 39adb13d7..3d08d60c0 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/utils/diagnostic_test_case.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/utils/diagnostic_test_case.py @@ -1,7 +1,7 @@ """Shared test case for diagnostic command tests.""" from dataclasses import dataclass, field -from typing import Any, Dict, Optional +from typing import Any, Dict, List, Optional from documentdb_tests.framework.test_case import BaseTestCase @@ -11,11 +11,13 @@ class DiagnosticTestCase(BaseTestCase): """Test case for diagnostic command tests. Attributes: + setup: Commands to run before the test command to establish state. command: The command document to execute. use_admin: If True, execute against the admin database. checks: Mapping of dotted field paths to property check objects. """ + setup: List[Dict[str, Any]] = field(default_factory=list) command: Optional[Dict[str, Any]] = None use_admin: bool = True checks: Dict[str, Any] = field(default_factory=dict) From 638594646f50e11fdae9459667e41fb13888bd3b Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 22 Jun 2026 12:07:05 -0700 Subject: [PATCH 6/7] add docs Signed-off-by: Alina (Xi) Li --- .../system/diagnostic/commands/top/test_top_consistency.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py index 48b7f1b6f..2f4525935 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -2,6 +2,11 @@ Validates idempotency, namespace visibility, system namespace structure, and behavior with capped collections and views. + +Standalone functions are used throughout because every test requires runtime +logic that DiagnosticTestCase cannot express: multi-call comparisons with +dynamic thresholds, namespace key extraction from the response, conditional +skips, or ad-hoc collection creation (capped, views). """ import pytest From 271906fb240a5dfc6035e37d61198d9d93bc81ef Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 22 Jun 2026 12:19:18 -0700 Subject: [PATCH 7/7] add test and fix format Signed-off-by: Alina (Xi) Li --- .../top/test_top_argument_handling.py | 16 ++---- .../commands/top/test_top_consistency.py | 34 ++++-------- .../commands/top/test_top_core_behavior.py | 52 +++++++------------ .../top/test_top_response_structure.py | 7 ++- 4 files changed, 42 insertions(+), 67 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py index 56b662805..e40863497 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_argument_handling.py @@ -131,14 +131,6 @@ ), ] - -@pytest.mark.parametrize("test", pytest_params(ARGUMENT_TYPE_TESTS)) -def test_top_argument_types(collection, test): - """Test that top accepts various BSON types as argument value.""" - result = execute_admin_command(collection, test.command) - assertProperties(result, test.checks, msg=test.msg, raw_res=True) - - # Property [Unrecognized Fields]: top accepts and ignores unrecognized fields. UNRECOGNIZED_FIELD_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( @@ -155,9 +147,11 @@ def test_top_argument_types(collection, test): ), ] +ARGUMENT_HANDLING_TESTS = ARGUMENT_TYPE_TESTS + UNRECOGNIZED_FIELD_TESTS + -@pytest.mark.parametrize("test", pytest_params(UNRECOGNIZED_FIELD_TESTS)) -def test_top_unrecognized_fields(collection, test): - """Test that top accepts unrecognized fields.""" +@pytest.mark.parametrize("test", pytest_params(ARGUMENT_HANDLING_TESTS)) +def test_top_argument_handling(collection, test): + """Test that top accepts various BSON types and unrecognized fields.""" result = execute_admin_command(collection, test.command) assertProperties(result, test.checks, msg=test.msg, raw_res=True) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py index 2f4525935..f8c037cfa 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_consistency.py @@ -100,7 +100,7 @@ def test_top_multiple_collections_appear(collection): def test_top_system_collections_have_event_structure(collection): - """Test that system namespaces in totals have the expected event field structure.""" + """Test that a system namespace in totals has the expected event field structure.""" collection.insert_one({"_id": 1}) result = execute_admin_command(collection, {"top": 1}) system_ns = None @@ -111,25 +111,10 @@ def test_top_system_collections_have_event_structure(collection): if system_ns is None: pytest.skip("No system namespace found in top totals") ns_data = result["totals"][system_ns] - checks = {} - for event in [ - "total", - "readLock", - "writeLock", - "queries", - "getmore", - "insert", - "update", - "remove", - "commands", - ]: - checks[event] = IsType("object") - checks[f"{event}.time"] = Gte(0) - checks[f"{event}.count"] = Gte(0) assertProperties( ns_data, - checks, - msg=f"System namespace {system_ns} should have all event fields with time/count", + {"total": IsType("object"), "total.time": Gte(0), "total.count": Gte(0)}, + msg=f"System namespace {system_ns} should have event fields with time/count", raw_res=True, ) @@ -154,15 +139,18 @@ def test_top_tracks_capped_collection(collection): def test_top_tracks_view(collection): - """Test whether a view namespace appears in top totals.""" + """Test that a view namespace appears in top totals.""" db = collection.database source_coll = db.create_collection(f"{collection.name}_view_src") source_coll.insert_one({"_id": 1}) - db.command("create", f"{collection.name}_view", viewOn=source_coll.name, pipeline=[]) + view_name = f"{collection.name}_view" + db.command("create", view_name, viewOn=source_coll.name, pipeline=[]) result = execute_admin_command(source_coll, {"top": 1}) + view_ns = f"{db.name}.{view_name}" + view_data = result["totals"].get(view_ns) assertProperties( - result, - {"totals": IsType("object")}, - msg="top should return totals even when views exist", + {"ns_entry": view_data}, + {"ns_entry": Exists()}, + msg=f"View namespace {view_ns} should appear in top totals", raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py index 00d45010d..ad3b7e01d 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_core_behavior.py @@ -16,22 +16,22 @@ pytestmark = pytest.mark.admin -# Property [Counter Behavior — Insert]: insert operations increment insert and writeLock counters. +# Property [Counter Behavior - Insert]: insert operations populate insert, writeLock, and time. INSERT_COUNTER_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( - "insert_increments_insert_count", + "insert_count_gte_1", command={"top": 1}, checks={"insert.count": Gte(1)}, msg="insert.count should be >= 1 after inserts", ), DiagnosticTestCase( - "insert_increments_writeLock_count", + "insert_writeLock_count_gte_1", command={"top": 1}, checks={"writeLock.count": Gte(1)}, msg="writeLock.count should be >= 1 after inserts", ), DiagnosticTestCase( - "insert_time_positive", + "insert_time_gt_0", command={"top": 1}, checks={"insert.time": Gt(0)}, msg="insert.time should be > 0 after inserts", @@ -40,8 +40,8 @@ @pytest.mark.parametrize("test", pytest_params(INSERT_COUNTER_TESTS)) -def test_top_insert_counters(collection, test): - """Test that insert operations increment the expected counters.""" +def test_top_after_inserts(collection, test): + """Test counters after insert operations.""" collection.insert_many([{"_id": i} for i in range(10)]) result = execute_admin_command(collection, test.command) ns = f"{collection.database.name}.{collection.name}" @@ -49,22 +49,22 @@ def test_top_insert_counters(collection, test): assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) -# Property [Counter Behavior — Query]: find operations increment queries and readLock counters. +# Property [Counter Behavior - Query]: find operations populate queries, readLock, and time. QUERY_COUNTER_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( - "query_increments_queries_count", + "queries_count_gte_1", command={"top": 1}, checks={"queries.count": Gte(1)}, msg="queries.count should be >= 1 after query", ), DiagnosticTestCase( - "query_increments_readLock_count", + "query_readLock_count_gte_1", command={"top": 1}, checks={"readLock.count": Gte(1)}, msg="readLock.count should be >= 1 after query", ), DiagnosticTestCase( - "query_time_positive", + "queries_time_gt_0", command={"top": 1}, checks={"queries.time": Gt(0)}, msg="queries.time should be > 0 after query", @@ -73,8 +73,8 @@ def test_top_insert_counters(collection, test): @pytest.mark.parametrize("test", pytest_params(QUERY_COUNTER_TESTS)) -def test_top_query_counters(collection, test): - """Test that find operations increment the expected counters.""" +def test_top_after_query(collection, test): + """Test counters after find operations.""" collection.insert_one({"_id": 1}) list(collection.find()) result = execute_admin_command(collection, test.command) @@ -83,26 +83,20 @@ def test_top_query_counters(collection, test): assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) -# Property [Counter Behavior — Update]: update operations increment update and writeLock counters. +# Property [Counter Behavior - Update]: update operations populate the update counter. UPDATE_COUNTER_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( - "update_increments_update_count", + "update_count_gte_1", command={"top": 1}, checks={"update.count": Gte(1)}, msg="update.count should be >= 1 after update", ), - DiagnosticTestCase( - "update_increments_writeLock_count", - command={"top": 1}, - checks={"writeLock.count": Gte(1)}, - msg="writeLock.count should be >= 1 after update", - ), ] @pytest.mark.parametrize("test", pytest_params(UPDATE_COUNTER_TESTS)) -def test_top_update_counters(collection, test): - """Test that update operations increment the expected counters.""" +def test_top_after_update(collection, test): + """Test counters after update operations.""" collection.insert_one({"_id": 1, "a": 1}) collection.update_one({"_id": 1}, {"$set": {"a": 2}}) result = execute_admin_command(collection, test.command) @@ -111,26 +105,20 @@ def test_top_update_counters(collection, test): assertProperties(ns_data, test.checks, msg=test.msg, raw_res=True) -# Property [Counter Behavior — Remove]: delete operations increment remove and writeLock counters. +# Property [Counter Behavior - Remove]: delete operations populate the remove counter. REMOVE_COUNTER_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( - "remove_increments_remove_count", + "remove_count_gte_1", command={"top": 1}, checks={"remove.count": Gte(1)}, msg="remove.count should be >= 1 after delete", ), - DiagnosticTestCase( - "remove_increments_writeLock_count", - command={"top": 1}, - checks={"writeLock.count": Gte(1)}, - msg="writeLock.count should be >= 1 after delete", - ), ] @pytest.mark.parametrize("test", pytest_params(REMOVE_COUNTER_TESTS)) -def test_top_remove_counters(collection, test): - """Test that delete operations increment the expected counters.""" +def test_top_after_remove(collection, test): + """Test counters after delete operations.""" collection.insert_one({"_id": 1}) collection.delete_one({"_id": 1}) result = execute_admin_command(collection, test.command) diff --git a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py index 0bcba39cd..c6e1c8baa 100644 --- a/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py +++ b/documentdb_tests/compatibility/tests/system/diagnostic/commands/top/test_top_response_structure.py @@ -16,13 +16,18 @@ pytestmark = pytest.mark.admin -# Property [Top-Level Fields]: top response contains totals and ok fields. +# Property [Top-Level Fields]: top response contains totals, totals.note, and ok fields. TOP_LEVEL_TESTS: list[DiagnosticTestCase] = [ DiagnosticTestCase( id="response_has_totals", checks={"totals": IsType("object")}, msg="'totals' field should be an object", ), + DiagnosticTestCase( + id="response_has_note", + checks={"totals.note": Eq("all times in microseconds")}, + msg="'totals.note' should describe time units", + ), DiagnosticTestCase( id="response_has_ok", checks={"ok": Eq(1.0)},