Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Tests for setParameter argument validation (success cases).

Validates control field Int64 max, parameter value range, and string param acceptance.
Type coercion matrices are in test_setParameter_bson_type_validation.py.
"""

import pytest

from documentdb_tests.compatibility.tests.core.utils.command_test_case import (
CommandContext,
CommandTestCase,
)
from documentdb_tests.framework.assertions import assertSuccessPartial
from documentdb_tests.framework.executor import execute_admin_command
from documentdb_tests.framework.parametrize import pytest_params
from documentdb_tests.framework.test_constants import INT64_MAX

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


# Property [Name Acceptance]: setParameter accepts edge-case control field values.
NAME_ACCEPTANCE_TESTS: list[CommandTestCase] = [
CommandTestCase(
"control_field_int64_max",
command=lambda ctx: {"setParameter": INT64_MAX, "logLevel": 0},
expected={"ok": 1.0},
msg="setParameter should accept Int64 max as control field value",
),
]


@pytest.mark.parametrize("test", pytest_params(NAME_ACCEPTANCE_TESTS))
def test_setParameter_name_accepted(database_client, collection, test):
"""Test setParameter accepts valid parameter names."""
collection = test.prepare(database_client, collection)
ctx = CommandContext.from_collection(collection)
result = execute_admin_command(collection, test.build_command(ctx))
assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg)


# Standalone tests below require save/restore of server state after each set.


# Property [Integer Range]: integer-typed parameters accept values within valid bounds.
def test_setParameter_integer_param_with_fractional_double_coerces(collection):
"""Test setParameter truncates fractional double for integer-typed param."""
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 1.5})
assertSuccessPartial(
result, {"ok": 1.0}, msg="setParameter should truncate fractional double for integer param"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})


def test_setParameter_integer_param_valid_range(collection):
"""Test setParameter accepts integer at valid upper bound."""
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 5})
assertSuccessPartial(
result, {"ok": 1.0}, msg="setParameter should accept logLevel at upper bound"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})


# Property [String Param Acceptance]: string-typed parameters accept valid strings.
def test_setParameter_string_param_valid_succeeds(collection):
"""Test setParameter accepts valid short string for string-typed param."""
result = execute_admin_command(
collection, {"setParameter": 1, "automationServiceDescriptor": "test"}
)
assertSuccessPartial(result, {"ok": 1.0}, msg="setParameter should accept valid string value")
execute_admin_command(collection, {"setParameter": 1, "automationServiceDescriptor": ""})
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""Tests for setParameter BSON type validation (success cases).

Validates control field acceptance of all BSON types, and type coercion
behavior for boolean and integer parameter values.
"""

import pytest
from bson import Decimal128, Int64

from documentdb_tests.framework.assertions import assertSuccessPartial
from documentdb_tests.framework.bson_type_validator import (
BsonType,
BsonTypeTestCase,
generate_bson_acceptance_test_cases,
)
from documentdb_tests.framework.executor import execute_admin_command

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


# Property [Control Field Acceptance]: setParameter control field accepts all BSON types.
CONTROL_FIELD_PARAM = [
BsonTypeTestCase(
id="setParameter_control",
msg="setParameter control field should accept all BSON types",
keyword="setParameter",
valid_types=list(BsonType),
requires={"logLevel": 0},
),
]

CONTROL_FIELD_ACCEPTANCE = generate_bson_acceptance_test_cases(CONTROL_FIELD_PARAM)


@pytest.mark.parametrize("bson_type,sample_value,spec", CONTROL_FIELD_ACCEPTANCE)
def test_setParameter_control_field_bson_type_accepted(collection, bson_type, sample_value, spec):
"""Test setParameter control field accepts all BSON types."""
result = execute_admin_command(collection, {"setParameter": sample_value, "logLevel": 0})
assertSuccessPartial(result, {"ok": 1.0}, msg=f"{spec.msg} (bson_type={bson_type.value})")


# Property [Boolean Coercion]: boolean-typed params accept many BSON types via coercion.
@pytest.mark.parametrize(
"value,desc",
[
pytest.param(True, "bool True", id="true"),
pytest.param(False, "bool False", id="false"),
pytest.param(1, "int 1", id="int1"),
pytest.param(0, "int 0", id="int0"),
pytest.param(1.0, "double 1.0", id="double1"),
pytest.param(0.0, "double 0.0", id="double0"),
pytest.param(Int64(1), "Int64(1)", id="long1"),
pytest.param(Int64(0), "Int64(0)", id="long0"),
pytest.param("true", "string 'true'", id="string"),
pytest.param([True], "array [True]", id="array"),
pytest.param({"a": True}, "document", id="document"),
],
)
def test_setParameter_boolean_coercion_accepted(collection, value, desc):
"""Test setParameter boolean parameter coercion."""
original = execute_admin_command(collection, {"getParameter": 1, "quiet": 1})
result = execute_admin_command(collection, {"setParameter": 1, "quiet": value})
assertSuccessPartial(
result, {"ok": 1.0}, msg=f"setParameter boolean param should accept {desc}"
)
execute_admin_command(collection, {"setParameter": 1, "quiet": original["quiet"]})


# Property [Integer Coercion Accepted]: integer-typed params accept whole-number numerics.
@pytest.mark.parametrize(
"value,desc",
[
pytest.param(1, "int32", id="int32"),
pytest.param(Int64(1), "Int64", id="long"),
pytest.param(1.0, "whole double", id="whole_double"),
pytest.param(Decimal128("1"), "Decimal128 whole", id="decimal128_whole"),
pytest.param(True, "bool True", id="bool"),
],
)
def test_setParameter_integer_coercion_accepted(collection, value, desc):
"""Test setParameter integer parameter coercion."""
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": value})
assertSuccessPartial(
result, {"ok": 1.0}, msg=f"setParameter integer param should accept {desc}"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
"""Tests for setParameter command core behavior.

Validates single/multiple parameter modification, admin database requirement,
runtime vs startup-only parameters, command shape, response structure, and
getParameter interaction.
"""

import pytest

from documentdb_tests.compatibility.tests.core.utils.command_test_case import (
CommandContext,
CommandTestCase,
)
from documentdb_tests.framework.assertions import 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]


# Property [Command Acceptance]: setParameter accepts valid commands on admin db.
COMMAND_ACCEPTANCE_TESTS: list[CommandTestCase] = [
CommandTestCase(
"admin_db_succeeds",
command=lambda ctx: {"setParameter": 1, "logLevel": 0},
expected={"ok": 1.0},
msg="setParameter should succeed on admin db",
),
CommandTestCase(
"comment_field_accepted",
command=lambda ctx: {"setParameter": 1, "logLevel": 0, "comment": "test"},
expected={"ok": 1.0},
msg="setParameter should accept comment field alongside params",
),
]


@pytest.mark.parametrize("test", pytest_params(COMMAND_ACCEPTANCE_TESTS))
def test_setParameter_accepted(database_client, collection, test):
"""Test setParameter command acceptance cases."""
collection = test.prepare(database_client, collection)
ctx = CommandContext.from_collection(collection)
result = execute_admin_command(collection, test.build_command(ctx))
assertSuccessPartial(result, test.build_expected(ctx), msg=test.msg)


# Standalone tests below require save/restore of server state after each set.


# Property [Response Structure]: setParameter returns ok:1 and previous value in 'was'.
def test_setParameter_single_param_returns_ok(collection):
"""Test setParameter with one runtime-settable parameter returns ok:1."""
original = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
original_val = original["logLevel"]
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 1})
assertSuccessPartial(result, {"ok": 1.0}, msg="setParameter should return ok:1")
execute_admin_command(collection, {"setParameter": 1, "logLevel": original_val})


def test_setParameter_returns_was_field(collection):
"""Test setParameter response includes the previous value in 'was' field."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 2})
assertSuccessPartial(
result, {"ok": 1.0, "was": 0}, msg="setParameter should report previous value in 'was'"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})


def test_setParameter_boolean_was_type(collection):
"""Test setParameter 'was' field for a boolean parameter is boolean type."""
original = execute_admin_command(collection, {"getParameter": 1, "quiet": 1})
execute_admin_command(collection, {"setParameter": 1, "quiet": False})
result = execute_admin_command(collection, {"setParameter": 1, "quiet": True})
assertSuccessPartial(
result, {"ok": 1.0, "was": False}, msg="setParameter 'was' should be boolean for quiet"
)
execute_admin_command(collection, {"setParameter": 1, "quiet": original["quiet"]})


# Property [Value Persistence]: setParameter changes are reflected in getParameter.
def test_setParameter_getParameter_reflects_new_value(collection):
"""Test setParameter changes are reflected via getParameter."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
execute_admin_command(collection, {"setParameter": 1, "logLevel": 3})
result = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
assertSuccessPartial(
result, {"logLevel": 3}, msg="setParameter should reflect new value via getParameter"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})


def test_setParameter_getParameter_unchanged_after_failure(collection):
"""Test setParameter getParameter is unchanged after a failed set."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
execute_admin_command(collection, {"setParameter": 1, "logLevel": "invalid"})
result = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
assertSuccessPartial(
result, {"logLevel": 0}, msg="setParameter should leave value unchanged after failure"
)


# Property [Idempotency]: setting a parameter to its current value succeeds.
def test_setParameter_idempotent_set(collection):
"""Test setParameter setting a parameter to its current value returns ok:1."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
assertSuccessPartial(
result, {"ok": 1.0, "was": 0}, msg="setParameter should succeed idempotently"
)


# Property [Multiple Parameters]: setParameter sets multiple params in one command.
def test_setParameter_two_params_returns_ok(collection):
"""Test setParameter with two params in one command sets both."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0, "quiet": False})
result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 1, "quiet": True})
assertSuccessPartial(result, {"ok": 1.0}, msg="setParameter should set both parameters")
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0, "quiet": False})


# Property [Round Trip]: value can be restored via 'was' field.
def test_setParameter_round_trip_restore(collection):
"""Test setParameter round-trip: set new, restore via 'was' field."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0})
set_result = execute_admin_command(collection, {"setParameter": 1, "logLevel": 3})
original_val = set_result["was"]
execute_admin_command(collection, {"setParameter": 1, "logLevel": original_val})
result = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
assertSuccessPartial(result, {"logLevel": 0}, msg="setParameter should restore to original")


# Property [Boolean Toggle]: boolean-typed parameters toggle correctly.
def test_setParameter_boolean_toggle(collection):
"""Test setParameter boolean-typed parameter toggles correctly."""
original = execute_admin_command(collection, {"getParameter": 1, "quiet": 1})
execute_admin_command(collection, {"setParameter": 1, "quiet": False})
result = execute_admin_command(collection, {"getParameter": 1, "quiet": 1})
assertSuccessPartial(result, {"quiet": False}, msg="setParameter boolean should be False")
execute_admin_command(collection, {"setParameter": 1, "quiet": original["quiet"]})


# Property [Ordering Independence]: parameter order in command does not affect result.
def test_setParameter_ordering_independence(collection):
"""Test setParameter parameter order in command does not affect result."""
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0, "quiet": False})
execute_admin_command(collection, {"setParameter": 1, "logLevel": 2, "quiet": True})
state1 = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0, "quiet": False})
execute_admin_command(collection, {"setParameter": 1, "quiet": True, "logLevel": 2})
state2 = execute_admin_command(collection, {"getParameter": 1, "logLevel": 1})
assertSuccessPartial(
state2, {"logLevel": state1["logLevel"]}, msg="setParameter order should not matter"
)
execute_admin_command(collection, {"setParameter": 1, "logLevel": 0, "quiet": False})
Loading
Loading