Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""Tests for setFeatureCompatibilityVersion confirm field semantics (error cases).

Validates that omitting confirm or setting confirm:false prevents FCV changes.
"""

import pytest

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

from .utils.setFeatureCompatibilityVersion_common import get_fcv

pytestmark = [pytest.mark.admin, pytest.mark.no_parallel]


# 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",
),
CommandTestCase(
"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",
),
]

# 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",
),
]


@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)
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(UPGRADE_NO_CONFIRM_TESTS))
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)
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,
)
execute_admin_command(collection, {"setFeatureCompatibilityVersion": original, "confirm": True})
Original file line number Diff line number Diff line change
@@ -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})
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Tests for setFeatureCompatibilityVersion confirm field type coercion (error cases).

Validates that the confirm field treats falsy values as false and rejects
non-numeric, non-bool types.
"""

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 (
FCV_CONFIRM_REQUIRED_ERROR,
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 [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},
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",
),
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",
),
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",
),
CommandTestCase(
"string_type",
command=lambda ctx: {
"setFeatureCompatibilityVersion": "OTHER_FCV",
"confirm": "true",
},
error_code=TYPE_MISMATCH_ERROR,
msg="setFeatureCompatibilityVersion should reject confirm as string type",
),
CommandTestCase(
"object_type",
command=lambda ctx: {
"setFeatureCompatibilityVersion": "OTHER_FCV",
"confirm": {"a": 1},
},
error_code=TYPE_MISMATCH_ERROR,
msg="setFeatureCompatibilityVersion should reject confirm as object type",
),
CommandTestCase(
"array_type",
command=lambda ctx: {
"setFeatureCompatibilityVersion": "OTHER_FCV",
"confirm": [True],
},
error_code=TYPE_MISMATCH_ERROR,
msg="setFeatureCompatibilityVersion should reject confirm as array type",
),
]


@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)
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,
)
Loading
Loading