From d9d037c0e616382d73f44d721b2e9f0980834f33 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 24 Jun 2026 15:22:03 -0700 Subject: [PATCH 01/12] initially generated tests by Victor Signed-off-by: Alina (Xi) Li --- ...eCompatibilityVersion_confirm_semantics.py | 109 ++++++++ ...patibilityVersion_confirm_type_coercion.py | 222 +++++++++++++++ ...atureCompatibilityVersion_core_behavior.py | 125 +++++++++ ...t_setFeatureCompatibilityVersion_errors.py | 174 ++++++++++++ ...patibilityVersion_feature_not_supported.py | 38 +++ ...tibilityVersion_version_type_validation.py | 86 ++++++ ...ibilityVersion_version_value_validation.py | 155 +++++++++++ ...tibilityVersion_writeConcern_validation.py | 257 ++++++++++++++++++ 8 files changed, 1166 insertions(+) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py new file mode 100644 index 000000000..f509280a4 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py @@ -0,0 +1,109 @@ +"""Tests for setFeatureCompatibilityVersion confirm field semantics. + +Validates that the confirm field is required for version changes, +and that confirm:false or omitted confirm prevents FCV changes. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def _get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +def _set_fcv(collection, version): + """Set FCV with confirm:true.""" + return execute_admin_command( + collection, {"setFeatureCompatibilityVersion": version, "confirm": True} + ) + + +def _get_lower_fcv(current): + """Get a different supported FCV than the current one.""" + return "8.0" if current != "8.0" else "8.2" + + +def test_setFeatureCompatibilityVersion_confirm_true_allows_change(collection): + """Test confirm:true allows a version change to proceed.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": lower, "confirm": True} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm:true should allow version change") + _set_fcv(collection, original) + + +def test_setFeatureCompatibilityVersion_confirm_omitted_fails(collection): + """Test confirm omitted on a version change fails (ok:0), FCV unchanged.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": lower}) + assertFailureCode(result, 7369100, msg="Should fail when confirm is omitted") + + +def test_setFeatureCompatibilityVersion_confirm_false_fails(collection): + """Test confirm:false on a version change fails (ok:0), FCV unchanged.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": lower, "confirm": False} + ) + assertFailureCode(result, 7369100, msg="Should fail when confirm is false") + + +def test_setFeatureCompatibilityVersion_confirm_omitted_returns_error_code(collection): + """Test the confirm-gate failure returns a stable error code.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": lower}) + # Assert it failed with a numeric code (7369100 per JS test specs) + assertFailureCode(result, 7369100, msg="Omitting confirm should return error code 7369100") + + +def test_setFeatureCompatibilityVersion_confirm_false_returns_error_code(collection): + """Test confirm:false returns the same stable error code.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": lower, "confirm": False} + ) + assertFailureCode(result, 7369100, msg="confirm:false should return error code 7369100") + + +def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails(collection): + """Test upgrading without confirm also fails with error code 7369100.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + # First downgrade + _set_fcv(collection, lower) + # Try upgrade without confirm + result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": original}) + assertFailureCode(result, 7369100, msg="Upgrade without confirm should fail with 7369100") + # Restore + _set_fcv(collection, original) + + +def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds(collection): + """Test upgrading with confirm:true succeeds.""" + original = _get_fcv(collection) + lower = _get_lower_fcv(original) + # First downgrade + _set_fcv(collection, lower) + # Upgrade with confirm + result = _set_fcv(collection, original) + assertSuccessPartial(result, {"ok": 1.0}, msg="Upgrade with confirm:true should succeed") diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py new file mode 100644 index 000000000..15310928d --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -0,0 +1,222 @@ +"""Tests for setFeatureCompatibilityVersion confirm field type coercion. + +Validates how the confirm field handles various BSON types beyond bool, +recording coercion behavior (accepted-as-true vs rejected/treated-as-false). +""" + +import pytest +from bson import Decimal128, Int64 + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + +# Error code when confirm is treated as falsy (not-true) +FCV_CONFIRM_REQUIRED_ERROR = 7369100 + + +def _get_fcv(collection): + """Read the current FCV.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.0" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.0") + return str(fcv_data) + + +def _set_fcv(collection, version): + """Set FCV with confirm:true.""" + return execute_admin_command( + collection, {"setFeatureCompatibilityVersion": version, "confirm": True} + ) + + +def _get_other_fcv(current): + """Get a different supported FCV than the current one.""" + return "8.0" if current != "8.0" else "8.2" + + +def test_setFeatureCompatibilityVersion_confirm_int_1_coercion(collection): + """Test confirm = 1 (int32) is accepted as true.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": 1} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=1 (int) should be accepted as true") + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_int_0_coercion(collection): + """Test confirm = 0 (int32) is treated as false (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": 0} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=0 should be treated as false" + ) + + +def test_setFeatureCompatibilityVersion_confirm_double_1_coercion(collection): + """Test confirm = 1.0 (double) is accepted as true.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": 1.0} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=1.0 (double) should be accepted as true") + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_double_0_coercion(collection): + """Test confirm = 0.0 (double) is treated as false (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": 0.0} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=0.0 should be treated as false" + ) + + +def test_setFeatureCompatibilityVersion_confirm_long_1_coercion(collection): + """Test confirm = Int64(1) is accepted as true.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(1)} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=Int64(1) should be accepted as true") + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_long_0_coercion(collection): + """Test confirm = Int64(0) is treated as false (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(0)} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=Int64(0) should be treated as false" + ) + + +def test_setFeatureCompatibilityVersion_confirm_decimal_1_coercion(collection): + """Test confirm = Decimal128('1') is accepted as true.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("1")} + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="confirm=Decimal128('1') should be accepted as true" + ) + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_decimal_0_coercion(collection): + """Test confirm = Decimal128('0') is treated as false (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("0")} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=Decimal128('0') should be treated as false" + ) + + +def test_setFeatureCompatibilityVersion_confirm_null_coercion(collection): + """Test confirm = null is treated as not-true (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": None} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=null should be treated as not-true" + ) + + +def test_setFeatureCompatibilityVersion_confirm_negative_zero_coercion(collection): + """Test confirm = -0.0 is treated as false (error 7369100).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": -0.0} + ) + assertFailureCode( + result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=-0.0 should be treated as false" + ) + + +def test_setFeatureCompatibilityVersion_confirm_nan_coercion(collection): + """Test confirm = NaN is accepted as true (truthy in MongoDB bool coercion).""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": float("nan")} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=NaN should be accepted as true") + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_infinity_coercion(collection): + """Test confirm = Infinity is accepted as true.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": float("inf")} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=Infinity should be accepted as true") + _set_fcv(collection, current) + + +def test_setFeatureCompatibilityVersion_confirm_string_coercion(collection): + """Test confirm = string is rejected with TYPE_MISMATCH_ERROR.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": "true"} + ) + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="confirm='true' (string) should be rejected with type mismatch", + ) + + +def test_setFeatureCompatibilityVersion_confirm_object_coercion(collection): + """Test confirm = object is rejected with TYPE_MISMATCH_ERROR.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": {"a": 1}} + ) + assertFailureCode( + result, TYPE_MISMATCH_ERROR, msg="confirm={} (object) should be rejected with type mismatch" + ) + + +def test_setFeatureCompatibilityVersion_confirm_array_coercion(collection): + """Test confirm = array is rejected with TYPE_MISMATCH_ERROR.""" + current = _get_fcv(collection) + target = _get_other_fcv(current) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": target, "confirm": [True]} + ) + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="confirm=[True] (array) should be rejected with type mismatch", + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py new file mode 100644 index 000000000..5487bd0ba --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -0,0 +1,125 @@ +"""Tests for setFeatureCompatibilityVersion core behavior. + +Validates FCV set/get round-trip, idempotency, default value read-back, +and basic upgrade/downgrade with confirm. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertSuccessPartial +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def _get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return None + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version") + return str(fcv_data) + + +def _set_fcv(collection, version): + """Set FCV to the given version with confirm:true.""" + return execute_admin_command( + collection, {"setFeatureCompatibilityVersion": version, "confirm": True} + ) + + +def test_setFeatureCompatibilityVersion_set_current_version_succeeds(collection): + """Test setting FCV to the deployment's supported version with confirm:true succeeds.""" + current_fcv = _get_fcv(collection) + result = _set_fcv(collection, current_fcv) + assertSuccessPartial(result, {"ok": 1.0}, msg="Setting FCV to current version should succeed") + + +def test_setFeatureCompatibilityVersion_idempotent_same_value(collection): + """Test setting FCV to the value it already holds is idempotent and returns ok:1.""" + current_fcv = _get_fcv(collection) + _set_fcv(collection, current_fcv) + result = _set_fcv(collection, current_fcv) + assertSuccessPartial( + result, {"ok": 1.0}, msg="Re-setting FCV to same value should be idempotent" + ) + + +def test_setFeatureCompatibilityVersion_safe_retry(collection): + """Test re-running the identical successful command again succeeds.""" + current_fcv = _get_fcv(collection) + _set_fcv(collection, current_fcv) + result = _set_fcv(collection, current_fcv) + assertSuccessPartial(result, {"ok": 1.0}, msg="Safe retry of the same command should succeed") + + +def test_setFeatureCompatibilityVersion_getParameter_reads_back_value(collection): + """Test getParameter featureCompatibilityVersion reads back the most recently set value.""" + current_fcv = _get_fcv(collection) + _set_fcv(collection, current_fcv) + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="getParameter should succeed after setFeatureCompatibilityVersion", + ) + + +def test_setFeatureCompatibilityVersion_fresh_deployment_default_fcv(collection): + """Test a fresh deployment reports its expected default FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="getParameter featureCompatibilityVersion should succeed" + ) + + +def test_setFeatureCompatibilityVersion_downgrade_with_confirm(collection): + """Test the compatibility version can be downgraded with confirm.""" + original_fcv = _get_fcv(collection) + # Use the other supported version (8.0 or 8.2) + other_fcv = "8.0" if original_fcv != "8.0" else "8.2" + + result = _set_fcv(collection, other_fcv) + assertSuccessPartial(result, {"ok": 1.0}, msg="Changing FCV with confirm:true should succeed") + # Restore original + _set_fcv(collection, original_fcv) + + +def test_setFeatureCompatibilityVersion_upgrade_with_confirm(collection): + """Test the compatibility version can be upgraded back to the latest supported version.""" + original_fcv = _get_fcv(collection) + other_fcv = "8.0" if original_fcv != "8.0" else "8.2" + + # Change first + _set_fcv(collection, other_fcv) + # Change back + result = _set_fcv(collection, original_fcv) + assertSuccessPartial( + result, {"ok": 1.0}, msg="Changing FCV back with confirm:true should succeed" + ) + + +def test_setFeatureCompatibilityVersion_getParameter_reflects_change(collection): + """Test that after a successful setFeatureCompatibilityVersion the read-back matches.""" + original_fcv = _get_fcv(collection) + other_fcv = "8.0" if original_fcv != "8.0" else "8.2" + + _set_fcv(collection, other_fcv) + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + assertSuccessPartial( + result, + {"ok": 1.0, "featureCompatibilityVersion": {"version": other_fcv}}, + msg=f"getParameter should reflect changed FCV to '{other_fcv}'", + ) + # Restore + _set_fcv(collection, original_fcv) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py new file mode 100644 index 000000000..404352ee3 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -0,0 +1,174 @@ +"""Tests for setFeatureCompatibilityVersion error cases. + +Covers admin-database-only enforcement, unknown/extra fields, argument +handling combinations, response structure, and setParameter rejection. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import ( + ILLEGAL_OPERATION_ERROR, + UNAUTHORIZED_ERROR, + UNRECOGNIZED_COMMAND_FIELD_ERROR, +) +from documentdb_tests.framework.executor import execute_admin_command, execute_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def _get_fcv(collection): + """Read the current FCV.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +# --- Admin-Database-Only Enforcement --- + + +def test_setFeatureCompatibilityVersion_on_admin_db_accepted(collection): + """Test command on the admin database is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="Command on admin db should be accepted") + + +def test_setFeatureCompatibilityVersion_on_user_db_fails(collection): + """Test command on a user database fails with UNAUTHORIZED_ERROR (13).""" + current_fcv = _get_fcv(collection) + result = execute_command( + collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + ) + assertFailureCode( + result, UNAUTHORIZED_ERROR, msg="Command on user db should fail with UNAUTHORIZED_ERROR" + ) + + +# --- Unknown / Extra Fields --- + + +def test_setFeatureCompatibilityVersion_unrecognized_field_rejected(collection): + """Test an unrecognized top-level field fails with UNRECOGNIZED_COMMAND_FIELD_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "unknownField": 1, + }, + ) + assertFailureCode( + result, + UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="Unrecognized field should be rejected with 40415", + ) + + +def test_setFeatureCompatibilityVersion_misspelled_confirm_rejected(collection): + """Test a misspelled confirm field (confrim:true) is treated as unknown (40415).""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confrim": True, + }, + ) + assertFailureCode( + result, + UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="Misspelled 'confrim' should be rejected as unknown field", + ) + + +# --- setParameter rejection --- + + +def test_setFeatureCompatibilityVersion_via_setParameter_rejected(collection): + """Test the compatibility version cannot be set through the setParameter command.""" + result = execute_admin_command( + collection, + {"setParameter": 1, "featureCompatibilityVersion": "8.0"}, + ) + assertFailureCode( + result, + ILLEGAL_OPERATION_ERROR, + msg="setParameter should not accept featureCompatibilityVersion", + ) + + +# --- Argument Handling — Combinations --- + + +def test_setFeatureCompatibilityVersion_version_and_confirm_succeeds(collection): + """Test (version value + confirm:true) succeeds.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="version + confirm:true should succeed") + + +def test_setFeatureCompatibilityVersion_version_confirm_writeConcern_succeeds(collection): + """Test (version + confirm:true + writeConcern document) succeeds.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": 5000}, + }, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="version + confirm + writeConcern should succeed") + + +# --- Response Structure --- + + +def test_setFeatureCompatibilityVersion_success_contains_ok_1(collection): + """Test success response contains ok:1.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="Success response should contain ok:1") + + +def test_setFeatureCompatibilityVersion_error_contains_code(collection): + """Test error response contains ok:0, numeric code, and codeName.""" + result = execute_admin_command( + collection, + {"setFeatureCompatibilityVersion": "invalid_version", "confirm": True}, + ) + # MongoDB 8.2 uses code 4926900 for invalid FCV version strings + assertFailureCode(result, 4926900, msg="Invalid version should produce an error with code") + + +def test_setFeatureCompatibilityVersion_unknown_field_fires_before_state_change(collection): + """Test unknown-field rejection happens before any FCV state change.""" + original = _get_fcv(collection) + lower = "8.0" if original != "8.0" else "7.0" + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": lower, + "confirm": True, + "unknownField": 1, + }, + ) + assertFailureCode( + result, + UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="Unknown field should be rejected at parse time before any state change", + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py new file mode 100644 index 000000000..27ed2991c --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py @@ -0,0 +1,38 @@ +"""Tests for setFeatureCompatibilityVersion feature-not-supported behavior. + +Validates that setFeatureCompatibilityVersion is classified as an admin-only +command and returns the appropriate error when the feature is not supported. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + +# Error code 303 = CommandNotSupportedOnView or feature not supported +FEATURE_NOT_SUPPORTED_ERROR = 303 + + +def test_setFeatureCompatibilityVersion_unsupported_returns_303(collection): + """Test setFeatureCompatibilityVersion returns error code 303 when feature not supported.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8.0", "confirm": True} + ) + # This test is only meaningful on engines that do not support FCV (e.g., DocumentDB). + # On engines that support FCV, this test is expected to pass/succeed instead. + # We check if it returns 303 specifically for the not-supported case. + if ( + isinstance(result, Exception) + and hasattr(result, "code") + and result.code == FEATURE_NOT_SUPPORTED_ERROR + ): + assertFailureCode( + result, + FEATURE_NOT_SUPPORTED_ERROR, + msg="setFeatureCompatibilityVersion should return 303 when not supported", + ) + else: + # On engines that support FCV, this is a pass-through + pytest.skip("Engine supports setFeatureCompatibilityVersion") diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py new file mode 100644 index 000000000..dcef384af --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py @@ -0,0 +1,86 @@ +"""Tests for setFeatureCompatibilityVersion version field BSON type validation. + +Validates that the version field only accepts string type and rejects +all other BSON types with TYPE_MISMATCH_ERROR (14). +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.bson_type_validator import ( + BsonType, + BsonTypeTestCase, + generate_bson_rejection_test_cases, +) +from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def _get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +VERSION_TYPE_PARAM = [ + BsonTypeTestCase( + id="version_value", + msg="setFeatureCompatibilityVersion should only accept string for version", + keyword="setFeatureCompatibilityVersion", + valid_types=[BsonType.STRING], + skip_rejection_types=[BsonType.NULL], + default_error_code=TYPE_MISMATCH_ERROR, + requires={"confirm": True}, + ), +] + +VERSION_TYPE_REJECTIONS = generate_bson_rejection_test_cases(VERSION_TYPE_PARAM) + + +@pytest.mark.parametrize("bson_type,sample_value,spec", VERSION_TYPE_REJECTIONS) +def test_setFeatureCompatibilityVersion_version_type_rejected( + collection, bson_type, sample_value, spec +): + """Test version field rejects non-string BSON types with TYPE_MISMATCH_ERROR.""" + result = execute_admin_command( + collection, + {"setFeatureCompatibilityVersion": sample_value, "confirm": True}, + ) + assertFailureCode( + result, + spec.expected_code(bson_type), + msg=f"setFeatureCompatibilityVersion should reject {bson_type.value} for version", + ) + + +def test_setFeatureCompatibilityVersion_version_string_accepted(collection): + """Test version field accepts string type (the current version).""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept string version" + ) + + +def test_setFeatureCompatibilityVersion_version_null_rejected(collection): + """Test version field with null value is rejected (treated as missing field).""" + result = execute_admin_command( + collection, + {"setFeatureCompatibilityVersion": None, "confirm": True}, + ) + # null for version is treated as missing required field (code 40414) + assertFailureCode( + result, 40414, msg="setFeatureCompatibilityVersion should reject null for version" + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py new file mode 100644 index 000000000..14a3af224 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py @@ -0,0 +1,155 @@ +"""Tests for setFeatureCompatibilityVersion version value validation. + +Validates that the version field rejects unsupported, malformed, and +edge-case string values with FCV_INVALID_VERSION_ERROR (2). +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + +# MongoDB 8.2 uses this error code for invalid FCV version values +FCV_INVALID_VERSION_ERROR = 4926900 + + +def _get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +def test_setFeatureCompatibilityVersion_value_below_floor_rejected(collection): + """Test a value below the binary's supported floor is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "3.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Version below supported floor should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_value_above_max_rejected(collection): + """Test a value above the binary's max supported FCV is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "99.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Version above max supported should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_major_only_rejected(collection): + """Test a malformed value with no minor ('8') is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Major-only version string should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_full_semver_rejected(collection): + """Test a full-semver value ('8.0.0') is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8.0.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Full semver version string should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_leading_whitespace_rejected(collection): + """Test a value with leading whitespace (' 7.0') is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": " 7.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Version with leading whitespace should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_trailing_whitespace_rejected(collection): + """Test a value with trailing whitespace ('7.0 ') is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "7.0 ", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Version with trailing whitespace should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_empty_string_rejected(collection): + """Test an empty-string value is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Empty string version should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_zero_version_rejected(collection): + """Test '0.0' is rejected as an unsupported version.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "0.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="'0.0' should be rejected as unsupported" + ) + + +def test_setFeatureCompatibilityVersion_future_version_rejected(collection): + """Test '10.0' is rejected as a future unsupported version.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "10.0", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="'10.0' should be rejected as unsupported" + ) + + +def test_setFeatureCompatibilityVersion_non_ascii_rejected(collection): + """Test a non-ASCII/unicode-digit value is rejected.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8.0", "confirm": True} + ) + assertFailureCode(result, FCV_INVALID_VERSION_ERROR, msg="Non-ASCII version should be rejected") + + +def test_setFeatureCompatibilityVersion_very_long_string_rejected(collection): + """Test a very long string value is rejected without crash.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8" * 10000, "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Very long version string should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_intermediate_value_rejected(collection): + """Test setting to an intermediate value between supported versions fails.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "7.5", "confirm": True} + ) + assertFailureCode( + result, FCV_INVALID_VERSION_ERROR, msg="Intermediate version '7.5' should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_current_version_accepted(collection): + """Test the current binary version is accepted as a valid value.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="Current version should be accepted") diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py new file mode 100644 index 000000000..6a920fa8a --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py @@ -0,0 +1,257 @@ +"""Tests for setFeatureCompatibilityVersion writeConcern field validation. + +Validates writeConcern type validation, null-as-omitted behavior, +empty-doc acceptance, and wtimeout coercion. +""" + +import pytest +from bson import Decimal128, Int64 + +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def _get_fcv(collection): + """Read the current FCV.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +def test_setFeatureCompatibilityVersion_writeConcern_object_accepted(collection): + """Test writeConcern as object is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": 5000}, + }, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="writeConcern as object should be accepted") + + +def test_setFeatureCompatibilityVersion_writeConcern_empty_object_accepted(collection): + """Test writeConcern = {} (empty doc) is accepted with defaults applied.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {}, + }, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="writeConcern = {} should be accepted") + + +def test_setFeatureCompatibilityVersion_writeConcern_null_as_omitted(collection): + """Test writeConcern = null is treated as omitted (accepted).""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": None, + }, + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="writeConcern = null should be treated as omitted" + ) + + +def test_setFeatureCompatibilityVersion_writeConcern_string_rejected(collection): + """Test writeConcern as string fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": "majority", + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as string should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_int_rejected(collection): + """Test writeConcern as int fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": 1, + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as int should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_bool_rejected(collection): + """Test writeConcern as bool fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": True, + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as bool should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_array_rejected(collection): + """Test writeConcern as array fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": [{"w": 1}], + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as array should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_long_rejected(collection): + """Test writeConcern as long fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": Int64(1), + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as long should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_double_rejected(collection): + """Test writeConcern as double fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": 1.0, + }, + ) + assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as double should be rejected") + + +def test_setFeatureCompatibilityVersion_writeConcern_decimal_rejected(collection): + """Test writeConcern as decimal128 fails with TYPE_MISMATCH_ERROR.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": Decimal128("1"), + }, + ) + assertFailureCode( + result, TYPE_MISMATCH_ERROR, msg="writeConcern as decimal128 should be rejected" + ) + + +def test_setFeatureCompatibilityVersion_omitting_writeConcern_succeeds(collection): + """Test omitting writeConcern still succeeds (default wtimeout applied).""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="Omitting writeConcern should succeed") + + +def test_setFeatureCompatibilityVersion_wtimeout_double_coercion(collection): + """Test writeConcern.wtimeout as whole-number double (5000.0) is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": 5000.0}, + }, + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="wtimeout as whole-number double should be accepted" + ) + + +def test_setFeatureCompatibilityVersion_wtimeout_long_coercion(collection): + """Test writeConcern.wtimeout as Int64 is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": Int64(5000)}, + }, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="wtimeout as Int64 should be accepted") + + +def test_setFeatureCompatibilityVersion_wtimeout_decimal_whole_coercion(collection): + """Test writeConcern.wtimeout as whole-number Decimal128 coercion.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": Decimal128("5000")}, + }, + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="wtimeout as whole-number Decimal128 should be accepted" + ) + + +def test_setFeatureCompatibilityVersion_wtimeout_fractional_double_accepted(collection): + """Test writeConcern.wtimeout as fractional double (5000.5) is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": 5000.5}, + }, + ) + assertSuccessPartial( + result, {"ok": 1.0}, msg="wtimeout as fractional double should be accepted" + ) + + +def test_setFeatureCompatibilityVersion_wtimeout_negative_value_accepted(collection): + """Test writeConcern.wtimeout as negative value (-1) is accepted.""" + current_fcv = _get_fcv(collection) + result = execute_admin_command( + collection, + { + "setFeatureCompatibilityVersion": current_fcv, + "confirm": True, + "writeConcern": {"wtimeout": -1}, + }, + ) + assertSuccessPartial(result, {"ok": 1.0}, msg="wtimeout as negative value should be accepted") From 3fcd0e6233efc91dfecf28d6d1c008b54e0056a5 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 24 Jun 2026 15:26:45 -0700 Subject: [PATCH 02/12] add init.py Signed-off-by: Alina (Xi) Li --- .../commands/setFeatureCompatibilityVersion/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/__init__.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/__init__.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/__init__.py new file mode 100644 index 000000000..e69de29bb From 20f2c13652ab92a5316987658d4e193502c7937e Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 24 Jun 2026 16:01:21 -0700 Subject: [PATCH 03/12] fix according to docdb-test-review.md Signed-off-by: Alina (Xi) Li --- ...eCompatibilityVersion_confirm_semantics.py | 77 +++++------ ...patibilityVersion_confirm_type_coercion.py | 125 ++++++++++++------ ...atureCompatibilityVersion_core_behavior.py | 71 +++++----- ...t_setFeatureCompatibilityVersion_errors.py | 93 ++++--------- ...patibilityVersion_feature_not_supported.py | 38 ------ ...tibilityVersion_version_type_validation.py | 19 +-- ...ibilityVersion_version_value_validation.py | 97 +++++++++----- ...tibilityVersion_writeConcern_validation.py | 120 ++++++++++++----- ...st_smoke_setFeatureCompatibilityVersion.py | 46 ++++--- documentdb_tests/framework/error_codes.py | 3 + 10 files changed, 373 insertions(+), 316 deletions(-) delete mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py index f509280a4..02fc4ba8d 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py @@ -7,6 +7,7 @@ import pytest from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import FCV_CONFIRM_REQUIRED_ERROR from documentdb_tests.framework.executor import execute_admin_command pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -32,78 +33,72 @@ def _set_fcv(collection, version): ) -def _get_lower_fcv(current): +def _get_other_fcv(current): """Get a different supported FCV than the current one.""" return "8.0" if current != "8.0" else "8.2" def test_setFeatureCompatibilityVersion_confirm_true_allows_change(collection): - """Test confirm:true allows a version change to proceed.""" + """Test setFeatureCompatibilityVersion succeeds with confirm:true.""" original = _get_fcv(collection) - lower = _get_lower_fcv(original) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": lower, "confirm": True} + lower = _get_other_fcv(original) + result = _set_fcv(collection, lower) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should allow version change with confirm:true", ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm:true should allow version change") _set_fcv(collection, original) def test_setFeatureCompatibilityVersion_confirm_omitted_fails(collection): - """Test confirm omitted on a version change fails (ok:0), FCV unchanged.""" + """Test setFeatureCompatibilityVersion fails when confirm is omitted.""" original = _get_fcv(collection) - lower = _get_lower_fcv(original) + lower = _get_other_fcv(original) result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": lower}) - assertFailureCode(result, 7369100, msg="Should fail when confirm is omitted") + assertFailureCode( + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject version change without confirm", + ) def test_setFeatureCompatibilityVersion_confirm_false_fails(collection): - """Test confirm:false on a version change fails (ok:0), FCV unchanged.""" + """Test setFeatureCompatibilityVersion fails with confirm:false.""" original = _get_fcv(collection) - lower = _get_lower_fcv(original) + lower = _get_other_fcv(original) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": lower, "confirm": False} ) - assertFailureCode(result, 7369100, msg="Should fail when confirm is false") - - -def test_setFeatureCompatibilityVersion_confirm_omitted_returns_error_code(collection): - """Test the confirm-gate failure returns a stable error code.""" - original = _get_fcv(collection) - lower = _get_lower_fcv(original) - result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": lower}) - # Assert it failed with a numeric code (7369100 per JS test specs) - assertFailureCode(result, 7369100, msg="Omitting confirm should return error code 7369100") - - -def test_setFeatureCompatibilityVersion_confirm_false_returns_error_code(collection): - """Test confirm:false returns the same stable error code.""" - original = _get_fcv(collection) - lower = _get_lower_fcv(original) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": lower, "confirm": False} + assertFailureCode( + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject version change with confirm:false", ) - assertFailureCode(result, 7369100, msg="confirm:false should return error code 7369100") def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails(collection): - """Test upgrading without confirm also fails with error code 7369100.""" + """Test setFeatureCompatibilityVersion rejects upgrade without confirm.""" original = _get_fcv(collection) - lower = _get_lower_fcv(original) - # First downgrade + lower = _get_other_fcv(original) _set_fcv(collection, lower) - # Try upgrade without confirm result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": original}) - assertFailureCode(result, 7369100, msg="Upgrade without confirm should fail with 7369100") - # Restore + assertFailureCode( + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject upgrade without confirm", + ) _set_fcv(collection, original) def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds(collection): - """Test upgrading with confirm:true succeeds.""" + """Test setFeatureCompatibilityVersion succeeds on upgrade with confirm:true.""" original = _get_fcv(collection) - lower = _get_lower_fcv(original) - # First downgrade + lower = _get_other_fcv(original) _set_fcv(collection, lower) - # Upgrade with confirm result = _set_fcv(collection, original) - assertSuccessPartial(result, {"ok": 1.0}, msg="Upgrade with confirm:true should succeed") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed on upgrade with confirm:true", + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py index 15310928d..4e4f0beaf 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -8,25 +8,22 @@ from bson import Decimal128, Int64 from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial -from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.error_codes import FCV_CONFIRM_REQUIRED_ERROR, TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Error code when confirm is treated as falsy (not-true) -FCV_CONFIRM_REQUIRED_ERROR = 7369100 - def _get_fcv(collection): - """Read the current FCV.""" + """Read the current FCV via getParameter.""" result = execute_admin_command( collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) if isinstance(result, Exception): - return "8.0" + return "8.2" fcv_data = result.get("featureCompatibilityVersion", {}) if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.0") + return fcv_data.get("version", "8.2") return str(fcv_data) @@ -43,147 +40,185 @@ def _get_other_fcv(current): def test_setFeatureCompatibilityVersion_confirm_int_1_coercion(collection): - """Test confirm = 1 (int32) is accepted as true.""" + """Test setFeatureCompatibilityVersion accepts confirm=1 (int32) as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": 1} ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=1 (int) should be accepted as true") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=1 (int) as true", + ) _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_int_0_coercion(collection): - """Test confirm = 0 (int32) is treated as false (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=0 (int32) as false.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": 0} ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=0 should be treated as false" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=0 as false", ) def test_setFeatureCompatibilityVersion_confirm_double_1_coercion(collection): - """Test confirm = 1.0 (double) is accepted as true.""" + """Test setFeatureCompatibilityVersion accepts confirm=1.0 (double) as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": 1.0} ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=1.0 (double) should be accepted as true") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=1.0 (double) as true", + ) _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_double_0_coercion(collection): - """Test confirm = 0.0 (double) is treated as false (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=0.0 (double) as false.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": 0.0} ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=0.0 should be treated as false" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=0.0 as false", ) def test_setFeatureCompatibilityVersion_confirm_long_1_coercion(collection): - """Test confirm = Int64(1) is accepted as true.""" + """Test setFeatureCompatibilityVersion accepts confirm=Int64(1) as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(1)} ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=Int64(1) should be accepted as true") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Int64(1) as true", + ) _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_long_0_coercion(collection): - """Test confirm = Int64(0) is treated as false (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=Int64(0) as false.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(0)} ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=Int64(0) should be treated as false" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=Int64(0) as false", ) def test_setFeatureCompatibilityVersion_confirm_decimal_1_coercion(collection): - """Test confirm = Decimal128('1') is accepted as true.""" + """Test setFeatureCompatibilityVersion accepts confirm=Decimal128('1') as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("1")} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("1")}, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="confirm=Decimal128('1') should be accepted as true" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Decimal128('1') as true", ) _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_decimal_0_coercion(collection): - """Test confirm = Decimal128('0') is treated as false (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=Decimal128('0') as false.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("0")} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("0")}, ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=Decimal128('0') should be treated as false" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=Decimal128('0') as false", ) def test_setFeatureCompatibilityVersion_confirm_null_coercion(collection): - """Test confirm = null is treated as not-true (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=null as not-true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": None} ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=null should be treated as not-true" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=null as not-true", ) def test_setFeatureCompatibilityVersion_confirm_negative_zero_coercion(collection): - """Test confirm = -0.0 is treated as false (error 7369100).""" + """Test setFeatureCompatibilityVersion treats confirm=-0.0 as false.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": target, "confirm": -0.0} ) assertFailureCode( - result, FCV_CONFIRM_REQUIRED_ERROR, msg="confirm=-0.0 should be treated as false" + result, + FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=-0.0 as false", ) def test_setFeatureCompatibilityVersion_confirm_nan_coercion(collection): - """Test confirm = NaN is accepted as true (truthy in MongoDB bool coercion).""" + """Test setFeatureCompatibilityVersion accepts confirm=NaN as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": float("nan")} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": float("nan")}, + ) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=NaN as true", ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=NaN should be accepted as true") _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_infinity_coercion(collection): - """Test confirm = Infinity is accepted as true.""" + """Test setFeatureCompatibilityVersion accepts confirm=Infinity as true.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": float("inf")} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": float("inf")}, + ) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", ) - assertSuccessPartial(result, {"ok": 1.0}, msg="confirm=Infinity should be accepted as true") _set_fcv(collection, current) def test_setFeatureCompatibilityVersion_confirm_string_coercion(collection): - """Test confirm = string is rejected with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects confirm='true' (string).""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( @@ -192,31 +227,35 @@ def test_setFeatureCompatibilityVersion_confirm_string_coercion(collection): assertFailureCode( result, TYPE_MISMATCH_ERROR, - msg="confirm='true' (string) should be rejected with type mismatch", + msg="setFeatureCompatibilityVersion should reject confirm as string type", ) def test_setFeatureCompatibilityVersion_confirm_object_coercion(collection): - """Test confirm = object is rejected with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects confirm as object.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": {"a": 1}} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": {"a": 1}}, ) assertFailureCode( - result, TYPE_MISMATCH_ERROR, msg="confirm={} (object) should be rejected with type mismatch" + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject confirm as object type", ) def test_setFeatureCompatibilityVersion_confirm_array_coercion(collection): - """Test confirm = array is rejected with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects confirm as array.""" current = _get_fcv(collection) target = _get_other_fcv(current) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": [True]} + collection, + {"setFeatureCompatibilityVersion": target, "confirm": [True]}, ) assertFailureCode( result, TYPE_MISMATCH_ERROR, - msg="confirm=[True] (array) should be rejected with type mismatch", + msg="setFeatureCompatibilityVersion should reject confirm as array type", ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 5487bd0ba..23c236000 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -18,10 +18,10 @@ def _get_fcv(collection): collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) if isinstance(result, Exception): - return None + return "8.2" fcv_data = result.get("featureCompatibilityVersion", {}) if isinstance(fcv_data, dict): - return fcv_data.get("version") + return fcv_data.get("version", "8.2") return str(fcv_data) @@ -32,33 +32,36 @@ def _set_fcv(collection, version): ) -def test_setFeatureCompatibilityVersion_set_current_version_succeeds(collection): - """Test setting FCV to the deployment's supported version with confirm:true succeeds.""" - current_fcv = _get_fcv(collection) - result = _set_fcv(collection, current_fcv) - assertSuccessPartial(result, {"ok": 1.0}, msg="Setting FCV to current version should succeed") +def _get_other_fcv(current): + """Get a different supported FCV than the current one.""" + return "8.0" if current != "8.0" else "8.2" -def test_setFeatureCompatibilityVersion_idempotent_same_value(collection): - """Test setting FCV to the value it already holds is idempotent and returns ok:1.""" +def test_setFeatureCompatibilityVersion_set_current_version_succeeds(collection): + """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" current_fcv = _get_fcv(collection) - _set_fcv(collection, current_fcv) result = _set_fcv(collection, current_fcv) assertSuccessPartial( - result, {"ok": 1.0}, msg="Re-setting FCV to same value should be idempotent" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when setting the current version", ) -def test_setFeatureCompatibilityVersion_safe_retry(collection): - """Test re-running the identical successful command again succeeds.""" +def test_setFeatureCompatibilityVersion_idempotent_same_value(collection): + """Test setFeatureCompatibilityVersion is idempotent when re-setting the same value.""" current_fcv = _get_fcv(collection) _set_fcv(collection, current_fcv) result = _set_fcv(collection, current_fcv) - assertSuccessPartial(result, {"ok": 1.0}, msg="Safe retry of the same command should succeed") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should be idempotent when re-setting the same value", + ) def test_setFeatureCompatibilityVersion_getParameter_reads_back_value(collection): - """Test getParameter featureCompatibilityVersion reads back the most recently set value.""" + """Test getParameter reads back the most recently set FCV.""" current_fcv = _get_fcv(collection) _set_fcv(collection, current_fcv) result = execute_admin_command( @@ -67,7 +70,7 @@ def test_setFeatureCompatibilityVersion_getParameter_reads_back_value(collection assertSuccessPartial( result, {"ok": 1.0}, - msg="getParameter should succeed after setFeatureCompatibilityVersion", + msg="setFeatureCompatibilityVersion should persist and be readable via getParameter", ) @@ -77,41 +80,42 @@ def test_setFeatureCompatibilityVersion_fresh_deployment_default_fcv(collection) collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) assertSuccessPartial( - result, {"ok": 1.0}, msg="getParameter featureCompatibilityVersion should succeed" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should have a readable default on a fresh deployment", ) def test_setFeatureCompatibilityVersion_downgrade_with_confirm(collection): - """Test the compatibility version can be downgraded with confirm.""" + """Test setFeatureCompatibilityVersion can downgrade with confirm:true.""" original_fcv = _get_fcv(collection) - # Use the other supported version (8.0 or 8.2) - other_fcv = "8.0" if original_fcv != "8.0" else "8.2" - + other_fcv = _get_other_fcv(original_fcv) result = _set_fcv(collection, other_fcv) - assertSuccessPartial(result, {"ok": 1.0}, msg="Changing FCV with confirm:true should succeed") - # Restore original + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when changing version with confirm", + ) _set_fcv(collection, original_fcv) def test_setFeatureCompatibilityVersion_upgrade_with_confirm(collection): - """Test the compatibility version can be upgraded back to the latest supported version.""" + """Test setFeatureCompatibilityVersion can upgrade back to the original version.""" original_fcv = _get_fcv(collection) - other_fcv = "8.0" if original_fcv != "8.0" else "8.2" - - # Change first + other_fcv = _get_other_fcv(original_fcv) _set_fcv(collection, other_fcv) - # Change back result = _set_fcv(collection, original_fcv) assertSuccessPartial( - result, {"ok": 1.0}, msg="Changing FCV back with confirm:true should succeed" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when upgrading back", ) def test_setFeatureCompatibilityVersion_getParameter_reflects_change(collection): - """Test that after a successful setFeatureCompatibilityVersion the read-back matches.""" + """Test getParameter reflects the FCV after a change.""" original_fcv = _get_fcv(collection) - other_fcv = "8.0" if original_fcv != "8.0" else "8.2" - + other_fcv = _get_other_fcv(original_fcv) _set_fcv(collection, other_fcv) result = execute_admin_command( collection, {"getParameter": 1, "featureCompatibilityVersion": 1} @@ -119,7 +123,6 @@ def test_setFeatureCompatibilityVersion_getParameter_reflects_change(collection) assertSuccessPartial( result, {"ok": 1.0, "featureCompatibilityVersion": {"version": other_fcv}}, - msg=f"getParameter should reflect changed FCV to '{other_fcv}'", + msg="setFeatureCompatibilityVersion should be reflected in getParameter after a change", ) - # Restore _set_fcv(collection, original_fcv) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 404352ee3..3930691ff 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -1,13 +1,14 @@ """Tests for setFeatureCompatibilityVersion error cases. -Covers admin-database-only enforcement, unknown/extra fields, argument -handling combinations, response structure, and setParameter rejection. +Covers admin-database-only enforcement, unknown/extra fields, +response structure, and setParameter rejection. """ import pytest from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial from documentdb_tests.framework.error_codes import ( + FCV_INVALID_VERSION_ERROR, ILLEGAL_OPERATION_ERROR, UNAUTHORIZED_ERROR, UNRECOGNIZED_COMMAND_FIELD_ERROR, @@ -18,7 +19,7 @@ def _get_fcv(collection): - """Read the current FCV.""" + """Read the current FCV via getParameter.""" result = execute_admin_command( collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) @@ -30,34 +31,34 @@ def _get_fcv(collection): return str(fcv_data) -# --- Admin-Database-Only Enforcement --- - - def test_setFeatureCompatibilityVersion_on_admin_db_accepted(collection): - """Test command on the admin database is accepted.""" + """Test setFeatureCompatibilityVersion succeeds on the admin database.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} ) - assertSuccessPartial(result, {"ok": 1.0}, msg="Command on admin db should be accepted") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed on the admin database", + ) def test_setFeatureCompatibilityVersion_on_user_db_fails(collection): - """Test command on a user database fails with UNAUTHORIZED_ERROR (13).""" + """Test setFeatureCompatibilityVersion fails on a user database.""" current_fcv = _get_fcv(collection) result = execute_command( collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} ) assertFailureCode( - result, UNAUTHORIZED_ERROR, msg="Command on user db should fail with UNAUTHORIZED_ERROR" + result, + UNAUTHORIZED_ERROR, + msg="setFeatureCompatibilityVersion should reject execution on a user database", ) -# --- Unknown / Extra Fields --- - - def test_setFeatureCompatibilityVersion_unrecognized_field_rejected(collection): - """Test an unrecognized top-level field fails with UNRECOGNIZED_COMMAND_FIELD_ERROR.""" + """Test setFeatureCompatibilityVersion rejects an unrecognized top-level field.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -70,12 +71,12 @@ def test_setFeatureCompatibilityVersion_unrecognized_field_rejected(collection): assertFailureCode( result, UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="Unrecognized field should be rejected with 40415", + msg="setFeatureCompatibilityVersion should reject unrecognized fields", ) def test_setFeatureCompatibilityVersion_misspelled_confirm_rejected(collection): - """Test a misspelled confirm field (confrim:true) is treated as unknown (40415).""" + """Test setFeatureCompatibilityVersion rejects a misspelled confirm field.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -87,15 +88,12 @@ def test_setFeatureCompatibilityVersion_misspelled_confirm_rejected(collection): assertFailureCode( result, UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="Misspelled 'confrim' should be rejected as unknown field", + msg="setFeatureCompatibilityVersion should reject misspelled 'confrim' as unknown field", ) -# --- setParameter rejection --- - - def test_setFeatureCompatibilityVersion_via_setParameter_rejected(collection): - """Test the compatibility version cannot be set through the setParameter command.""" + """Test setFeatureCompatibilityVersion cannot be set through setParameter.""" result = execute_admin_command( collection, {"setParameter": 1, "featureCompatibilityVersion": "8.0"}, @@ -103,60 +101,25 @@ def test_setFeatureCompatibilityVersion_via_setParameter_rejected(collection): assertFailureCode( result, ILLEGAL_OPERATION_ERROR, - msg="setParameter should not accept featureCompatibilityVersion", - ) - - -# --- Argument Handling — Combinations --- - - -def test_setFeatureCompatibilityVersion_version_and_confirm_succeeds(collection): - """Test (version value + confirm:true) succeeds.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} - ) - assertSuccessPartial(result, {"ok": 1.0}, msg="version + confirm:true should succeed") - - -def test_setFeatureCompatibilityVersion_version_confirm_writeConcern_succeeds(collection): - """Test (version + confirm:true + writeConcern document) succeeds.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, - "confirm": True, - "writeConcern": {"wtimeout": 5000}, - }, + msg="setFeatureCompatibilityVersion should not be settable via setParameter", ) - assertSuccessPartial(result, {"ok": 1.0}, msg="version + confirm + writeConcern should succeed") - - -# --- Response Structure --- - - -def test_setFeatureCompatibilityVersion_success_contains_ok_1(collection): - """Test success response contains ok:1.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} - ) - assertSuccessPartial(result, {"ok": 1.0}, msg="Success response should contain ok:1") def test_setFeatureCompatibilityVersion_error_contains_code(collection): - """Test error response contains ok:0, numeric code, and codeName.""" + """Test setFeatureCompatibilityVersion error response contains a numeric code.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "invalid_version", "confirm": True}, ) - # MongoDB 8.2 uses code 4926900 for invalid FCV version strings - assertFailureCode(result, 4926900, msg="Invalid version should produce an error with code") + assertFailureCode( + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should return a numeric error code for invalid version", + ) def test_setFeatureCompatibilityVersion_unknown_field_fires_before_state_change(collection): - """Test unknown-field rejection happens before any FCV state change.""" + """Test setFeatureCompatibilityVersion rejects unknown fields before any state change.""" original = _get_fcv(collection) lower = "8.0" if original != "8.0" else "7.0" result = execute_admin_command( @@ -170,5 +133,5 @@ def test_setFeatureCompatibilityVersion_unknown_field_fires_before_state_change( assertFailureCode( result, UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="Unknown field should be rejected at parse time before any state change", + msg="setFeatureCompatibilityVersion should reject unknown fields before changing state", ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py deleted file mode 100644 index 27ed2991c..000000000 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Tests for setFeatureCompatibilityVersion feature-not-supported behavior. - -Validates that setFeatureCompatibilityVersion is classified as an admin-only -command and returns the appropriate error when the feature is not supported. -""" - -import pytest - -from documentdb_tests.framework.assertions import assertFailureCode -from documentdb_tests.framework.executor import execute_admin_command - -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - -# Error code 303 = CommandNotSupportedOnView or feature not supported -FEATURE_NOT_SUPPORTED_ERROR = 303 - - -def test_setFeatureCompatibilityVersion_unsupported_returns_303(collection): - """Test setFeatureCompatibilityVersion returns error code 303 when feature not supported.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "8.0", "confirm": True} - ) - # This test is only meaningful on engines that do not support FCV (e.g., DocumentDB). - # On engines that support FCV, this test is expected to pass/succeed instead. - # We check if it returns 303 specifically for the not-supported case. - if ( - isinstance(result, Exception) - and hasattr(result, "code") - and result.code == FEATURE_NOT_SUPPORTED_ERROR - ): - assertFailureCode( - result, - FEATURE_NOT_SUPPORTED_ERROR, - msg="setFeatureCompatibilityVersion should return 303 when not supported", - ) - else: - # On engines that support FCV, this is a pass-through - pytest.skip("Engine supports setFeatureCompatibilityVersion") diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py index dcef384af..5656556dc 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py @@ -1,7 +1,7 @@ """Tests for setFeatureCompatibilityVersion version field BSON type validation. Validates that the version field only accepts string type and rejects -all other BSON types with TYPE_MISMATCH_ERROR (14). +all other BSON types with TYPE_MISMATCH_ERROR. """ import pytest @@ -12,7 +12,7 @@ BsonTypeTestCase, generate_bson_rejection_test_cases, ) -from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.error_codes import MISSING_FIELD_ERROR, TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -50,7 +50,7 @@ def _get_fcv(collection): def test_setFeatureCompatibilityVersion_version_type_rejected( collection, bson_type, sample_value, spec ): - """Test version field rejects non-string BSON types with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects non-string BSON types for version.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": sample_value, "confirm": True}, @@ -63,24 +63,27 @@ def test_setFeatureCompatibilityVersion_version_type_rejected( def test_setFeatureCompatibilityVersion_version_string_accepted(collection): - """Test version field accepts string type (the current version).""" + """Test setFeatureCompatibilityVersion accepts string type for version.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept string version" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept string for version", ) def test_setFeatureCompatibilityVersion_version_null_rejected(collection): - """Test version field with null value is rejected (treated as missing field).""" + """Test setFeatureCompatibilityVersion rejects null for version.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": None, "confirm": True}, ) - # null for version is treated as missing required field (code 40414) assertFailureCode( - result, 40414, msg="setFeatureCompatibilityVersion should reject null for version" + result, + MISSING_FIELD_ERROR, + msg="setFeatureCompatibilityVersion should reject null for version", ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py index 14a3af224..116d84f28 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py @@ -1,19 +1,17 @@ """Tests for setFeatureCompatibilityVersion version value validation. Validates that the version field rejects unsupported, malformed, and -edge-case string values with FCV_INVALID_VERSION_ERROR (2). +edge-case string values. """ import pytest from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import FCV_INVALID_VERSION_ERROR from documentdb_tests.framework.executor import execute_admin_command pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# MongoDB 8.2 uses this error code for invalid FCV version values -FCV_INVALID_VERSION_ERROR = 4926900 - def _get_fcv(collection): """Read the current FCV via getParameter.""" @@ -29,127 +27,160 @@ def _get_fcv(collection): def test_setFeatureCompatibilityVersion_value_below_floor_rejected(collection): - """Test a value below the binary's supported floor is rejected.""" + """Test setFeatureCompatibilityVersion rejects a version below the supported floor.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "3.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Version below supported floor should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject version below supported floor", ) def test_setFeatureCompatibilityVersion_value_above_max_rejected(collection): - """Test a value above the binary's max supported FCV is rejected.""" + """Test setFeatureCompatibilityVersion rejects a version above the supported max.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "99.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Version above max supported should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject version above supported max", ) def test_setFeatureCompatibilityVersion_major_only_rejected(collection): - """Test a malformed value with no minor ('8') is rejected.""" + """Test setFeatureCompatibilityVersion rejects a major-only version string.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "8", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Major-only version string should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject major-only version string", ) def test_setFeatureCompatibilityVersion_full_semver_rejected(collection): - """Test a full-semver value ('8.0.0') is rejected.""" + """Test setFeatureCompatibilityVersion rejects a full semver string.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "8.0.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Full semver version string should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject full semver version string", ) def test_setFeatureCompatibilityVersion_leading_whitespace_rejected(collection): - """Test a value with leading whitespace (' 7.0') is rejected.""" + """Test setFeatureCompatibilityVersion rejects a version with leading whitespace.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": " 7.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Version with leading whitespace should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject version with leading whitespace", ) def test_setFeatureCompatibilityVersion_trailing_whitespace_rejected(collection): - """Test a value with trailing whitespace ('7.0 ') is rejected.""" + """Test setFeatureCompatibilityVersion rejects a version with trailing whitespace.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "7.0 ", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Version with trailing whitespace should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject version with trailing whitespace", ) def test_setFeatureCompatibilityVersion_empty_string_rejected(collection): - """Test an empty-string value is rejected.""" + """Test setFeatureCompatibilityVersion rejects an empty string.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Empty string version should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject empty string version", ) def test_setFeatureCompatibilityVersion_zero_version_rejected(collection): - """Test '0.0' is rejected as an unsupported version.""" + """Test setFeatureCompatibilityVersion rejects '0.0' as unsupported.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "0.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="'0.0' should be rejected as unsupported" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject '0.0' as unsupported", ) def test_setFeatureCompatibilityVersion_future_version_rejected(collection): - """Test '10.0' is rejected as a future unsupported version.""" + """Test setFeatureCompatibilityVersion rejects a future unsupported version.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "10.0", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="'10.0' should be rejected as unsupported" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject future unsupported version", ) def test_setFeatureCompatibilityVersion_non_ascii_rejected(collection): - """Test a non-ASCII/unicode-digit value is rejected.""" + """Test setFeatureCompatibilityVersion rejects non-ASCII digit characters.""" result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "8.0", "confirm": True} + collection, + {"setFeatureCompatibilityVersion": "\uff18.\uff10", "confirm": True}, + ) + assertFailureCode( + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject non-ASCII version string", ) - assertFailureCode(result, FCV_INVALID_VERSION_ERROR, msg="Non-ASCII version should be rejected") def test_setFeatureCompatibilityVersion_very_long_string_rejected(collection): - """Test a very long string value is rejected without crash.""" + """Test setFeatureCompatibilityVersion rejects a very long string.""" result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "8" * 10000, "confirm": True} + collection, + {"setFeatureCompatibilityVersion": "8" * 10_000, "confirm": True}, ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Very long version string should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject a very long version string", ) def test_setFeatureCompatibilityVersion_intermediate_value_rejected(collection): - """Test setting to an intermediate value between supported versions fails.""" + """Test setFeatureCompatibilityVersion rejects an intermediate version value.""" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": "7.5", "confirm": True} ) assertFailureCode( - result, FCV_INVALID_VERSION_ERROR, msg="Intermediate version '7.5' should be rejected" + result, + FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject intermediate version value", ) def test_setFeatureCompatibilityVersion_current_version_accepted(collection): - """Test the current binary version is accepted as a valid value.""" + """Test setFeatureCompatibilityVersion accepts the current binary version.""" current_fcv = _get_fcv(collection) result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} + collection, + {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, + ) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept the current binary version", ) - assertSuccessPartial(result, {"ok": 1.0}, msg="Current version should be accepted") diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py index 6a920fa8a..0cb2d1101 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py @@ -15,7 +15,7 @@ def _get_fcv(collection): - """Read the current FCV.""" + """Read the current FCV via getParameter.""" result = execute_admin_command( collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) @@ -28,7 +28,7 @@ def _get_fcv(collection): def test_setFeatureCompatibilityVersion_writeConcern_object_accepted(collection): - """Test writeConcern as object is accepted.""" + """Test setFeatureCompatibilityVersion accepts writeConcern as object.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -38,11 +38,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_object_accepted(collection) "writeConcern": {"wtimeout": 5000}, }, ) - assertSuccessPartial(result, {"ok": 1.0}, msg="writeConcern as object should be accepted") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept writeConcern as object", + ) def test_setFeatureCompatibilityVersion_writeConcern_empty_object_accepted(collection): - """Test writeConcern = {} (empty doc) is accepted with defaults applied.""" + """Test setFeatureCompatibilityVersion accepts writeConcern as empty object.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -52,11 +56,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_empty_object_accepted(colle "writeConcern": {}, }, ) - assertSuccessPartial(result, {"ok": 1.0}, msg="writeConcern = {} should be accepted") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept writeConcern as empty object", + ) def test_setFeatureCompatibilityVersion_writeConcern_null_as_omitted(collection): - """Test writeConcern = null is treated as omitted (accepted).""" + """Test setFeatureCompatibilityVersion treats writeConcern=null as omitted.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -67,12 +75,14 @@ def test_setFeatureCompatibilityVersion_writeConcern_null_as_omitted(collection) }, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="writeConcern = null should be treated as omitted" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should treat writeConcern=null as omitted", ) def test_setFeatureCompatibilityVersion_writeConcern_string_rejected(collection): - """Test writeConcern as string fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as string.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -82,11 +92,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_string_rejected(collection) "writeConcern": "majority", }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as string should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as string", + ) def test_setFeatureCompatibilityVersion_writeConcern_int_rejected(collection): - """Test writeConcern as int fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as int.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -96,11 +110,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_int_rejected(collection): "writeConcern": 1, }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as int should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as int", + ) def test_setFeatureCompatibilityVersion_writeConcern_bool_rejected(collection): - """Test writeConcern as bool fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as bool.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -110,11 +128,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_bool_rejected(collection): "writeConcern": True, }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as bool should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as bool", + ) def test_setFeatureCompatibilityVersion_writeConcern_array_rejected(collection): - """Test writeConcern as array fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as array.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -124,11 +146,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_array_rejected(collection): "writeConcern": [{"w": 1}], }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as array should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as array", + ) def test_setFeatureCompatibilityVersion_writeConcern_long_rejected(collection): - """Test writeConcern as long fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as long.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -138,11 +164,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_long_rejected(collection): "writeConcern": Int64(1), }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as long should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as long", + ) def test_setFeatureCompatibilityVersion_writeConcern_double_rejected(collection): - """Test writeConcern as double fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as double.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -152,11 +182,15 @@ def test_setFeatureCompatibilityVersion_writeConcern_double_rejected(collection) "writeConcern": 1.0, }, ) - assertFailureCode(result, TYPE_MISMATCH_ERROR, msg="writeConcern as double should be rejected") + assertFailureCode( + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as double", + ) def test_setFeatureCompatibilityVersion_writeConcern_decimal_rejected(collection): - """Test writeConcern as decimal128 fails with TYPE_MISMATCH_ERROR.""" + """Test setFeatureCompatibilityVersion rejects writeConcern as Decimal128.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -167,22 +201,28 @@ def test_setFeatureCompatibilityVersion_writeConcern_decimal_rejected(collection }, ) assertFailureCode( - result, TYPE_MISMATCH_ERROR, msg="writeConcern as decimal128 should be rejected" + result, + TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as Decimal128", ) def test_setFeatureCompatibilityVersion_omitting_writeConcern_succeeds(collection): - """Test omitting writeConcern still succeeds (default wtimeout applied).""" + """Test setFeatureCompatibilityVersion succeeds when writeConcern is omitted.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, ) - assertSuccessPartial(result, {"ok": 1.0}, msg="Omitting writeConcern should succeed") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when writeConcern is omitted", + ) def test_setFeatureCompatibilityVersion_wtimeout_double_coercion(collection): - """Test writeConcern.wtimeout as whole-number double (5000.0) is accepted.""" + """Test setFeatureCompatibilityVersion accepts wtimeout as whole-number double.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -193,12 +233,14 @@ def test_setFeatureCompatibilityVersion_wtimeout_double_coercion(collection): }, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="wtimeout as whole-number double should be accepted" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number double", ) def test_setFeatureCompatibilityVersion_wtimeout_long_coercion(collection): - """Test writeConcern.wtimeout as Int64 is accepted.""" + """Test setFeatureCompatibilityVersion accepts wtimeout as Int64.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -208,11 +250,15 @@ def test_setFeatureCompatibilityVersion_wtimeout_long_coercion(collection): "writeConcern": {"wtimeout": Int64(5000)}, }, ) - assertSuccessPartial(result, {"ok": 1.0}, msg="wtimeout as Int64 should be accepted") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as Int64", + ) def test_setFeatureCompatibilityVersion_wtimeout_decimal_whole_coercion(collection): - """Test writeConcern.wtimeout as whole-number Decimal128 coercion.""" + """Test setFeatureCompatibilityVersion accepts wtimeout as whole-number Decimal128.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -223,12 +269,14 @@ def test_setFeatureCompatibilityVersion_wtimeout_decimal_whole_coercion(collecti }, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="wtimeout as whole-number Decimal128 should be accepted" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number Decimal128", ) def test_setFeatureCompatibilityVersion_wtimeout_fractional_double_accepted(collection): - """Test writeConcern.wtimeout as fractional double (5000.5) is accepted.""" + """Test setFeatureCompatibilityVersion accepts wtimeout as fractional double.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -239,12 +287,14 @@ def test_setFeatureCompatibilityVersion_wtimeout_fractional_double_accepted(coll }, ) assertSuccessPartial( - result, {"ok": 1.0}, msg="wtimeout as fractional double should be accepted" + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as fractional double", ) def test_setFeatureCompatibilityVersion_wtimeout_negative_value_accepted(collection): - """Test writeConcern.wtimeout as negative value (-1) is accepted.""" + """Test setFeatureCompatibilityVersion accepts wtimeout as negative value.""" current_fcv = _get_fcv(collection) result = execute_admin_command( collection, @@ -254,4 +304,8 @@ def test_setFeatureCompatibilityVersion_wtimeout_negative_value_accepted(collect "writeConcern": {"wtimeout": -1}, }, ) - assertSuccessPartial(result, {"ok": 1.0}, msg="wtimeout as negative value should be accepted") + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as negative value", + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py index f343fb194..5c900a241 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py @@ -12,30 +12,34 @@ pytestmark = [pytest.mark.smoke, pytest.mark.no_parallel] -def test_smoke_setFeatureCompatibilityVersion(collection): - """Test basic setFeatureCompatibilityVersion behavior.""" - get_result = execute_admin_command( +def _get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( collection, {"getParameter": 1, "featureCompatibilityVersion": 1} ) - - original_fcv = "8.2" - if not isinstance(get_result, Exception): - fcv_data = get_result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - original_fcv = fcv_data.get("version", "8.2") - else: - original_fcv = str(fcv_data) - - new_fcv = "8.2" if original_fcv != "8.2" else "8.0" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": new_fcv, "confirm": True} + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) + + +def _set_fcv(collection, version): + """Set FCV with confirm:true.""" + return execute_admin_command( + collection, {"setFeatureCompatibilityVersion": version, "confirm": True} ) - expected = {"ok": 1.0} - assertSuccessPartial( - result, expected, msg="Should support setFeatureCompatibilityVersion command" - ) - execute_admin_command( - collection, {"setFeatureCompatibilityVersion": original_fcv, "confirm": True} +def test_smoke_setFeatureCompatibilityVersion(collection): + """Test basic setFeatureCompatibilityVersion behavior.""" + original_fcv = _get_fcv(collection) + new_fcv = "8.0" if original_fcv != "8.0" else "8.2" + result = _set_fcv(collection, new_fcv) + assertSuccessPartial( + result, + {"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed with a valid version change", ) + _set_fcv(collection, original_fcv) diff --git a/documentdb_tests/framework/error_codes.py b/documentdb_tests/framework/error_codes.py index 423b3fe65..db111a2fe 100644 --- a/documentdb_tests/framework/error_codes.py +++ b/documentdb_tests/framework/error_codes.py @@ -58,6 +58,7 @@ CHANGE_STREAM_HISTORY_LOST_ERROR = 286 NO_QUERY_EXECUTION_PLANS_ERROR = 291 QUERY_EXCEEDED_MEMORY_NO_DISK_USE_ERROR = 292 +COMMAND_NOT_SUPPORTED_ERROR = 303 API_VERSION_ERROR = 322 API_STRICT_ERROR = 323 COLLECTION_UUID_MISMATCH_ERROR = 361 @@ -446,6 +447,7 @@ MODULO_BY_ZERO_V2_ERROR = 4848403 API_VERSION_REQUIRED_ERROR = 4886600 LET_FIELD_REFERENCE_IN_VALUE_ERROR = 4890500 +FCV_INVALID_VERSION_ERROR = 4926900 COLLECTION_UUID_NOT_SUPPORTED_AGNOSTIC_ERROR = 4928901 ARRAY_TO_OBJECT_NULL_BYTE_PAIR_KEY_ERROR = 4940400 ARRAY_TO_OBJECT_NULL_BYTE_KV_KEY_ERROR = 4940401 @@ -516,6 +518,7 @@ WILDCARD_MULTIPLE_FIELDS_ERROR = 7246201 WILDCARD_STRING_TYPE_ERROR = 7246202 OUT_TIMESERIES_COLLECTION_TYPE_ERROR = 7268700 +FCV_CONFIRM_REQUIRED_ERROR = 7369100 OUT_TIMESERIES_OPTIONS_MISMATCH_ERROR = 7406103 SORT_DUPLICATE_KEY_ERROR = 7472500 N_ACCUMULATOR_INVALID_N_ERROR = 7548606 From 6596a1cd7774b99d5813975a0207a3b6aa32b14c Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 15:29:51 -0700 Subject: [PATCH 04/12] remove errror precedence test Signed-off-by: Alina (Xi) Li --- ...t_setFeatureCompatibilityVersion_errors.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 3930691ff..1559a86b1 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -116,22 +116,3 @@ def test_setFeatureCompatibilityVersion_error_contains_code(collection): FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should return a numeric error code for invalid version", ) - - -def test_setFeatureCompatibilityVersion_unknown_field_fires_before_state_change(collection): - """Test setFeatureCompatibilityVersion rejects unknown fields before any state change.""" - original = _get_fcv(collection) - lower = "8.0" if original != "8.0" else "7.0" - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": lower, - "confirm": True, - "unknownField": 1, - }, - ) - assertFailureCode( - result, - UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="setFeatureCompatibilityVersion should reject unknown fields before changing state", - ) From da5eea5d5ba98ed70fc00eac988a94863cba2df1 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 15:40:57 -0700 Subject: [PATCH 05/12] convert test cases to use CommandTestCase Signed-off-by: Alina (Xi) Li --- ...eCompatibilityVersion_confirm_semantics.py | 171 ++++++-- ...patibilityVersion_confirm_type_coercion.py | 380 +++++++++-------- ...atureCompatibilityVersion_core_behavior.py | 207 +++++++--- ...t_setFeatureCompatibilityVersion_errors.py | 192 ++++++--- ...tibilityVersion_version_type_validation.py | 71 +++- ...ibilityVersion_version_value_validation.py | 248 +++++------ ...tibilityVersion_writeConcern_validation.py | 385 ++++++++---------- 7 files changed, 922 insertions(+), 732 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py index 02fc4ba8d..c9d8fc87c 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py @@ -6,9 +6,14 @@ import pytest -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import FCV_CONFIRM_REQUIRED_ERROR from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -38,67 +43,163 @@ def _get_other_fcv(current): return "8.0" if current != "8.0" else "8.2" -def test_setFeatureCompatibilityVersion_confirm_true_allows_change(collection): +# Property [Confirm Required]: confirm:true is required for version changes. +CONFIRM_TRUE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "confirm_true_allows_change", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should allow version change with confirm:true", + ), +] + +# Property [Confirm Omitted]: omitting confirm prevents version changes. +CONFIRM_OMITTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "confirm_omitted", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV"}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject version change without confirm", + ), +] + +# Property [Confirm False]: confirm:false prevents version changes. +CONFIRM_FALSE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "confirm_false", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": False}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject version change with confirm:false", + ), +] + +# Property [Upgrade Without Confirm]: upgrade without confirm is rejected. +UPGRADE_NO_CONFIRM_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "upgrade_without_confirm", + command=lambda ctx: {"setFeatureCompatibilityVersion": "ORIGINAL_FCV"}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should reject upgrade without confirm", + ), +] + +# Property [Upgrade With Confirm]: upgrade with confirm:true succeeds. +UPGRADE_WITH_CONFIRM_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "upgrade_with_confirm", + command=lambda ctx: {"setFeatureCompatibilityVersion": "ORIGINAL_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed on upgrade with confirm:true", + ), +] + + +def _resolve_fcv_placeholders(command_dict, **replacements): + """Replace FCV placeholders in a command dict.""" + resolved = {} + for k, v in command_dict.items(): + if isinstance(v, str) and v in replacements: + resolved[k] = replacements[v] + else: + resolved[k] = v + return resolved + + +@pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUE_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_true_allows_change( + database_client, collection, test +): """Test setFeatureCompatibilityVersion succeeds with confirm:true.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - lower = _get_other_fcv(original) - result = _set_fcv(collection, lower) - assertSuccessPartial( + other = _get_other_fcv(original) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should allow version change with confirm:true", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) _set_fcv(collection, original) -def test_setFeatureCompatibilityVersion_confirm_omitted_fails(collection): +@pytest.mark.parametrize("test", pytest_params(CONFIRM_OMITTED_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, collection, test): """Test setFeatureCompatibilityVersion fails when confirm is omitted.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - lower = _get_other_fcv(original) - result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": lower}) - assertFailureCode( + other = _get_other_fcv(original) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + result = execute_admin_command(collection, cmd) + assertResult( result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should reject version change without confirm", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_confirm_false_fails(collection): +@pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSE_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_false_fails(database_client, collection, test): """Test setFeatureCompatibilityVersion fails with confirm:false.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - lower = _get_other_fcv(original) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": lower, "confirm": False} - ) - assertFailureCode( + other = _get_other_fcv(original) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + result = execute_admin_command(collection, cmd) + assertResult( result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should reject version change with confirm:false", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails(collection): +@pytest.mark.parametrize("test", pytest_params(UPGRADE_NO_CONFIRM_TESTS)) +def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( + database_client, collection, test +): """Test setFeatureCompatibilityVersion rejects upgrade without confirm.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - lower = _get_other_fcv(original) - _set_fcv(collection, lower) - result = execute_admin_command(collection, {"setFeatureCompatibilityVersion": original}) - assertFailureCode( + other = _get_other_fcv(original) + _set_fcv(collection, other) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + result = execute_admin_command(collection, cmd) + assertResult( result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should reject upgrade without confirm", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) _set_fcv(collection, original) -def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds(collection): +@pytest.mark.parametrize("test", pytest_params(UPGRADE_WITH_CONFIRM_TESTS)) +def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds( + database_client, collection, test +): """Test setFeatureCompatibilityVersion succeeds on upgrade with confirm:true.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - lower = _get_other_fcv(original) - _set_fcv(collection, lower) - result = _set_fcv(collection, original) - assertSuccessPartial( + other = _get_other_fcv(original) + _set_fcv(collection, other) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed on upgrade with confirm:true", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py index 4e4f0beaf..aba759d08 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -7,9 +7,14 @@ import pytest from bson import Decimal128, Int64 -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import FCV_CONFIRM_REQUIRED_ERROR, TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -39,223 +44,202 @@ def _get_other_fcv(current): return "8.0" if current != "8.0" else "8.2" -def test_setFeatureCompatibilityVersion_confirm_int_1_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=1 (int32) as true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": 1} - ) - assertSuccessPartial( - result, - {"ok": 1.0}, +# Property [Truthy Coercion]: confirm field accepts truthy numeric values. +CONFIRM_TRUTHY_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "int_1", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept confirm=1 (int) as true", - ) - _set_fcv(collection, current) - - -def test_setFeatureCompatibilityVersion_confirm_int_0_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=0 (int32) as false.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": 0} - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should treat confirm=0 as false", - ) - - -def test_setFeatureCompatibilityVersion_confirm_double_1_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=1.0 (double) as true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": 1.0} - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + ), + CommandTestCase( + "double_1", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept confirm=1.0 (double) as true", - ) - _set_fcv(collection, current) - - -def test_setFeatureCompatibilityVersion_confirm_double_0_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=0.0 (double) as false.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": 0.0} - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should treat confirm=0.0 as false", - ) - - -def test_setFeatureCompatibilityVersion_confirm_long_1_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=Int64(1) as true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(1)} - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + ), + CommandTestCase( + "long_1", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Int64(1), + }, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept confirm=Int64(1) as true", - ) - _set_fcv(collection, current) - - -def test_setFeatureCompatibilityVersion_confirm_long_0_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=Int64(0) as false.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": Int64(0)} - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should treat confirm=Int64(0) as false", - ) - - -def test_setFeatureCompatibilityVersion_confirm_decimal_1_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=Decimal128('1') as true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("1")}, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + ), + CommandTestCase( + "decimal_1", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Decimal128("1"), + }, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept confirm=Decimal128('1') as true", - ) - _set_fcv(collection, current) + ), + CommandTestCase( + "nan", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("nan"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=NaN as true", + ), + CommandTestCase( + "infinity", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("inf"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", + ), +] -def test_setFeatureCompatibilityVersion_confirm_decimal_0_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=Decimal128('0') as false.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": Decimal128("0")}, - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, +# Property [Falsy Coercion]: confirm field treats falsy values as false, +# requiring confirm to be truthy. +CONFIRM_FALSY_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "int_0", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 0}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=0 as false", + ), + CommandTestCase( + "double_0", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 0.0}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=0.0 as false", + ), + CommandTestCase( + "long_0", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Int64(0), + }, + error_code=FCV_CONFIRM_REQUIRED_ERROR, + msg="setFeatureCompatibilityVersion should treat confirm=Int64(0) as false", + ), + CommandTestCase( + "decimal_0", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Decimal128("0"), + }, + error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=Decimal128('0') as false", - ) - - -def test_setFeatureCompatibilityVersion_confirm_null_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=null as not-true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": None} - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, + ), + CommandTestCase( + "null", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": None}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=null as not-true", - ) - - -def test_setFeatureCompatibilityVersion_confirm_negative_zero_coercion(collection): - """Test setFeatureCompatibilityVersion treats confirm=-0.0 as false.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": -0.0} - ) - assertFailureCode( - result, - FCV_CONFIRM_REQUIRED_ERROR, + ), + CommandTestCase( + "negative_zero", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": -0.0}, + error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=-0.0 as false", - ) - - -def test_setFeatureCompatibilityVersion_confirm_nan_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=NaN as true.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": float("nan")}, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=NaN as true", - ) - _set_fcv(collection, current) - - -def test_setFeatureCompatibilityVersion_confirm_infinity_coercion(collection): - """Test setFeatureCompatibilityVersion accepts confirm=Infinity as true.""" + ), +] + + +# Property [Type Rejected]: confirm field rejects non-numeric, non-bool types. +CONFIRM_TYPE_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "string", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": "true", + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject confirm as string type", + ), + CommandTestCase( + "object", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": {"a": 1}, + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject confirm as object type", + ), + CommandTestCase( + "array", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": [True], + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject confirm as array type", + ), +] + + +def _resolve_fcv_placeholders(command_dict, current_fcv, other_fcv): + """Replace FCV placeholders in a command dict.""" + resolved = {} + for k, v in command_dict.items(): + if v == "CURRENT_FCV": + resolved[k] = current_fcv + elif v == "OTHER_FCV": + resolved[k] = other_fcv + else: + resolved[k] = v + return resolved + + +@pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUTHY_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collection, test): + """Test setFeatureCompatibilityVersion accepts truthy confirm values.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": float("inf")}, - ) - assertSuccessPartial( + other = _get_other_fcv(current) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) _set_fcv(collection, current) -def test_setFeatureCompatibilityVersion_confirm_string_coercion(collection): - """Test setFeatureCompatibilityVersion rejects confirm='true' (string).""" +@pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSY_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_falsy(database_client, collection, test): + """Test setFeatureCompatibilityVersion treats falsy confirm values as false.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": target, "confirm": "true"} - ) - assertFailureCode( + other = _get_other_fcv(current) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + result = execute_admin_command(collection, cmd) + assertResult( result, - TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject confirm as string type", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_confirm_object_coercion(collection): - """Test setFeatureCompatibilityVersion rejects confirm as object.""" +@pytest.mark.parametrize("test", pytest_params(CONFIRM_TYPE_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_type_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects non-numeric, non-bool confirm types.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": {"a": 1}}, - ) - assertFailureCode( + other = _get_other_fcv(current) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + result = execute_admin_command(collection, cmd) + assertResult( result, - TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject confirm as object type", - ) - - -def test_setFeatureCompatibilityVersion_confirm_array_coercion(collection): - """Test setFeatureCompatibilityVersion rejects confirm as array.""" - current = _get_fcv(collection) - target = _get_other_fcv(current) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": target, "confirm": [True]}, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject confirm as array type", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 23c236000..073985065 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -6,8 +6,13 @@ import pytest -from documentdb_tests.framework.assertions import assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult, assertSuccessPartial from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -37,92 +42,162 @@ def _get_other_fcv(current): return "8.0" if current != "8.0" else "8.2" -def test_setFeatureCompatibilityVersion_set_current_version_succeeds(collection): - """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" - current_fcv = _get_fcv(collection) - result = _set_fcv(collection, current_fcv) - assertSuccessPartial( - result, - {"ok": 1.0}, +# Property [Set Current]: setting the current version succeeds idempotently. +SET_CURRENT_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "set_current_version", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should succeed when setting the current version", - ) + ), + CommandTestCase( + "idempotent_same_value", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should be idempotent when re-setting the same value", + ), +] -def test_setFeatureCompatibilityVersion_idempotent_same_value(collection): - """Test setFeatureCompatibilityVersion is idempotent when re-setting the same value.""" - current_fcv = _get_fcv(collection) - _set_fcv(collection, current_fcv) - result = _set_fcv(collection, current_fcv) - assertSuccessPartial( - result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should be idempotent when re-setting the same value", - ) +# Property [GetParameter Readback]: getParameter reads back the current FCV. +GET_PARAMETER_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "getParameter_reads_back", + command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should persist and be readable via getParameter", + ), + CommandTestCase( + "fresh_deployment_default", + command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should have a readable default on a fresh deployment", + ), +] + + +# Property [Downgrade]: setFeatureCompatibilityVersion can downgrade with confirm:true. +DOWNGRADE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "downgrade_with_confirm", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when changing version with confirm", + ), +] + + +# Property [Upgrade]: setFeatureCompatibilityVersion can upgrade back. +UPGRADE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "upgrade_with_confirm", + command=lambda ctx: {"setFeatureCompatibilityVersion": "ORIGINAL_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when upgrading back", + ), +] + + +# Property [GetParameter Reflects Change]: getParameter reflects FCV after change. +GET_PARAMETER_AFTER_CHANGE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "getParameter_reflects_change", + command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should be reflected in getParameter after a change", + ), +] + +def _resolve_fcv_placeholders(command_dict, **replacements): + """Replace FCV placeholders in a command dict.""" + resolved = {} + for k, v in command_dict.items(): + if isinstance(v, str) and v in replacements: + resolved[k] = replacements[v] + else: + resolved[k] = v + return resolved -def test_setFeatureCompatibilityVersion_getParameter_reads_back_value(collection): - """Test getParameter reads back the most recently set FCV.""" + +@pytest.mark.parametrize("test", pytest_params(SET_CURRENT_TESTS)) +def test_setFeatureCompatibilityVersion_set_current(database_client, collection, test): + """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current_fcv = _get_fcv(collection) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), CURRENT_FCV=current_fcv) _set_fcv(collection, current_fcv) - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - assertSuccessPartial( + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should persist and be readable via getParameter", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_fresh_deployment_default_fcv(collection): - """Test a fresh deployment reports its expected default FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - assertSuccessPartial( - result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should have a readable default on a fresh deployment", - ) +@pytest.mark.parametrize("test", pytest_params(GET_PARAMETER_TESTS)) +def test_setFeatureCompatibilityVersion_getParameter(database_client, collection, test): + """Test getParameter reads back the current FCV.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + current_fcv = _get_fcv(collection) + _set_fcv(collection, current_fcv) + result = execute_admin_command(collection, test.build_command(ctx)) + assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg) -def test_setFeatureCompatibilityVersion_downgrade_with_confirm(collection): +@pytest.mark.parametrize("test", pytest_params(DOWNGRADE_TESTS)) +def test_setFeatureCompatibilityVersion_downgrade(database_client, collection, test): """Test setFeatureCompatibilityVersion can downgrade with confirm:true.""" - original_fcv = _get_fcv(collection) - other_fcv = _get_other_fcv(original_fcv) - result = _set_fcv(collection, other_fcv) - assertSuccessPartial( + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + original = _get_fcv(collection) + other = _get_other_fcv(original) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when changing version with confirm", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) - _set_fcv(collection, original_fcv) + _set_fcv(collection, original) -def test_setFeatureCompatibilityVersion_upgrade_with_confirm(collection): +@pytest.mark.parametrize("test", pytest_params(UPGRADE_TESTS)) +def test_setFeatureCompatibilityVersion_upgrade(database_client, collection, test): """Test setFeatureCompatibilityVersion can upgrade back to the original version.""" - original_fcv = _get_fcv(collection) - other_fcv = _get_other_fcv(original_fcv) - _set_fcv(collection, other_fcv) - result = _set_fcv(collection, original_fcv) - assertSuccessPartial( + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + original = _get_fcv(collection) + other = _get_other_fcv(original) + _set_fcv(collection, other) + cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when upgrading back", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_getParameter_reflects_change(collection): +@pytest.mark.parametrize("test", pytest_params(GET_PARAMETER_AFTER_CHANGE_TESTS)) +def test_setFeatureCompatibilityVersion_getParameter_reflects_change( + database_client, collection, test +): """Test getParameter reflects the FCV after a change.""" - original_fcv = _get_fcv(collection) - other_fcv = _get_other_fcv(original_fcv) - _set_fcv(collection, other_fcv) - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - assertSuccessPartial( - result, - {"ok": 1.0, "featureCompatibilityVersion": {"version": other_fcv}}, - msg="setFeatureCompatibilityVersion should be reflected in getParameter after a change", - ) - _set_fcv(collection, original_fcv) + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + original = _get_fcv(collection) + other = _get_other_fcv(original) + _set_fcv(collection, other) + result = execute_admin_command(collection, test.build_command(ctx)) + expected = {"ok": 1.0, "featureCompatibilityVersion": {"version": other}} + assertSuccessPartial(result, expected, msg=test.msg) + _set_fcv(collection, original) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 1559a86b1..38d210f35 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -6,7 +6,11 @@ import pytest -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import ( FCV_INVALID_VERSION_ERROR, ILLEGAL_OPERATION_ERROR, @@ -14,6 +18,7 @@ UNRECOGNIZED_COMMAND_FIELD_ERROR, ) from documentdb_tests.framework.executor import execute_admin_command, execute_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -31,88 +36,155 @@ def _get_fcv(collection): return str(fcv_data) -def test_setFeatureCompatibilityVersion_on_admin_db_accepted(collection): - """Test setFeatureCompatibilityVersion succeeds on the admin database.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} - ) - assertSuccessPartial( - result, - {"ok": 1.0}, +# Property [Admin DB Accepted]: setFeatureCompatibilityVersion succeeds on the admin database. +ADMIN_DB_ACCEPTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "admin_db_accepted", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should succeed on the admin database", - ) + ), +] -def test_setFeatureCompatibilityVersion_on_user_db_fails(collection): - """Test setFeatureCompatibilityVersion fails on a user database.""" - current_fcv = _get_fcv(collection) - result = execute_command( - collection, {"setFeatureCompatibilityVersion": current_fcv, "confirm": True} - ) - assertFailureCode( - result, - UNAUTHORIZED_ERROR, +# Property [User DB Rejected]: setFeatureCompatibilityVersion fails on a user database. +USER_DB_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "user_db_rejected", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + error_code=UNAUTHORIZED_ERROR, msg="setFeatureCompatibilityVersion should reject execution on a user database", - ) + ), +] -def test_setFeatureCompatibilityVersion_unrecognized_field_rejected(collection): - """Test setFeatureCompatibilityVersion rejects an unrecognized top-level field.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, +# Property [Unrecognized Fields]: setFeatureCompatibilityVersion rejects unrecognized fields. +UNRECOGNIZED_FIELD_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "unrecognized_field", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "unknownField": 1, }, - ) - assertFailureCode( - result, - UNRECOGNIZED_COMMAND_FIELD_ERROR, + error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, msg="setFeatureCompatibilityVersion should reject unrecognized fields", - ) + ), + CommandTestCase( + "misspelled_confirm", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confrim": True, + }, + error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="setFeatureCompatibilityVersion should reject misspelled 'confrim' as unknown field", + ), +] -def test_setFeatureCompatibilityVersion_misspelled_confirm_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a misspelled confirm field.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, - "confrim": True, +# Property [setParameter Rejected]: FCV cannot be set through setParameter. +SET_PARAMETER_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "via_setParameter", + command=lambda ctx: {"setParameter": 1, "featureCompatibilityVersion": "8.0"}, + error_code=ILLEGAL_OPERATION_ERROR, + msg="setFeatureCompatibilityVersion should not be settable via setParameter", + ), +] + + +# Property [Error Contains Code]: error response contains a numeric code. +ERROR_CODE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "invalid_version_error_code", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "invalid_version", + "confirm": True, }, + error_code=FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should return a numeric error code for invalid version", + ), +] + + +def _resolve_fcv(command_dict, current_fcv): + """Replace the CURRENT_FCV placeholder in a command dict.""" + return {k: current_fcv if v == "CURRENT_FCV" else v for k, v in command_dict.items()} + + +@pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) +def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): + """Test setFeatureCompatibilityVersion succeeds on the admin database.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + +@pytest.mark.parametrize("test", pytest_params(USER_DB_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_user_db_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion fails on a user database.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) - assertFailureCode( + + +@pytest.mark.parametrize("test", pytest_params(UNRECOGNIZED_FIELD_TESTS)) +def test_setFeatureCompatibilityVersion_unrecognized_field(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects unrecognized fields.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_admin_command(collection, cmd) + assertResult( result, - UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="setFeatureCompatibilityVersion should reject misspelled 'confrim' as unknown field", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_via_setParameter_rejected(collection): +@pytest.mark.parametrize("test", pytest_params(SET_PARAMETER_TESTS)) +def test_setFeatureCompatibilityVersion_set_parameter_rejected(database_client, collection, test): """Test setFeatureCompatibilityVersion cannot be set through setParameter.""" - result = execute_admin_command( - collection, - {"setParameter": 1, "featureCompatibilityVersion": "8.0"}, - ) - assertFailureCode( + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + result = execute_admin_command(collection, test.build_command(ctx)) + assertResult( result, - ILLEGAL_OPERATION_ERROR, - msg="setFeatureCompatibilityVersion should not be settable via setParameter", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_error_contains_code(collection): +@pytest.mark.parametrize("test", pytest_params(ERROR_CODE_TESTS)) +def test_setFeatureCompatibilityVersion_error_code(database_client, collection, test): """Test setFeatureCompatibilityVersion error response contains a numeric code.""" - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": "invalid_version", "confirm": True}, - ) - assertFailureCode( + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + result = execute_admin_command(collection, test.build_command(ctx)) + assertResult( result, - FCV_INVALID_VERSION_ERROR, - msg="setFeatureCompatibilityVersion should return a numeric error code for invalid version", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py index 5656556dc..2b42dc43c 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py @@ -6,7 +6,11 @@ import pytest -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.bson_type_validator import ( BsonType, BsonTypeTestCase, @@ -14,6 +18,7 @@ ) from documentdb_tests.framework.error_codes import MISSING_FIELD_ERROR, TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -55,35 +60,63 @@ def test_setFeatureCompatibilityVersion_version_type_rejected( collection, {"setFeatureCompatibilityVersion": sample_value, "confirm": True}, ) - assertFailureCode( + assertResult( result, - spec.expected_code(bson_type), + error_code=spec.expected_code(bson_type), msg=f"setFeatureCompatibilityVersion should reject {bson_type.value} for version", + raw_res=True, ) -def test_setFeatureCompatibilityVersion_version_string_accepted(collection): +# Property [String Accepted]: setFeatureCompatibilityVersion accepts string type. +VERSION_STRING_ACCEPTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "version_string_accepted", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept string for version", + ), +] + +# Property [Null Rejected]: setFeatureCompatibilityVersion rejects null for version. +VERSION_NULL_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "version_null_rejected", + command=lambda ctx: {"setFeatureCompatibilityVersion": None, "confirm": True}, + error_code=MISSING_FIELD_ERROR, + msg="setFeatureCompatibilityVersion should reject null for version", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(VERSION_STRING_ACCEPTED_TESTS)) +def test_setFeatureCompatibilityVersion_version_string_accepted(database_client, collection, test): """Test setFeatureCompatibilityVersion accepts string type for version.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, - ) - assertSuccessPartial( + cmd = test.build_command(ctx) + cmd = {k: current_fcv if v == "CURRENT_FCV" else v for k, v in cmd.items()} + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept string for version", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_version_null_rejected(collection): +@pytest.mark.parametrize("test", pytest_params(VERSION_NULL_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_version_null_rejected(database_client, collection, test): """Test setFeatureCompatibilityVersion rejects null for version.""" - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": None, "confirm": True}, - ) - assertFailureCode( + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + result = execute_admin_command(collection, test.build_command(ctx)) + assertResult( result, - MISSING_FIELD_ERROR, - msg="setFeatureCompatibilityVersion should reject null for version", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py index 116d84f28..1a6fe6c89 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py @@ -6,9 +6,14 @@ import pytest -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import FCV_INVALID_VERSION_ERROR from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -26,161 +31,130 @@ def _get_fcv(collection): return str(fcv_data) -def test_setFeatureCompatibilityVersion_value_below_floor_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a version below the supported floor.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "3.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, +# Property [Invalid Version Rejected]: setFeatureCompatibilityVersion rejects +# unsupported, malformed, and edge-case version strings. +VERSION_VALUE_REJECTION_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "below_floor", + command=lambda ctx: {"setFeatureCompatibilityVersion": "3.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject version below supported floor", - ) - - -def test_setFeatureCompatibilityVersion_value_above_max_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a version above the supported max.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "99.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "above_max", + command=lambda ctx: {"setFeatureCompatibilityVersion": "99.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject version above supported max", - ) - - -def test_setFeatureCompatibilityVersion_major_only_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a major-only version string.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "8", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "major_only", + command=lambda ctx: {"setFeatureCompatibilityVersion": "8", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject major-only version string", - ) - - -def test_setFeatureCompatibilityVersion_full_semver_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a full semver string.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "8.0.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "full_semver", + command=lambda ctx: {"setFeatureCompatibilityVersion": "8.0.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject full semver version string", - ) - - -def test_setFeatureCompatibilityVersion_leading_whitespace_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a version with leading whitespace.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": " 7.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "leading_whitespace", + command=lambda ctx: {"setFeatureCompatibilityVersion": " 7.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject version with leading whitespace", - ) - - -def test_setFeatureCompatibilityVersion_trailing_whitespace_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a version with trailing whitespace.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "7.0 ", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "trailing_whitespace", + command=lambda ctx: {"setFeatureCompatibilityVersion": "7.0 ", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject version with trailing whitespace", - ) - - -def test_setFeatureCompatibilityVersion_empty_string_rejected(collection): - """Test setFeatureCompatibilityVersion rejects an empty string.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "empty_string", + command=lambda ctx: {"setFeatureCompatibilityVersion": "", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject empty string version", - ) - - -def test_setFeatureCompatibilityVersion_zero_version_rejected(collection): - """Test setFeatureCompatibilityVersion rejects '0.0' as unsupported.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "0.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "zero_version", + command=lambda ctx: {"setFeatureCompatibilityVersion": "0.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject '0.0' as unsupported", - ) - - -def test_setFeatureCompatibilityVersion_future_version_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a future unsupported version.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "10.0", "confirm": True} - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "future_version", + command=lambda ctx: {"setFeatureCompatibilityVersion": "10.0", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject future unsupported version", - ) - - -def test_setFeatureCompatibilityVersion_non_ascii_rejected(collection): - """Test setFeatureCompatibilityVersion rejects non-ASCII digit characters.""" - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": "\uff18.\uff10", "confirm": True}, - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, + ), + CommandTestCase( + "non_ascii", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "\uff18.\uff10", + "confirm": True, + }, + error_code=FCV_INVALID_VERSION_ERROR, msg="setFeatureCompatibilityVersion should reject non-ASCII version string", - ) + ), + CommandTestCase( + "very_long_string", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "8" * 10_000, + "confirm": True, + }, + error_code=FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject a very long version string", + ), + CommandTestCase( + "intermediate_value", + command=lambda ctx: {"setFeatureCompatibilityVersion": "7.5", "confirm": True}, + error_code=FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion should reject intermediate version value", + ), +] -def test_setFeatureCompatibilityVersion_very_long_string_rejected(collection): - """Test setFeatureCompatibilityVersion rejects a very long string.""" - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": "8" * 10_000, "confirm": True}, - ) - assertFailureCode( - result, - FCV_INVALID_VERSION_ERROR, - msg="setFeatureCompatibilityVersion should reject a very long version string", - ) +# Property [Current Version Accepted]: setFeatureCompatibilityVersion accepts +# the current binary version. +CURRENT_VERSION_ACCEPTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "current_version", + command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept the current binary version", + ), +] -def test_setFeatureCompatibilityVersion_intermediate_value_rejected(collection): - """Test setFeatureCompatibilityVersion rejects an intermediate version value.""" - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": "7.5", "confirm": True} - ) - assertFailureCode( +@pytest.mark.parametrize("test", pytest_params(VERSION_VALUE_REJECTION_TESTS)) +def test_setFeatureCompatibilityVersion_version_value_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects invalid version values.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + result = execute_admin_command(collection, test.build_command(ctx)) + assertResult( result, - FCV_INVALID_VERSION_ERROR, - msg="setFeatureCompatibilityVersion should reject intermediate version value", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) -def test_setFeatureCompatibilityVersion_current_version_accepted(collection): +@pytest.mark.parametrize("test", pytest_params(CURRENT_VERSION_ACCEPTED_TESTS)) +def test_setFeatureCompatibilityVersion_current_version_accepted(database_client, collection, test): """Test setFeatureCompatibilityVersion accepts the current binary version.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, - ) - assertSuccessPartial( + cmd = test.build_command(ctx) + cmd = {k: current_fcv if v == "CURRENT_FCV" else v for k, v in cmd.items()} + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept the current binary version", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py index 0cb2d1101..4828b9247 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py @@ -7,9 +7,14 @@ import pytest from bson import Decimal128, Int64 -from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -27,285 +32,231 @@ def _get_fcv(collection): return str(fcv_data) -def test_setFeatureCompatibilityVersion_writeConcern_object_accepted(collection): - """Test setFeatureCompatibilityVersion accepts writeConcern as object.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, +# Property [writeConcern Accepted]: setFeatureCompatibilityVersion accepts +# valid writeConcern values. +WRITE_CONCERN_ACCEPTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "object", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": 5000}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept writeConcern as object", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_empty_object_accepted(collection): - """Test setFeatureCompatibilityVersion accepts writeConcern as empty object.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "empty_object", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept writeConcern as empty object", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_null_as_omitted(collection): - """Test setFeatureCompatibilityVersion treats writeConcern=null as omitted.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "null_as_omitted", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": None, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should treat writeConcern=null as omitted", - ) + ), + CommandTestCase( + "omitted", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed when writeConcern is omitted", + ), +] -def test_setFeatureCompatibilityVersion_writeConcern_string_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as string.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, +# Property [writeConcern Rejected]: setFeatureCompatibilityVersion rejects +# non-object writeConcern types. +WRITE_CONCERN_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "string", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": "majority", }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as string", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_int_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as int.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "int", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": 1, }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as int", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_bool_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as bool.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "bool", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": True, }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as bool", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_array_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as array.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "array", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": [{"w": 1}], }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as array", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_long_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as long.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "long", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": Int64(1), }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as long", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_double_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as double.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "double", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": 1.0, }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as double", - ) - - -def test_setFeatureCompatibilityVersion_writeConcern_decimal_rejected(collection): - """Test setFeatureCompatibilityVersion rejects writeConcern as Decimal128.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "decimal128", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": Decimal128("1"), }, - ) - assertFailureCode( - result, - TYPE_MISMATCH_ERROR, + error_code=TYPE_MISMATCH_ERROR, msg="setFeatureCompatibilityVersion should reject writeConcern as Decimal128", - ) - - -def test_setFeatureCompatibilityVersion_omitting_writeConcern_succeeds(collection): - """Test setFeatureCompatibilityVersion succeeds when writeConcern is omitted.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - {"setFeatureCompatibilityVersion": current_fcv, "confirm": True}, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when writeConcern is omitted", - ) + ), +] -def test_setFeatureCompatibilityVersion_wtimeout_double_coercion(collection): - """Test setFeatureCompatibilityVersion accepts wtimeout as whole-number double.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, +# Property [wtimeout Coercion]: setFeatureCompatibilityVersion accepts +# various numeric types for wtimeout. +WTIMEOUT_COERCION_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "wtimeout_double", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": 5000.0}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number double", - ) - - -def test_setFeatureCompatibilityVersion_wtimeout_long_coercion(collection): - """Test setFeatureCompatibilityVersion accepts wtimeout as Int64.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "wtimeout_long", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": Int64(5000)}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept wtimeout as Int64", - ) - - -def test_setFeatureCompatibilityVersion_wtimeout_decimal_whole_coercion(collection): - """Test setFeatureCompatibilityVersion accepts wtimeout as whole-number Decimal128.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "wtimeout_decimal_whole", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": Decimal128("5000")}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number Decimal128", - ) - - -def test_setFeatureCompatibilityVersion_wtimeout_fractional_double_accepted(collection): - """Test setFeatureCompatibilityVersion accepts wtimeout as fractional double.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "wtimeout_fractional_double", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": 5000.5}, }, - ) - assertSuccessPartial( - result, - {"ok": 1.0}, + expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept wtimeout as fractional double", - ) - - -def test_setFeatureCompatibilityVersion_wtimeout_negative_value_accepted(collection): - """Test setFeatureCompatibilityVersion accepts wtimeout as negative value.""" - current_fcv = _get_fcv(collection) - result = execute_admin_command( - collection, - { - "setFeatureCompatibilityVersion": current_fcv, + ), + CommandTestCase( + "wtimeout_negative", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True, "writeConcern": {"wtimeout": -1}, }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept wtimeout as negative value", + ), +] + + +def _resolve_fcv(command_dict, current_fcv): + """Replace the CURRENT_FCV placeholder in a command dict.""" + return {k: current_fcv if v == "CURRENT_FCV" else v for k, v in command_dict.items()} + + +@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_ACCEPTED_TESTS)) +def test_setFeatureCompatibilityVersion_writeConcern_accepted(database_client, collection, test): + """Test setFeatureCompatibilityVersion accepts valid writeConcern values.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) - assertSuccessPartial( + + +@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_writeConcern_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects non-object writeConcern types.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_admin_command(collection, cmd) + assertResult( result, - {"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept wtimeout as negative value", + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + +@pytest.mark.parametrize("test", pytest_params(WTIMEOUT_COERCION_TESTS)) +def test_setFeatureCompatibilityVersion_wtimeout_coercion(database_client, collection, test): + """Test setFeatureCompatibilityVersion accepts various numeric types for wtimeout.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, ) From a36956439cf6c113406737ce6f76fc6d0d9d2a89 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 15:48:03 -0700 Subject: [PATCH 06/12] inline helpers Signed-off-by: Alina (Xi) Li --- ...eCompatibilityVersion_confirm_semantics.py | 56 +++++++------------ ...patibilityVersion_confirm_type_coercion.py | 42 ++++---------- ...atureCompatibilityVersion_core_behavior.py | 56 ++++++------------- ...t_setFeatureCompatibilityVersion_errors.py | 20 +++---- ...tibilityVersion_version_type_validation.py | 9 ++- ...ibilityVersion_version_value_validation.py | 9 ++- ...tibilityVersion_writeConcern_validation.py | 14 ++--- ...st_smoke_setFeatureCompatibilityVersion.py | 15 ++--- 8 files changed, 75 insertions(+), 146 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py index c9d8fc87c..45c355a1f 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py @@ -31,18 +31,6 @@ def _get_fcv(collection): return str(fcv_data) -def _set_fcv(collection, version): - """Set FCV with confirm:true.""" - return execute_admin_command( - collection, {"setFeatureCompatibilityVersion": version, "confirm": True} - ) - - -def _get_other_fcv(current): - """Get a different supported FCV than the current one.""" - return "8.0" if current != "8.0" else "8.2" - - # Property [Confirm Required]: confirm:true is required for version changes. CONFIRM_TRUE_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -94,17 +82,6 @@ def _get_other_fcv(current): ] -def _resolve_fcv_placeholders(command_dict, **replacements): - """Replace FCV placeholders in a command dict.""" - resolved = {} - for k, v in command_dict.items(): - if isinstance(v, str) and v in replacements: - resolved[k] = replacements[v] - else: - resolved[k] = v - return resolved - - @pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUE_TESTS)) def test_setFeatureCompatibilityVersion_confirm_true_allows_change( database_client, collection, test @@ -113,8 +90,9 @@ def test_setFeatureCompatibilityVersion_confirm_true_allows_change( collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + other = "8.0" if original != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -123,7 +101,7 @@ def test_setFeatureCompatibilityVersion_confirm_true_allows_change( msg=test.msg, raw_res=True, ) - _set_fcv(collection, original) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) @pytest.mark.parametrize("test", pytest_params(CONFIRM_OMITTED_TESTS)) @@ -132,8 +110,9 @@ def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, c collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + other = "8.0" if original != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -150,8 +129,9 @@ def test_setFeatureCompatibilityVersion_confirm_false_fails(database_client, col collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + other = "8.0" if original != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -170,9 +150,10 @@ def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - _set_fcv(collection, other) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + other = "8.0" if original != "8.0" else "8.2" + execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = original result = execute_admin_command(collection, cmd) assertResult( result, @@ -181,7 +162,7 @@ def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( msg=test.msg, raw_res=True, ) - _set_fcv(collection, original) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) @pytest.mark.parametrize("test", pytest_params(UPGRADE_WITH_CONFIRM_TESTS)) @@ -192,9 +173,10 @@ def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds( collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - _set_fcv(collection, other) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + other = "8.0" if original != "8.0" else "8.2" + execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = original result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py index aba759d08..cae100cfa 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -32,18 +32,6 @@ def _get_fcv(collection): return str(fcv_data) -def _set_fcv(collection, version): - """Set FCV with confirm:true.""" - return execute_admin_command( - collection, {"setFeatureCompatibilityVersion": version, "confirm": True} - ) - - -def _get_other_fcv(current): - """Get a different supported FCV than the current one.""" - return "8.0" if current != "8.0" else "8.2" - - # Property [Truthy Coercion]: confirm field accepts truthy numeric values. CONFIRM_TRUTHY_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -177,27 +165,15 @@ def _get_other_fcv(current): ] -def _resolve_fcv_placeholders(command_dict, current_fcv, other_fcv): - """Replace FCV placeholders in a command dict.""" - resolved = {} - for k, v in command_dict.items(): - if v == "CURRENT_FCV": - resolved[k] = current_fcv - elif v == "OTHER_FCV": - resolved[k] = other_fcv - else: - resolved[k] = v - return resolved - - @pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUTHY_TESTS)) def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collection, test): """Test setFeatureCompatibilityVersion accepts truthy confirm values.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - other = _get_other_fcv(current) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + other = "8.0" if current != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -206,7 +182,7 @@ def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collecti msg=test.msg, raw_res=True, ) - _set_fcv(collection, current) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": current, "confirm": True}) @pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSY_TESTS)) @@ -215,8 +191,9 @@ def test_setFeatureCompatibilityVersion_confirm_falsy(database_client, collectio collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - other = _get_other_fcv(current) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + other = "8.0" if current != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -233,8 +210,9 @@ def test_setFeatureCompatibilityVersion_confirm_type_rejected(database_client, c collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) current = _get_fcv(collection) - other = _get_other_fcv(current) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), current, other) + other = "8.0" if current != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 073985065..758b0a726 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -30,18 +30,6 @@ def _get_fcv(collection): return str(fcv_data) -def _set_fcv(collection, version): - """Set FCV to the given version with confirm:true.""" - return execute_admin_command( - collection, {"setFeatureCompatibilityVersion": version, "confirm": True} - ) - - -def _get_other_fcv(current): - """Get a different supported FCV than the current one.""" - return "8.0" if current != "8.0" else "8.2" - - # Property [Set Current]: setting the current version succeeds idempotently. SET_CURRENT_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -109,26 +97,16 @@ def _get_other_fcv(current): ] -def _resolve_fcv_placeholders(command_dict, **replacements): - """Replace FCV placeholders in a command dict.""" - resolved = {} - for k, v in command_dict.items(): - if isinstance(v, str) and v in replacements: - resolved[k] = replacements[v] - else: - resolved[k] = v - return resolved - - @pytest.mark.parametrize("test", pytest_params(SET_CURRENT_TESTS)) def test_setFeatureCompatibilityVersion_set_current(database_client, collection, test): """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current_fcv = _get_fcv(collection) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), CURRENT_FCV=current_fcv) - _set_fcv(collection, current_fcv) - result = execute_admin_command(collection, cmd) + fcv = _get_fcv(collection) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) assertResult( result, expected=test.build_expected(ctx), @@ -143,8 +121,8 @@ def test_setFeatureCompatibilityVersion_getParameter(database_client, collection """Test getParameter reads back the current FCV.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current_fcv = _get_fcv(collection) - _set_fcv(collection, current_fcv) + fcv = _get_fcv(collection) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) result = execute_admin_command(collection, test.build_command(ctx)) assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg) @@ -155,8 +133,9 @@ def test_setFeatureCompatibilityVersion_downgrade(database_client, collection, t collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), OTHER_FCV=other) + other = "8.0" if original != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other result = execute_admin_command(collection, cmd) assertResult( result, @@ -165,7 +144,7 @@ def test_setFeatureCompatibilityVersion_downgrade(database_client, collection, t msg=test.msg, raw_res=True, ) - _set_fcv(collection, original) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) @pytest.mark.parametrize("test", pytest_params(UPGRADE_TESTS)) @@ -174,9 +153,10 @@ def test_setFeatureCompatibilityVersion_upgrade(database_client, collection, tes collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - _set_fcv(collection, other) - cmd = _resolve_fcv_placeholders(test.build_command(ctx), ORIGINAL_FCV=original) + other = "8.0" if original != "8.0" else "8.2" + execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = original result = execute_admin_command(collection, cmd) assertResult( result, @@ -195,9 +175,9 @@ def test_setFeatureCompatibilityVersion_getParameter_reflects_change( collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = _get_fcv(collection) - other = _get_other_fcv(original) - _set_fcv(collection, other) + other = "8.0" if original != "8.0" else "8.2" + execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) result = execute_admin_command(collection, test.build_command(ctx)) expected = {"ok": 1.0, "featureCompatibilityVersion": {"version": other}} assertSuccessPartial(result, expected, msg=test.msg) - _set_fcv(collection, original) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 38d210f35..f3d048a78 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -40,7 +40,6 @@ def _get_fcv(collection): ADMIN_DB_ACCEPTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "admin_db_accepted", - command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should succeed on the admin database", ), @@ -51,7 +50,6 @@ def _get_fcv(collection): USER_DB_REJECTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "user_db_rejected", - command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, error_code=UNAUTHORIZED_ERROR, msg="setFeatureCompatibilityVersion should reject execution on a user database", ), @@ -107,18 +105,15 @@ def _get_fcv(collection): ] -def _resolve_fcv(command_dict, current_fcv): - """Replace the CURRENT_FCV placeholder in a command dict.""" - return {k: current_fcv if v == "CURRENT_FCV" else v for k, v in command_dict.items()} - - @pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): """Test setFeatureCompatibilityVersion succeeds on the admin database.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) - result = execute_admin_command(collection, cmd) + fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) assertResult( result, expected=test.build_expected(ctx), @@ -133,8 +128,8 @@ def test_setFeatureCompatibilityVersion_user_db_rejected(database_client, collec """Test setFeatureCompatibilityVersion fails on a user database.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) - result = execute_command(collection, cmd) + fcv = _get_fcv(collection) + result = execute_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) assertResult( result, expected=test.build_expected(ctx), @@ -149,7 +144,8 @@ def test_setFeatureCompatibilityVersion_unrecognized_field(database_client, coll """Test setFeatureCompatibilityVersion rejects unrecognized fields.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py index 2b42dc43c..7f4a32224 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py @@ -72,7 +72,6 @@ def test_setFeatureCompatibilityVersion_version_type_rejected( VERSION_STRING_ACCEPTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "version_string_accepted", - command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept string for version", ), @@ -94,10 +93,10 @@ def test_setFeatureCompatibilityVersion_version_string_accepted(database_client, """Test setFeatureCompatibilityVersion accepts string type for version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current_fcv = _get_fcv(collection) - cmd = test.build_command(ctx) - cmd = {k: current_fcv if v == "CURRENT_FCV" else v for k, v in cmd.items()} - result = execute_admin_command(collection, cmd) + fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) assertResult( result, expected=test.build_expected(ctx), diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py index 1a6fe6c89..9095ffa8d 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py @@ -120,7 +120,6 @@ def _get_fcv(collection): CURRENT_VERSION_ACCEPTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "current_version", - command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept the current binary version", ), @@ -147,10 +146,10 @@ def test_setFeatureCompatibilityVersion_current_version_accepted(database_client """Test setFeatureCompatibilityVersion accepts the current binary version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current_fcv = _get_fcv(collection) - cmd = test.build_command(ctx) - cmd = {k: current_fcv if v == "CURRENT_FCV" else v for k, v in cmd.items()} - result = execute_admin_command(collection, cmd) + fcv = _get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) assertResult( result, expected=test.build_expected(ctx), diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py index 4828b9247..b47d24025 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py @@ -209,17 +209,13 @@ def _get_fcv(collection): ] -def _resolve_fcv(command_dict, current_fcv): - """Replace the CURRENT_FCV placeholder in a command dict.""" - return {k: current_fcv if v == "CURRENT_FCV" else v for k, v in command_dict.items()} - - @pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_ACCEPTED_TESTS)) def test_setFeatureCompatibilityVersion_writeConcern_accepted(database_client, collection, test): """Test setFeatureCompatibilityVersion accepts valid writeConcern values.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, @@ -235,7 +231,8 @@ def test_setFeatureCompatibilityVersion_writeConcern_rejected(database_client, c """Test setFeatureCompatibilityVersion rejects non-object writeConcern types.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, @@ -251,7 +248,8 @@ def test_setFeatureCompatibilityVersion_wtimeout_coercion(database_client, colle """Test setFeatureCompatibilityVersion accepts various numeric types for wtimeout.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - cmd = _resolve_fcv(test.build_command(ctx), _get_fcv(collection)) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py index 5c900a241..aeadcd20d 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py @@ -25,21 +25,18 @@ def _get_fcv(collection): return str(fcv_data) -def _set_fcv(collection, version): - """Set FCV with confirm:true.""" - return execute_admin_command( - collection, {"setFeatureCompatibilityVersion": version, "confirm": True} - ) - - def test_smoke_setFeatureCompatibilityVersion(collection): """Test basic setFeatureCompatibilityVersion behavior.""" original_fcv = _get_fcv(collection) new_fcv = "8.0" if original_fcv != "8.0" else "8.2" - result = _set_fcv(collection, new_fcv) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": new_fcv, "confirm": True} + ) assertSuccessPartial( result, {"ok": 1.0}, msg="setFeatureCompatibilityVersion should succeed with a valid version change", ) - _set_fcv(collection, original_fcv) + execute_admin_command( + collection, {"setFeatureCompatibilityVersion": original_fcv, "confirm": True} + ) From cc4214bfa0ccb76d6e361a0cd223e068f93bd666 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 16:23:27 -0700 Subject: [PATCH 07/12] move get_fcv to utils Signed-off-by: Alina (Xi) Li --- ...eCompatibilityVersion_confirm_semantics.py | 25 ++++++------------- ...patibilityVersion_confirm_type_coercion.py | 21 ++++------------ ...atureCompatibilityVersion_core_behavior.py | 25 ++++++------------- ...t_setFeatureCompatibilityVersion_errors.py | 21 ++++------------ ...tibilityVersion_version_type_validation.py | 17 +++---------- ...ibilityVersion_version_value_validation.py | 17 +++---------- ...tibilityVersion_writeConcern_validation.py | 21 ++++------------ ...st_smoke_setFeatureCompatibilityVersion.py | 17 +++---------- .../utils/__init__.py | 0 .../setFeatureCompatibilityVersion_common.py | 16 ++++++++++++ 10 files changed, 54 insertions(+), 126 deletions(-) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/__init__.py create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/setFeatureCompatibilityVersion_common.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py index 45c355a1f..df23a25e8 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py @@ -15,20 +15,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [Confirm Required]: confirm:true is required for version changes. @@ -89,7 +78,7 @@ def test_setFeatureCompatibilityVersion_confirm_true_allows_change( """Test setFeatureCompatibilityVersion succeeds with confirm:true.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -109,7 +98,7 @@ def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, c """Test setFeatureCompatibilityVersion fails when confirm is omitted.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -128,7 +117,7 @@ def test_setFeatureCompatibilityVersion_confirm_false_fails(database_client, col """Test setFeatureCompatibilityVersion fails with confirm:false.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -149,7 +138,7 @@ def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( """Test setFeatureCompatibilityVersion rejects upgrade without confirm.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) cmd = test.build_command(ctx) @@ -172,7 +161,7 @@ def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds( """Test setFeatureCompatibilityVersion succeeds on upgrade with confirm:true.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) cmd = test.build_command(ctx) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py index cae100cfa..3ff1b081d 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -16,20 +16,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [Truthy Coercion]: confirm field accepts truthy numeric values. @@ -170,7 +159,7 @@ def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collecti """Test setFeatureCompatibilityVersion accepts truthy confirm values.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current = _get_fcv(collection) + current = get_fcv(collection) other = "8.0" if current != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -190,7 +179,7 @@ def test_setFeatureCompatibilityVersion_confirm_falsy(database_client, collectio """Test setFeatureCompatibilityVersion treats falsy confirm values as false.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current = _get_fcv(collection) + current = get_fcv(collection) other = "8.0" if current != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -209,7 +198,7 @@ def test_setFeatureCompatibilityVersion_confirm_type_rejected(database_client, c """Test setFeatureCompatibilityVersion rejects non-numeric, non-bool confirm types.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - current = _get_fcv(collection) + current = get_fcv(collection) other = "8.0" if current != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 758b0a726..25b519473 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -14,20 +14,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [Set Current]: setting the current version succeeds idempotently. @@ -102,7 +91,7 @@ def test_setFeatureCompatibilityVersion_set_current(database_client, collection, """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) execute_admin_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} @@ -121,7 +110,7 @@ def test_setFeatureCompatibilityVersion_getParameter(database_client, collection """Test getParameter reads back the current FCV.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) execute_admin_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) result = execute_admin_command(collection, test.build_command(ctx)) assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg) @@ -132,7 +121,7 @@ def test_setFeatureCompatibilityVersion_downgrade(database_client, collection, t """Test setFeatureCompatibilityVersion can downgrade with confirm:true.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" cmd = test.build_command(ctx) cmd["setFeatureCompatibilityVersion"] = other @@ -152,7 +141,7 @@ def test_setFeatureCompatibilityVersion_upgrade(database_client, collection, tes """Test setFeatureCompatibilityVersion can upgrade back to the original version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) cmd = test.build_command(ctx) @@ -174,7 +163,7 @@ def test_setFeatureCompatibilityVersion_getParameter_reflects_change( """Test getParameter reflects the FCV after a change.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - original = _get_fcv(collection) + original = get_fcv(collection) other = "8.0" if original != "8.0" else "8.2" execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) result = execute_admin_command(collection, test.build_command(ctx)) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index f3d048a78..6117254f3 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -20,20 +20,9 @@ from documentdb_tests.framework.executor import execute_admin_command, execute_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [Admin DB Accepted]: setFeatureCompatibilityVersion succeeds on the admin database. @@ -110,7 +99,7 @@ def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, colle """Test setFeatureCompatibilityVersion succeeds on the admin database.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} ) @@ -128,7 +117,7 @@ def test_setFeatureCompatibilityVersion_user_db_rejected(database_client, collec """Test setFeatureCompatibilityVersion fails on a user database.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) result = execute_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) assertResult( result, @@ -145,7 +134,7 @@ def test_setFeatureCompatibilityVersion_unrecognized_field(database_client, coll collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py index 7f4a32224..38658f2b4 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py @@ -20,20 +20,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] VERSION_TYPE_PARAM = [ @@ -93,7 +82,7 @@ def test_setFeatureCompatibilityVersion_version_string_accepted(database_client, """Test setFeatureCompatibilityVersion accepts string type for version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py index 9095ffa8d..505e11e4c 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py @@ -15,20 +15,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [Invalid Version Rejected]: setFeatureCompatibilityVersion rejects @@ -146,7 +135,7 @@ def test_setFeatureCompatibilityVersion_current_version_accepted(database_client """Test setFeatureCompatibilityVersion accepts the current binary version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) - fcv = _get_fcv(collection) + fcv = get_fcv(collection) result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py index b47d24025..d01e7c0e7 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py @@ -16,20 +16,9 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] # Property [writeConcern Accepted]: setFeatureCompatibilityVersion accepts @@ -215,7 +204,7 @@ def test_setFeatureCompatibilityVersion_writeConcern_accepted(database_client, c collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, @@ -232,7 +221,7 @@ def test_setFeatureCompatibilityVersion_writeConcern_rejected(database_client, c collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, @@ -249,7 +238,7 @@ def test_setFeatureCompatibilityVersion_wtimeout_coercion(database_client, colle collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = _get_fcv(collection) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) result = execute_admin_command(collection, cmd) assertResult( result, diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py index aeadcd20d..0c381df45 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_smoke_setFeatureCompatibilityVersion.py @@ -9,25 +9,14 @@ from documentdb_tests.framework.assertions import assertSuccessPartial from documentdb_tests.framework.executor import execute_admin_command -pytestmark = [pytest.mark.smoke, pytest.mark.no_parallel] - +from .utils.setFeatureCompatibilityVersion_common import get_fcv -def _get_fcv(collection): - """Read the current FCV via getParameter.""" - result = execute_admin_command( - collection, {"getParameter": 1, "featureCompatibilityVersion": 1} - ) - if isinstance(result, Exception): - return "8.2" - fcv_data = result.get("featureCompatibilityVersion", {}) - if isinstance(fcv_data, dict): - return fcv_data.get("version", "8.2") - return str(fcv_data) +pytestmark = [pytest.mark.smoke, pytest.mark.no_parallel] def test_smoke_setFeatureCompatibilityVersion(collection): """Test basic setFeatureCompatibilityVersion behavior.""" - original_fcv = _get_fcv(collection) + original_fcv = get_fcv(collection) new_fcv = "8.0" if original_fcv != "8.0" else "8.2" result = execute_admin_command( collection, {"setFeatureCompatibilityVersion": new_fcv, "confirm": True} diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/__init__.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/setFeatureCompatibilityVersion_common.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/setFeatureCompatibilityVersion_common.py new file mode 100644 index 000000000..efe74a378 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/utils/setFeatureCompatibilityVersion_common.py @@ -0,0 +1,16 @@ +"""Utilities for setFeatureCompatibilityVersion tests.""" + +from documentdb_tests.framework.executor import execute_admin_command + + +def get_fcv(collection): + """Read the current FCV via getParameter.""" + result = execute_admin_command( + collection, {"getParameter": 1, "featureCompatibilityVersion": 1} + ) + if isinstance(result, Exception): + return "8.2" + fcv_data = result.get("featureCompatibilityVersion", {}) + if isinstance(fcv_data, dict): + return fcv_data.get("version", "8.2") + return str(fcv_data) From b583573efbe2950fd35d23c66bf411ade317381a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 16:36:40 -0700 Subject: [PATCH 08/12] add test_setFeatureCompatibilityVersion_feature_not_supported.py Signed-off-by: Alina (Xi) Li --- ...patibilityVersion_feature_not_supported.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py new file mode 100644 index 000000000..48563c5be --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_feature_not_supported.py @@ -0,0 +1,34 @@ +"""Tests for setFeatureCompatibilityVersion feature-not-supported behavior. + +Validates that setFeatureCompatibilityVersion is classified as an admin-only +command and returns the appropriate error when the feature is not supported. +""" + +import pytest + +from documentdb_tests.framework.assertions import assertFailureCode +from documentdb_tests.framework.error_codes import COMMAND_NOT_SUPPORTED_ERROR +from documentdb_tests.framework.executor import execute_admin_command + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +def test_setFeatureCompatibilityVersion_unsupported_returns_303(collection): + """Test setFeatureCompatibilityVersion returns error code 303 when feature not supported.""" + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": "8.0", "confirm": True} + ) + # This test is only meaningful on engines that do not support FCV (e.g., DocumentDB). + # On engines that support FCV, this test is expected to pass/succeed instead. + if ( + isinstance(result, Exception) + and hasattr(result, "code") + and result.code == COMMAND_NOT_SUPPORTED_ERROR + ): + assertFailureCode( + result, + COMMAND_NOT_SUPPORTED_ERROR, + msg="setFeatureCompatibilityVersion should return 303 when not supported", + ) + else: + pytest.skip("Engine supports setFeatureCompatibilityVersion, skipping not-supported test") From a7711731c76cc646649e4798101a86488411c8ce Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 16:40:23 -0700 Subject: [PATCH 09/12] add missing tests Signed-off-by: Alina (Xi) Li --- ...patibilityVersion_confirm_type_coercion.py | 9 ++ ...t_setFeatureCompatibilityVersion_errors.py | 123 +++++++++++++++++- 2 files changed, 131 insertions(+), 1 deletion(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py index 3ff1b081d..4cb69593d 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py @@ -71,6 +71,15 @@ expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", ), + CommandTestCase( + "negative_infinity", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("-inf"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=-Infinity as true", + ), ] diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 6117254f3..300cd5555 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -10,7 +10,7 @@ CommandContext, CommandTestCase, ) -from documentdb_tests.framework.assertions import assertResult +from documentdb_tests.framework.assertions import assertFailureCode, assertResult from documentdb_tests.framework.error_codes import ( FCV_INVALID_VERSION_ERROR, ILLEGAL_OPERATION_ERROR, @@ -45,6 +45,21 @@ ] +# Property [System DB Rejected]: setFeatureCompatibilityVersion fails on local and config databases. +SYSTEM_DB_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "local_db_rejected", + error_code=UNAUTHORIZED_ERROR, + msg="setFeatureCompatibilityVersion should reject execution on the local database", + ), + CommandTestCase( + "config_db_rejected", + error_code=UNAUTHORIZED_ERROR, + msg="setFeatureCompatibilityVersion should reject execution on the config database", + ), +] + + # Property [Unrecognized Fields]: setFeatureCompatibilityVersion rejects unrecognized fields. UNRECOGNIZED_FIELD_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -80,6 +95,21 @@ ] +# Property [writeConcern Unknown Sub-field]: unknown fields inside writeConcern are rejected. +WRITE_CONCERN_UNKNOWN_SUBFIELD_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "writeConcern_unknown_subfield", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": {"unknownField": 1}, + }, + error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="setFeatureCompatibilityVersion should reject unknown sub-fields inside writeConcern", + ), +] + + # Property [Error Contains Code]: error response contains a numeric code. ERROR_CODE_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -94,6 +124,30 @@ ] +# Property [Success Response Structure]: success response contains ok:1. +SUCCESS_RESPONSE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "success_contains_ok", + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion success response should contain ok:1", + ), +] + + +# Property [Error Response Structure]: error response contains code and codeName. +ERROR_RESPONSE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "error_contains_code_and_codeName", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "invalid_version", + "confirm": True, + }, + error_code=FCV_INVALID_VERSION_ERROR, + msg="setFeatureCompatibilityVersion error response should contain code and codeName", + ), +] + + @pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): """Test setFeatureCompatibilityVersion succeeds on the admin database.""" @@ -128,6 +182,26 @@ def test_setFeatureCompatibilityVersion_user_db_rejected(database_client, collec ) +@pytest.mark.parametrize("test", pytest_params(SYSTEM_DB_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_system_db_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion fails on local and config databases.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + fcv = get_fcv(collection) + db_name = "local" if "local" in test.id else "config" + target_collection = collection.database.client[db_name]["test"] + result = execute_command( + target_collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + @pytest.mark.parametrize("test", pytest_params(UNRECOGNIZED_FIELD_TESTS)) def test_setFeatureCompatibilityVersion_unrecognized_field(database_client, collection, test): """Test setFeatureCompatibilityVersion rejects unrecognized fields.""" @@ -160,6 +234,25 @@ def test_setFeatureCompatibilityVersion_set_parameter_rejected(database_client, ) +@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_UNKNOWN_SUBFIELD_TESTS)) +def test_setFeatureCompatibilityVersion_writeConcern_unknown_subfield( + database_client, collection, test +): + """Test setFeatureCompatibilityVersion rejects unknown sub-fields inside writeConcern.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + @pytest.mark.parametrize("test", pytest_params(ERROR_CODE_TESTS)) def test_setFeatureCompatibilityVersion_error_code(database_client, collection, test): """Test setFeatureCompatibilityVersion error response contains a numeric code.""" @@ -173,3 +266,31 @@ def test_setFeatureCompatibilityVersion_error_code(database_client, collection, msg=test.msg, raw_res=True, ) + + +@pytest.mark.parametrize("test", pytest_params(SUCCESS_RESPONSE_TESTS)) +def test_setFeatureCompatibilityVersion_success_response(database_client, collection, test): + """Test setFeatureCompatibilityVersion success response contains ok:1.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + fcv = get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + +@pytest.mark.parametrize("test", pytest_params(ERROR_RESPONSE_TESTS)) +def test_setFeatureCompatibilityVersion_error_response(database_client, collection, test): + """Test setFeatureCompatibilityVersion error response contains code and codeName.""" + collection = test.prepare(database_client, collection) + result = execute_admin_command( + collection, test.build_command(CommandContext.from_collection(collection)) + ) + assertFailureCode(result, test.error_code, msg=test.msg) From 48230b10e4ed53760050abaddef2f4213d2b5af5 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 25 Jun 2026 17:03:25 -0700 Subject: [PATCH 10/12] put error and success in right files Signed-off-by: Alina (Xi) Li --- ...ibilityVersion_confirm_semantics_error.py} | 69 +---------- ...tibilityVersion_confirm_truthy_coercion.py | 102 ++++++++++++++++ ...ityVersion_confirm_type_coercion_error.py} | 88 +------------- ...atureCompatibilityVersion_core_behavior.py | 61 +++++++++- ...t_setFeatureCompatibilityVersion_errors.py | 60 +--------- ...yVersion_version_type_validation_error.py} | 35 +----- ...Version_version_value_validation_error.py} | 33 +---- ...atibilityVersion_writeConcern_accepted.py} | 100 +--------------- ...tyVersion_writeConcern_validation_error.py | 113 ++++++++++++++++++ 9 files changed, 288 insertions(+), 373 deletions(-) rename documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/{test_setFeatureCompatibilityVersion_confirm_semantics.py => test_setFeatureCompatibilityVersion_confirm_semantics_error.py} (61%) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_truthy_coercion.py rename documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/{test_setFeatureCompatibilityVersion_confirm_type_coercion.py => test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py} (61%) rename documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/{test_setFeatureCompatibilityVersion_version_type_validation.py => test_setFeatureCompatibilityVersion_version_type_validation_error.py} (70%) rename documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/{test_setFeatureCompatibilityVersion_version_value_validation.py => test_setFeatureCompatibilityVersion_version_value_validation_error.py} (81%) rename documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/{test_setFeatureCompatibilityVersion_writeConcern_validation.py => test_setFeatureCompatibilityVersion_writeConcern_accepted.py} (60%) create mode 100644 documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation_error.py diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py similarity index 61% rename from documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py rename to documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py index df23a25e8..fe863f35e 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py @@ -1,7 +1,6 @@ -"""Tests for setFeatureCompatibilityVersion confirm field semantics. +"""Tests for setFeatureCompatibilityVersion confirm field semantics (error cases). -Validates that the confirm field is required for version changes, -and that confirm:false or omitted confirm prevents FCV changes. +Validates that omitting confirm or setting confirm:false prevents FCV changes. """ import pytest @@ -20,16 +19,6 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Confirm Required]: confirm:true is required for version changes. -CONFIRM_TRUE_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "confirm_true_allows_change", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": True}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should allow version change with confirm:true", - ), -] - # Property [Confirm Omitted]: omitting confirm prevents version changes. CONFIRM_OMITTED_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -60,38 +49,6 @@ ), ] -# Property [Upgrade With Confirm]: upgrade with confirm:true succeeds. -UPGRADE_WITH_CONFIRM_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "upgrade_with_confirm", - command=lambda ctx: {"setFeatureCompatibilityVersion": "ORIGINAL_FCV", "confirm": True}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed on upgrade with confirm:true", - ), -] - - -@pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUE_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_true_allows_change( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion succeeds with confirm:true.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - original = get_fcv(collection) - other = "8.0" if original != "8.0" else "8.2" - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = other - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) - @pytest.mark.parametrize("test", pytest_params(CONFIRM_OMITTED_TESTS)) def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, collection, test): @@ -152,25 +109,3 @@ def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( raw_res=True, ) execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) - - -@pytest.mark.parametrize("test", pytest_params(UPGRADE_WITH_CONFIRM_TESTS)) -def test_setFeatureCompatibilityVersion_upgrade_with_confirm_succeeds( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion succeeds on upgrade with confirm:true.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - original = get_fcv(collection) - other = "8.0" if original != "8.0" else "8.2" - execute_admin_command(collection, {"setFeatureCompatibilityVersion": other, "confirm": True}) - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = original - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_truthy_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_truthy_coercion.py new file mode 100644 index 000000000..6a976a43a --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_truthy_coercion.py @@ -0,0 +1,102 @@ +"""Tests for setFeatureCompatibilityVersion confirm field truthy coercion. + +Validates that the confirm field accepts truthy numeric values +(int 1, double 1.0, Int64(1), Decimal128("1"), NaN, Infinity, -Infinity). +""" + +import pytest +from bson import Decimal128, Int64 + +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult +from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params + +from .utils.setFeatureCompatibilityVersion_common import get_fcv + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +# Property [Truthy Coercion]: confirm field accepts truthy numeric values. +CONFIRM_TRUTHY_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "int_1", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=1 (int) as true", + ), + CommandTestCase( + "double_1", + command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1.0}, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=1.0 (double) as true", + ), + CommandTestCase( + "long_1", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Int64(1), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Int64(1) as true", + ), + CommandTestCase( + "decimal_1", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": Decimal128("1"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Decimal128('1') as true", + ), + CommandTestCase( + "nan", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("nan"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=NaN as true", + ), + CommandTestCase( + "infinity", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("inf"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", + ), + CommandTestCase( + "negative_infinity", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": float("-inf"), + }, + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should accept confirm=-Infinity as true", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUTHY_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collection, test): + """Test setFeatureCompatibilityVersion accepts truthy confirm values.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + current = get_fcv(collection) + other = "8.0" if current != "8.0" else "8.2" + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = other + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + execute_admin_command(collection, {"setFeatureCompatibilityVersion": current, "confirm": True}) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py similarity index 61% rename from documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py rename to documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py index 4cb69593d..8bd1e80e3 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py @@ -1,7 +1,7 @@ -"""Tests for setFeatureCompatibilityVersion confirm field type coercion. +"""Tests for setFeatureCompatibilityVersion confirm field type coercion (error cases). -Validates how the confirm field handles various BSON types beyond bool, -recording coercion behavior (accepted-as-true vs rejected/treated-as-false). +Validates that the confirm field treats falsy values as false and rejects +non-numeric, non-bool types. """ import pytest @@ -21,68 +21,6 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Truthy Coercion]: confirm field accepts truthy numeric values. -CONFIRM_TRUTHY_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "int_1", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=1 (int) as true", - ), - CommandTestCase( - "double_1", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 1.0}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=1.0 (double) as true", - ), - CommandTestCase( - "long_1", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "OTHER_FCV", - "confirm": Int64(1), - }, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=Int64(1) as true", - ), - CommandTestCase( - "decimal_1", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "OTHER_FCV", - "confirm": Decimal128("1"), - }, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=Decimal128('1') as true", - ), - CommandTestCase( - "nan", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "OTHER_FCV", - "confirm": float("nan"), - }, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=NaN as true", - ), - CommandTestCase( - "infinity", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "OTHER_FCV", - "confirm": float("inf"), - }, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=Infinity as true", - ), - CommandTestCase( - "negative_infinity", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "OTHER_FCV", - "confirm": float("-inf"), - }, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept confirm=-Infinity as true", - ), -] - - # Property [Falsy Coercion]: confirm field treats falsy values as false, # requiring confirm to be truthy. CONFIRM_FALSY_TESTS: list[CommandTestCase] = [ @@ -163,26 +101,6 @@ ] -@pytest.mark.parametrize("test", pytest_params(CONFIRM_TRUTHY_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_truthy(database_client, collection, test): - """Test setFeatureCompatibilityVersion accepts truthy confirm values.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - current = get_fcv(collection) - other = "8.0" if current != "8.0" else "8.2" - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = other - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - execute_admin_command(collection, {"setFeatureCompatibilityVersion": current, "confirm": True}) - - @pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSY_TESTS)) def test_setFeatureCompatibilityVersion_confirm_falsy(database_client, collection, test): """Test setFeatureCompatibilityVersion treats falsy confirm values as false.""" diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 25b519473..87a86fbc6 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -1,7 +1,8 @@ -"""Tests for setFeatureCompatibilityVersion core behavior. +"""Tests for setFeatureCompatibilityVersion core behavior (success cases). Validates FCV set/get round-trip, idempotency, default value read-back, -and basic upgrade/downgrade with confirm. +basic upgrade/downgrade with confirm, admin-database acceptance, +and success response structure. """ import pytest @@ -86,6 +87,26 @@ ] +# Property [Admin DB Accepted]: setFeatureCompatibilityVersion succeeds on the admin database. +ADMIN_DB_ACCEPTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "admin_db_accepted", + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion should succeed on the admin database", + ), +] + + +# Property [Success Response Structure]: success response contains ok:1. +SUCCESS_RESPONSE_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "success_contains_ok", + expected={"ok": 1.0}, + msg="setFeatureCompatibilityVersion success response should contain ok:1", + ), +] + + @pytest.mark.parametrize("test", pytest_params(SET_CURRENT_TESTS)) def test_setFeatureCompatibilityVersion_set_current(database_client, collection, test): """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" @@ -170,3 +191,39 @@ def test_setFeatureCompatibilityVersion_getParameter_reflects_change( expected = {"ok": 1.0, "featureCompatibilityVersion": {"version": other}} assertSuccessPartial(result, expected, msg=test.msg) execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) + + +@pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) +def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): + """Test setFeatureCompatibilityVersion succeeds on the admin database.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + fcv = get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) + + +@pytest.mark.parametrize("test", pytest_params(SUCCESS_RESPONSE_TESTS)) +def test_setFeatureCompatibilityVersion_success_response(database_client, collection, test): + """Test setFeatureCompatibilityVersion success response contains ok:1.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + fcv = get_fcv(collection) + result = execute_admin_command( + collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} + ) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index 300cd5555..b4bdf97a8 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -1,7 +1,7 @@ """Tests for setFeatureCompatibilityVersion error cases. -Covers admin-database-only enforcement, unknown/extra fields, -response structure, and setParameter rejection. +Covers database enforcement (user/local/config DB rejection), unknown/extra fields, +error response structure, and setParameter rejection. """ import pytest @@ -25,16 +25,6 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Admin DB Accepted]: setFeatureCompatibilityVersion succeeds on the admin database. -ADMIN_DB_ACCEPTED_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "admin_db_accepted", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed on the admin database", - ), -] - - # Property [User DB Rejected]: setFeatureCompatibilityVersion fails on a user database. USER_DB_REJECTED_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -124,16 +114,6 @@ ] -# Property [Success Response Structure]: success response contains ok:1. -SUCCESS_RESPONSE_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "success_contains_ok", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion success response should contain ok:1", - ), -] - - # Property [Error Response Structure]: error response contains code and codeName. ERROR_RESPONSE_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -148,24 +128,6 @@ ] -@pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) -def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): - """Test setFeatureCompatibilityVersion succeeds on the admin database.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - @pytest.mark.parametrize("test", pytest_params(USER_DB_REJECTED_TESTS)) def test_setFeatureCompatibilityVersion_user_db_rejected(database_client, collection, test): """Test setFeatureCompatibilityVersion fails on a user database.""" @@ -268,24 +230,6 @@ def test_setFeatureCompatibilityVersion_error_code(database_client, collection, ) -@pytest.mark.parametrize("test", pytest_params(SUCCESS_RESPONSE_TESTS)) -def test_setFeatureCompatibilityVersion_success_response(database_client, collection, test): - """Test setFeatureCompatibilityVersion success response contains ok:1.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - @pytest.mark.parametrize("test", pytest_params(ERROR_RESPONSE_TESTS)) def test_setFeatureCompatibilityVersion_error_response(database_client, collection, test): """Test setFeatureCompatibilityVersion error response contains code and codeName.""" diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation_error.py similarity index 70% rename from documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py rename to documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation_error.py index 38658f2b4..41d9e87f8 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_type_validation_error.py @@ -1,7 +1,7 @@ -"""Tests for setFeatureCompatibilityVersion version field BSON type validation. +"""Tests for setFeatureCompatibilityVersion version field BSON type validation (error cases). -Validates that the version field only accepts string type and rejects -all other BSON types with TYPE_MISMATCH_ERROR. +Validates that the version field rejects all non-string BSON types +with TYPE_MISMATCH_ERROR, and rejects null with MISSING_FIELD_ERROR. """ import pytest @@ -20,8 +20,6 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -from .utils.setFeatureCompatibilityVersion_common import get_fcv - pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -57,15 +55,6 @@ def test_setFeatureCompatibilityVersion_version_type_rejected( ) -# Property [String Accepted]: setFeatureCompatibilityVersion accepts string type. -VERSION_STRING_ACCEPTED_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "version_string_accepted", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept string for version", - ), -] - # Property [Null Rejected]: setFeatureCompatibilityVersion rejects null for version. VERSION_NULL_REJECTED_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -77,24 +66,6 @@ def test_setFeatureCompatibilityVersion_version_type_rejected( ] -@pytest.mark.parametrize("test", pytest_params(VERSION_STRING_ACCEPTED_TESTS)) -def test_setFeatureCompatibilityVersion_version_string_accepted(database_client, collection, test): - """Test setFeatureCompatibilityVersion accepts string type for version.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - @pytest.mark.parametrize("test", pytest_params(VERSION_NULL_REJECTED_TESTS)) def test_setFeatureCompatibilityVersion_version_null_rejected(database_client, collection, test): """Test setFeatureCompatibilityVersion rejects null for version.""" diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation_error.py similarity index 81% rename from documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py rename to documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation_error.py index 505e11e4c..9c68b6059 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_version_value_validation_error.py @@ -1,4 +1,4 @@ -"""Tests for setFeatureCompatibilityVersion version value validation. +"""Tests for setFeatureCompatibilityVersion version value validation (error cases). Validates that the version field rejects unsupported, malformed, and edge-case string values. @@ -15,8 +15,6 @@ from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params -from .utils.setFeatureCompatibilityVersion_common import get_fcv - pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] @@ -104,17 +102,6 @@ ] -# Property [Current Version Accepted]: setFeatureCompatibilityVersion accepts -# the current binary version. -CURRENT_VERSION_ACCEPTED_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "current_version", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept the current binary version", - ), -] - - @pytest.mark.parametrize("test", pytest_params(VERSION_VALUE_REJECTION_TESTS)) def test_setFeatureCompatibilityVersion_version_value_rejected(database_client, collection, test): """Test setFeatureCompatibilityVersion rejects invalid version values.""" @@ -128,21 +115,3 @@ def test_setFeatureCompatibilityVersion_version_value_rejected(database_client, msg=test.msg, raw_res=True, ) - - -@pytest.mark.parametrize("test", pytest_params(CURRENT_VERSION_ACCEPTED_TESTS)) -def test_setFeatureCompatibilityVersion_current_version_accepted(database_client, collection, test): - """Test setFeatureCompatibilityVersion accepts the current binary version.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py similarity index 60% rename from documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py rename to documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py index d01e7c0e7..2c8b7fcac 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py @@ -1,7 +1,7 @@ -"""Tests for setFeatureCompatibilityVersion writeConcern field validation. +"""Tests for setFeatureCompatibilityVersion writeConcern field acceptance. -Validates writeConcern type validation, null-as-omitted behavior, -empty-doc acceptance, and wtimeout coercion. +Validates that writeConcern accepts valid object values, null-as-omitted, +empty-doc, omission, and various numeric types for wtimeout. """ import pytest @@ -12,7 +12,6 @@ CommandTestCase, ) from documentdb_tests.framework.assertions import assertResult -from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params @@ -66,82 +65,6 @@ ] -# Property [writeConcern Rejected]: setFeatureCompatibilityVersion rejects -# non-object writeConcern types. -WRITE_CONCERN_REJECTED_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "string", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": "majority", - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as string", - ), - CommandTestCase( - "int", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": 1, - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as int", - ), - CommandTestCase( - "bool", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": True, - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as bool", - ), - CommandTestCase( - "array", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": [{"w": 1}], - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as array", - ), - CommandTestCase( - "long", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": Int64(1), - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as long", - ), - CommandTestCase( - "double", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": 1.0, - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as double", - ), - CommandTestCase( - "decimal128", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": Decimal128("1"), - }, - error_code=TYPE_MISMATCH_ERROR, - msg="setFeatureCompatibilityVersion should reject writeConcern as Decimal128", - ), -] - - # Property [wtimeout Coercion]: setFeatureCompatibilityVersion accepts # various numeric types for wtimeout. WTIMEOUT_COERCION_TESTS: list[CommandTestCase] = [ @@ -215,23 +138,6 @@ def test_setFeatureCompatibilityVersion_writeConcern_accepted(database_client, c ) -@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_REJECTED_TESTS)) -def test_setFeatureCompatibilityVersion_writeConcern_rejected(database_client, collection, test): - """Test setFeatureCompatibilityVersion rejects non-object writeConcern types.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - @pytest.mark.parametrize("test", pytest_params(WTIMEOUT_COERCION_TESTS)) def test_setFeatureCompatibilityVersion_wtimeout_coercion(database_client, collection, test): """Test setFeatureCompatibilityVersion accepts various numeric types for wtimeout.""" diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation_error.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation_error.py new file mode 100644 index 000000000..4855b7459 --- /dev/null +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_validation_error.py @@ -0,0 +1,113 @@ +"""Tests for setFeatureCompatibilityVersion writeConcern field rejection (error cases). + +Validates that writeConcern rejects non-object types with TYPE_MISMATCH_ERROR. +""" + +import pytest +from bson import Decimal128, Int64 + +from documentdb_tests.compatibility.tests.core.utils.command_test_case import ( + CommandContext, + CommandTestCase, +) +from documentdb_tests.framework.assertions import assertResult +from documentdb_tests.framework.error_codes import TYPE_MISMATCH_ERROR +from documentdb_tests.framework.executor import execute_admin_command +from documentdb_tests.framework.parametrize import pytest_params + +from .utils.setFeatureCompatibilityVersion_common import get_fcv + +pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] + + +# Property [writeConcern Rejected]: setFeatureCompatibilityVersion rejects +# non-object writeConcern types. +WRITE_CONCERN_REJECTED_TESTS: list[CommandTestCase] = [ + CommandTestCase( + "string", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": "majority", + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as string", + ), + CommandTestCase( + "int", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": 1, + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as int", + ), + CommandTestCase( + "bool", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": True, + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as bool", + ), + CommandTestCase( + "array", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": [{"w": 1}], + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as array", + ), + CommandTestCase( + "long", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": Int64(1), + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as long", + ), + CommandTestCase( + "double", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": 1.0, + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as double", + ), + CommandTestCase( + "decimal128", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": Decimal128("1"), + }, + error_code=TYPE_MISMATCH_ERROR, + msg="setFeatureCompatibilityVersion should reject writeConcern as Decimal128", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_writeConcern_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects non-object writeConcern types.""" + collection = test.prepare(database_client, collection) + ctx = CommandContext.from_collection(collection) + cmd = test.build_command(ctx) + cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) + result = execute_admin_command(collection, cmd) + assertResult( + result, + expected=test.build_expected(ctx), + error_code=test.error_code, + msg=test.msg, + raw_res=True, + ) From a4582cfdb44b6de287ab2be959becae204f14b68 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 26 Jun 2026 13:12:15 -0700 Subject: [PATCH 11/12] remove duplicate Signed-off-by: Alina (Xi) Li --- ...tibilityVersion_confirm_semantics_error.py | 24 ++-- ...atureCompatibilityVersion_core_behavior.py | 120 +++--------------- ...t_setFeatureCompatibilityVersion_errors.py | 37 +----- 3 files changed, 35 insertions(+), 146 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py index fe863f35e..13a9bf0e8 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py @@ -22,17 +22,17 @@ # Property [Confirm Omitted]: omitting confirm prevents version changes. CONFIRM_OMITTED_TESTS: list[CommandTestCase] = [ CommandTestCase( - "confirm_omitted", + "downgrade_without_confirm", command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV"}, error_code=FCV_CONFIRM_REQUIRED_ERROR, - msg="setFeatureCompatibilityVersion should reject version change without confirm", + msg="setFeatureCompatibilityVersion should reject downgrade without confirm field", ), ] # Property [Confirm False]: confirm:false prevents version changes. CONFIRM_FALSE_TESTS: list[CommandTestCase] = [ CommandTestCase( - "confirm_false", + "confirm_false_rejects_change", command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": False}, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should reject version change with confirm:false", @@ -51,8 +51,10 @@ @pytest.mark.parametrize("test", pytest_params(CONFIRM_OMITTED_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, collection, test): - """Test setFeatureCompatibilityVersion fails when confirm is omitted.""" +def test_setFeatureCompatibilityVersion_downgrade_without_confirm( + database_client, collection, test +): + """Test setFeatureCompatibilityVersion rejects downgrade when confirm is omitted.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = get_fcv(collection) @@ -70,8 +72,10 @@ def test_setFeatureCompatibilityVersion_confirm_omitted_fails(database_client, c @pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSE_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_false_fails(database_client, collection, test): - """Test setFeatureCompatibilityVersion fails with confirm:false.""" +def test_setFeatureCompatibilityVersion_confirm_false_rejects_change( + database_client, collection, test +): + """Test setFeatureCompatibilityVersion rejects version change with confirm:false.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = get_fcv(collection) @@ -89,10 +93,8 @@ def test_setFeatureCompatibilityVersion_confirm_false_fails(database_client, col @pytest.mark.parametrize("test", pytest_params(UPGRADE_NO_CONFIRM_TESTS)) -def test_setFeatureCompatibilityVersion_upgrade_without_confirm_fails( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion rejects upgrade without confirm.""" +def test_setFeatureCompatibilityVersion_upgrade_without_confirm(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects upgrade when confirm is omitted.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = get_fcv(collection) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py index 87a86fbc6..8757587fa 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_core_behavior.py @@ -1,8 +1,7 @@ """Tests for setFeatureCompatibilityVersion core behavior (success cases). -Validates FCV set/get round-trip, idempotency, default value read-back, -basic upgrade/downgrade with confirm, admin-database acceptance, -and success response structure. +Validates idempotent set, downgrade/upgrade with confirm, and +getParameter readback after change. """ import pytest @@ -20,36 +19,14 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Set Current]: setting the current version succeeds idempotently. -SET_CURRENT_TESTS: list[CommandTestCase] = [ +# Property [Idempotent Set]: setting the current version succeeds and returns ok:1. +IDEMPOTENT_SET_TESTS: list[CommandTestCase] = [ CommandTestCase( - "set_current_version", + "idempotent_set_current_version", command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when setting the current version", - ), - CommandTestCase( - "idempotent_same_value", - command=lambda ctx: {"setFeatureCompatibilityVersion": "CURRENT_FCV", "confirm": True}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should be idempotent when re-setting the same value", - ), -] - - -# Property [GetParameter Readback]: getParameter reads back the current FCV. -GET_PARAMETER_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "getParameter_reads_back", - command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should persist and be readable via getParameter", - ), - CommandTestCase( - "fresh_deployment_default", - command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should have a readable default on a fresh deployment", + msg="setFeatureCompatibilityVersion should succeed idempotently when re-setting" + " current version", ), ] @@ -60,7 +37,7 @@ "downgrade_with_confirm", command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": True}, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when changing version with confirm", + msg="setFeatureCompatibilityVersion should succeed when downgrading version with confirm", ), ] @@ -71,45 +48,25 @@ "upgrade_with_confirm", command=lambda ctx: {"setFeatureCompatibilityVersion": "ORIGINAL_FCV", "confirm": True}, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed when upgrading back", + msg="setFeatureCompatibilityVersion should succeed when upgrading version with confirm", ), ] -# Property [GetParameter Reflects Change]: getParameter reflects FCV after change. +# Property [GetParameter Reflects Change]: getParameter returns the new version after change. GET_PARAMETER_AFTER_CHANGE_TESTS: list[CommandTestCase] = [ CommandTestCase( "getParameter_reflects_change", command=lambda ctx: {"getParameter": 1, "featureCompatibilityVersion": 1}, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should be reflected in getParameter after a change", - ), -] - - -# Property [Admin DB Accepted]: setFeatureCompatibilityVersion succeeds on the admin database. -ADMIN_DB_ACCEPTED_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "admin_db_accepted", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should succeed on the admin database", - ), -] - - -# Property [Success Response Structure]: success response contains ok:1. -SUCCESS_RESPONSE_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "success_contains_ok", - expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion success response should contain ok:1", + msg="getParameter should return the new version after setFeatureCompatibilityVersion", ), ] -@pytest.mark.parametrize("test", pytest_params(SET_CURRENT_TESTS)) -def test_setFeatureCompatibilityVersion_set_current(database_client, collection, test): - """Test setFeatureCompatibilityVersion succeeds when setting the current version.""" +@pytest.mark.parametrize("test", pytest_params(IDEMPOTENT_SET_TESTS)) +def test_setFeatureCompatibilityVersion_idempotent_set(database_client, collection, test): + """Test setFeatureCompatibilityVersion succeeds when re-setting the current version.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) fcv = get_fcv(collection) @@ -126,17 +83,6 @@ def test_setFeatureCompatibilityVersion_set_current(database_client, collection, ) -@pytest.mark.parametrize("test", pytest_params(GET_PARAMETER_TESTS)) -def test_setFeatureCompatibilityVersion_getParameter(database_client, collection, test): - """Test getParameter reads back the current FCV.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - execute_admin_command(collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True}) - result = execute_admin_command(collection, test.build_command(ctx)) - assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg) - - @pytest.mark.parametrize("test", pytest_params(DOWNGRADE_TESTS)) def test_setFeatureCompatibilityVersion_downgrade(database_client, collection, test): """Test setFeatureCompatibilityVersion can downgrade with confirm:true.""" @@ -181,7 +127,7 @@ def test_setFeatureCompatibilityVersion_upgrade(database_client, collection, tes def test_setFeatureCompatibilityVersion_getParameter_reflects_change( database_client, collection, test ): - """Test getParameter reflects the FCV after a change.""" + """Test getParameter returns the new version after setFeatureCompatibilityVersion.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = get_fcv(collection) @@ -191,39 +137,3 @@ def test_setFeatureCompatibilityVersion_getParameter_reflects_change( expected = {"ok": 1.0, "featureCompatibilityVersion": {"version": other}} assertSuccessPartial(result, expected, msg=test.msg) execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True}) - - -@pytest.mark.parametrize("test", pytest_params(ADMIN_DB_ACCEPTED_TESTS)) -def test_setFeatureCompatibilityVersion_admin_db_accepted(database_client, collection, test): - """Test setFeatureCompatibilityVersion succeeds on the admin database.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - -@pytest.mark.parametrize("test", pytest_params(SUCCESS_RESPONSE_TESTS)) -def test_setFeatureCompatibilityVersion_success_response(database_client, collection, test): - """Test setFeatureCompatibilityVersion success response contains ok:1.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - fcv = get_fcv(collection) - result = execute_admin_command( - collection, {"setFeatureCompatibilityVersion": fcv, "confirm": True} - ) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index b4bdf97a8..ddd7c8668 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -10,7 +10,7 @@ CommandContext, CommandTestCase, ) -from documentdb_tests.framework.assertions import assertFailureCode, assertResult +from documentdb_tests.framework.assertions import assertResult from documentdb_tests.framework.error_codes import ( FCV_INVALID_VERSION_ERROR, ILLEGAL_OPERATION_ERROR, @@ -100,30 +100,17 @@ ] -# Property [Error Contains Code]: error response contains a numeric code. +# Property [Error Contains Code]: invalid version returns FCV_INVALID_VERSION_ERROR. ERROR_CODE_TESTS: list[CommandTestCase] = [ CommandTestCase( - "invalid_version_error_code", + "invalid_version_returns_error", command=lambda ctx: { "setFeatureCompatibilityVersion": "invalid_version", "confirm": True, }, error_code=FCV_INVALID_VERSION_ERROR, - msg="setFeatureCompatibilityVersion should return a numeric error code for invalid version", - ), -] - - -# Property [Error Response Structure]: error response contains code and codeName. -ERROR_RESPONSE_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "error_contains_code_and_codeName", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "invalid_version", - "confirm": True, - }, - error_code=FCV_INVALID_VERSION_ERROR, - msg="setFeatureCompatibilityVersion error response should contain code and codeName", + msg="setFeatureCompatibilityVersion should return FCV_INVALID_VERSION_ERROR" + " for non-existent version string", ), ] @@ -216,8 +203,8 @@ def test_setFeatureCompatibilityVersion_writeConcern_unknown_subfield( @pytest.mark.parametrize("test", pytest_params(ERROR_CODE_TESTS)) -def test_setFeatureCompatibilityVersion_error_code(database_client, collection, test): - """Test setFeatureCompatibilityVersion error response contains a numeric code.""" +def test_setFeatureCompatibilityVersion_invalid_version_error(database_client, collection, test): + """Test setFeatureCompatibilityVersion returns FCV_INVALID_VERSION_ERROR.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) result = execute_admin_command(collection, test.build_command(ctx)) @@ -228,13 +215,3 @@ def test_setFeatureCompatibilityVersion_error_code(database_client, collection, msg=test.msg, raw_res=True, ) - - -@pytest.mark.parametrize("test", pytest_params(ERROR_RESPONSE_TESTS)) -def test_setFeatureCompatibilityVersion_error_response(database_client, collection, test): - """Test setFeatureCompatibilityVersion error response contains code and codeName.""" - collection = test.prepare(database_client, collection) - result = execute_admin_command( - collection, test.build_command(CommandContext.from_collection(collection)) - ) - assertFailureCode(result, test.error_code, msg=test.msg) From 2db52e939dbf6f89f5016db03bc9cba10e623937 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 26 Jun 2026 13:24:01 -0700 Subject: [PATCH 12/12] merge same test function into 1 Signed-off-by: Alina (Xi) Li --- ...tibilityVersion_confirm_semantics_error.py | 42 +++---------- ...lityVersion_confirm_type_coercion_error.py | 62 ++++++++----------- ...t_setFeatureCompatibilityVersion_errors.py | 44 +++---------- ...patibilityVersion_writeConcern_accepted.py | 29 +-------- 4 files changed, 47 insertions(+), 130 deletions(-) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py index 13a9bf0e8..530e6e5b6 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_semantics_error.py @@ -19,21 +19,20 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Confirm Omitted]: omitting confirm prevents version changes. -CONFIRM_OMITTED_TESTS: list[CommandTestCase] = [ +# Property [Confirm Required]: version change without confirm (omitted or false) is rejected. +CONFIRM_REQUIRED_TESTS: list[CommandTestCase] = [ CommandTestCase( "downgrade_without_confirm", command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV"}, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should reject downgrade without confirm field", ), -] - -# Property [Confirm False]: confirm:false prevents version changes. -CONFIRM_FALSE_TESTS: list[CommandTestCase] = [ CommandTestCase( "confirm_false_rejects_change", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": False}, + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": False, + }, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should reject version change with confirm:false", ), @@ -50,32 +49,9 @@ ] -@pytest.mark.parametrize("test", pytest_params(CONFIRM_OMITTED_TESTS)) -def test_setFeatureCompatibilityVersion_downgrade_without_confirm( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion rejects downgrade when confirm is omitted.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - original = get_fcv(collection) - other = "8.0" if original != "8.0" else "8.2" - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = other - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - -@pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSE_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_false_rejects_change( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion rejects version change with confirm:false.""" +@pytest.mark.parametrize("test", pytest_params(CONFIRM_REQUIRED_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_required(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects change without valid confirm.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) original = get_fcv(collection) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py index 8bd1e80e3..e1260e50e 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_confirm_type_coercion_error.py @@ -12,7 +12,10 @@ CommandTestCase, ) from documentdb_tests.framework.assertions import assertResult -from documentdb_tests.framework.error_codes import FCV_CONFIRM_REQUIRED_ERROR, TYPE_MISMATCH_ERROR +from documentdb_tests.framework.error_codes import ( + FCV_CONFIRM_REQUIRED_ERROR, + TYPE_MISMATCH_ERROR, +) from documentdb_tests.framework.executor import execute_admin_command from documentdb_tests.framework.parametrize import pytest_params @@ -21,9 +24,9 @@ pytestmark = [pytest.mark.admin, pytest.mark.no_parallel] -# Property [Falsy Coercion]: confirm field treats falsy values as false, -# requiring confirm to be truthy. -CONFIRM_FALSY_TESTS: list[CommandTestCase] = [ +# Property [Confirm Rejected]: confirm field treats falsy values as false +# and rejects non-numeric, non-bool types. +CONFIRM_REJECTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "int_0", command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 0}, @@ -32,7 +35,10 @@ ), CommandTestCase( "double_0", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": 0.0}, + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": 0.0, + }, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=0.0 as false", ), @@ -56,23 +62,24 @@ ), CommandTestCase( "null", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": None}, + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": None, + }, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=null as not-true", ), CommandTestCase( "negative_zero", - command=lambda ctx: {"setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": -0.0}, + command=lambda ctx: { + "setFeatureCompatibilityVersion": "OTHER_FCV", + "confirm": -0.0, + }, error_code=FCV_CONFIRM_REQUIRED_ERROR, msg="setFeatureCompatibilityVersion should treat confirm=-0.0 as false", ), -] - - -# Property [Type Rejected]: confirm field rejects non-numeric, non-bool types. -CONFIRM_TYPE_REJECTED_TESTS: list[CommandTestCase] = [ CommandTestCase( - "string", + "string_type", command=lambda ctx: { "setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": "true", @@ -81,7 +88,7 @@ msg="setFeatureCompatibilityVersion should reject confirm as string type", ), CommandTestCase( - "object", + "object_type", command=lambda ctx: { "setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": {"a": 1}, @@ -90,7 +97,7 @@ msg="setFeatureCompatibilityVersion should reject confirm as object type", ), CommandTestCase( - "array", + "array_type", command=lambda ctx: { "setFeatureCompatibilityVersion": "OTHER_FCV", "confirm": [True], @@ -101,28 +108,9 @@ ] -@pytest.mark.parametrize("test", pytest_params(CONFIRM_FALSY_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_falsy(database_client, collection, test): - """Test setFeatureCompatibilityVersion treats falsy confirm values as false.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - current = get_fcv(collection) - other = "8.0" if current != "8.0" else "8.2" - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = other - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - -@pytest.mark.parametrize("test", pytest_params(CONFIRM_TYPE_REJECTED_TESTS)) -def test_setFeatureCompatibilityVersion_confirm_type_rejected(database_client, collection, test): - """Test setFeatureCompatibilityVersion rejects non-numeric, non-bool confirm types.""" +@pytest.mark.parametrize("test", pytest_params(CONFIRM_REJECTED_TESTS)) +def test_setFeatureCompatibilityVersion_confirm_rejected(database_client, collection, test): + """Test setFeatureCompatibilityVersion rejects invalid confirm values.""" collection = test.prepare(database_client, collection) ctx = CommandContext.from_collection(collection) current = get_fcv(collection) diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py index ddd7c8668..59ec92d10 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_errors.py @@ -71,6 +71,16 @@ error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, msg="setFeatureCompatibilityVersion should reject misspelled 'confrim' as unknown field", ), + CommandTestCase( + "writeConcern_unknown_subfield", + command=lambda ctx: { + "setFeatureCompatibilityVersion": "CURRENT_FCV", + "confirm": True, + "writeConcern": {"unknownField": 1}, + }, + error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, + msg="setFeatureCompatibilityVersion should reject unknown sub-fields in writeConcern", + ), ] @@ -85,21 +95,6 @@ ] -# Property [writeConcern Unknown Sub-field]: unknown fields inside writeConcern are rejected. -WRITE_CONCERN_UNKNOWN_SUBFIELD_TESTS: list[CommandTestCase] = [ - CommandTestCase( - "writeConcern_unknown_subfield", - command=lambda ctx: { - "setFeatureCompatibilityVersion": "CURRENT_FCV", - "confirm": True, - "writeConcern": {"unknownField": 1}, - }, - error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR, - msg="setFeatureCompatibilityVersion should reject unknown sub-fields inside writeConcern", - ), -] - - # Property [Error Contains Code]: invalid version returns FCV_INVALID_VERSION_ERROR. ERROR_CODE_TESTS: list[CommandTestCase] = [ CommandTestCase( @@ -183,25 +178,6 @@ def test_setFeatureCompatibilityVersion_set_parameter_rejected(database_client, ) -@pytest.mark.parametrize("test", pytest_params(WRITE_CONCERN_UNKNOWN_SUBFIELD_TESTS)) -def test_setFeatureCompatibilityVersion_writeConcern_unknown_subfield( - database_client, collection, test -): - """Test setFeatureCompatibilityVersion rejects unknown sub-fields inside writeConcern.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - ) - - @pytest.mark.parametrize("test", pytest_params(ERROR_CODE_TESTS)) def test_setFeatureCompatibilityVersion_invalid_version_error(database_client, collection, test): """Test setFeatureCompatibilityVersion returns FCV_INVALID_VERSION_ERROR.""" diff --git a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py index 2c8b7fcac..c4ec4661e 100644 --- a/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py +++ b/documentdb_tests/compatibility/tests/system/administration/commands/setFeatureCompatibilityVersion/test_setFeatureCompatibilityVersion_writeConcern_accepted.py @@ -21,7 +21,7 @@ # Property [writeConcern Accepted]: setFeatureCompatibilityVersion accepts -# valid writeConcern values. +# valid writeConcern values and various numeric types for wtimeout. WRITE_CONCERN_ACCEPTED_TESTS: list[CommandTestCase] = [ CommandTestCase( "object", @@ -62,12 +62,6 @@ expected={"ok": 1.0}, msg="setFeatureCompatibilityVersion should succeed when writeConcern is omitted", ), -] - - -# Property [wtimeout Coercion]: setFeatureCompatibilityVersion accepts -# various numeric types for wtimeout. -WTIMEOUT_COERCION_TESTS: list[CommandTestCase] = [ CommandTestCase( "wtimeout_double", command=lambda ctx: { @@ -76,7 +70,7 @@ "writeConcern": {"wtimeout": 5000.0}, }, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number double", + msg="setFeatureCompatibilityVersion should accept wtimeout as double", ), CommandTestCase( "wtimeout_long", @@ -96,7 +90,7 @@ "writeConcern": {"wtimeout": Decimal128("5000")}, }, expected={"ok": 1.0}, - msg="setFeatureCompatibilityVersion should accept wtimeout as whole-number Decimal128", + msg="setFeatureCompatibilityVersion should accept wtimeout as Decimal128", ), CommandTestCase( "wtimeout_fractional_double", @@ -136,20 +130,3 @@ def test_setFeatureCompatibilityVersion_writeConcern_accepted(database_client, c msg=test.msg, raw_res=True, ) - - -@pytest.mark.parametrize("test", pytest_params(WTIMEOUT_COERCION_TESTS)) -def test_setFeatureCompatibilityVersion_wtimeout_coercion(database_client, collection, test): - """Test setFeatureCompatibilityVersion accepts various numeric types for wtimeout.""" - collection = test.prepare(database_client, collection) - ctx = CommandContext.from_collection(collection) - cmd = test.build_command(ctx) - cmd["setFeatureCompatibilityVersion"] = get_fcv(collection) - result = execute_admin_command(collection, cmd) - assertResult( - result, - expected=test.build_expected(ctx), - error_code=test.error_code, - msg=test.msg, - raw_res=True, - )