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,37 @@
"""Tests for hostInfo command argument handling.

hostInfo takes no arguments: the command value is ignored and any BSON type
is accepted, always returning ok:1.
"""

import pytest

from documentdb_tests.framework.assertions import assertProperties
from documentdb_tests.framework.bson_type_validator import (
BsonTypeTestCase,
generate_bson_acceptance_test_cases,
)
from documentdb_tests.framework.executor import execute_admin_command
from documentdb_tests.framework.property_checks import Eq
from documentdb_tests.framework.test_constants import BsonType

pytestmark = pytest.mark.admin


BSON_TYPE_PARAMS = [
BsonTypeTestCase(
id="hostInfo_command_value",
msg="hostInfo should accept any BSON type as command value",
keyword="hostInfo",
valid_types=list(BsonType),
),
]

ACCEPTANCE_CASES = generate_bson_acceptance_test_cases(BSON_TYPE_PARAMS)


@pytest.mark.parametrize("bson_type,sample_value,spec", ACCEPTANCE_CASES)
def test_hostInfo_argument_types(collection, bson_type, sample_value, spec):
"""Test that hostInfo accepts any BSON type as its command value."""
result = execute_admin_command(collection, {"hostInfo": sample_value})
assertProperties(result, {"ok": Eq(1.0)}, msg=spec.msg, raw_res=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Tests for hostInfo core behavior and consistency.

Validates that hostInfo ignores its argument value and succeeds across
different database contexts.
"""

import pytest

from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import (
DiagnosticTestCase,
)
from documentdb_tests.framework.assertions import assertProperties
from documentdb_tests.framework.executor import execute_admin_command, execute_command
from documentdb_tests.framework.parametrize import pytest_params
from documentdb_tests.framework.property_checks import Eq

pytestmark = pytest.mark.admin


ACCESS_TESTS = [
# The MongoDB manual states hostInfo must be run against the admin database,
# but in practice it succeeds on any database.
DiagnosticTestCase(
id="succeeds_on_non_admin_db",
Comment thread
PatersonProjects marked this conversation as resolved.
use_admin=False,
checks={"ok": Eq(1.0)},
msg="hostInfo should succeed on a non-admin database",
),
]


@pytest.mark.parametrize("test", pytest_params(ACCESS_TESTS))
def test_hostInfo_access(collection, test):
"""Verify hostInfo access behaviour across different database contexts."""
if test.use_admin:
result = execute_admin_command(collection, {"hostInfo": 1})
else:
result = execute_command(collection, {"hostInfo": 1})
assertProperties(result, test.checks, msg=test.msg, raw_res=True)


def test_hostInfo_argument_value_ignored(collection):
"""Verify the command value does not affect the os/extra output."""
numeric = execute_admin_command(collection, {"hostInfo": 1})
other = execute_admin_command(collection, {"hostInfo": "ignored"})
assertProperties(
other,
{"os": Eq(numeric.get("os")), "extra": Eq(numeric.get("extra"))},
raw_res=True,
msg="hostInfo output should not depend on the command value",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Tests for hostInfo command error conditions.

Validates that invalid usages of hostInfo produce the appropriate error codes.
"""

import pytest

from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import (
DiagnosticTestCase,
)
from documentdb_tests.framework.assertions import assertFailureCode
from documentdb_tests.framework.error_codes import (
COMMAND_NOT_FOUND_ERROR,
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


ERROR_TESTS: list[DiagnosticTestCase] = [
DiagnosticTestCase(
id="unrecognized_field",
command={"hostInfo": 1, "unknownField": 1},
use_admin=True,
error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR,
msg="Should reject unrecognized fields",
),
DiagnosticTestCase(
id="case_sensitive",
command={"HostInfo": 1},
use_admin=True,
error_code=COMMAND_NOT_FOUND_ERROR,
msg="Case-mismatched command name should fail",
),
]


@pytest.mark.parametrize("test", pytest_params(ERROR_TESTS))
def test_hostInfo_error_conditions(collection, test):
"""Verifies hostInfo rejects invalid usages with appropriate error codes."""
if test.use_admin:
result = execute_admin_command(collection, test.command)
else:
result = execute_command(collection, test.command)
assertFailureCode(result, test.error_code, msg=test.msg)
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
"""Tests for hostInfo command response structure.

Validates presence, types, and value constraints of the system, os, and extra
sub-documents returned by hostInfo.
"""

import pytest

from documentdb_tests.compatibility.tests.system.diagnostic.utils.diagnostic_test_case import (
DiagnosticTestCase,
)
from documentdb_tests.framework.assertions import assertProperties
from documentdb_tests.framework.executor import execute_admin_command
from documentdb_tests.framework.parametrize import pytest_params
from documentdb_tests.framework.property_checks import (
Gt,
Gte,
IsType,
NonEmptyStr,
)

pytestmark = pytest.mark.admin


PROPERTY_TESTS: list[DiagnosticTestCase] = [
DiagnosticTestCase(
id="system_is_object",
checks={"system": IsType("object")},
msg="'system' should be an embedded document",
),
DiagnosticTestCase(
id="os_is_object",
checks={"os": IsType("object")},
msg="'os' should be an embedded document",
),
DiagnosticTestCase(
id="extra_is_object",
checks={"extra": IsType("object")},
msg="'extra' should be an embedded document",
),
DiagnosticTestCase(
id="system_currentTime_is_date",
checks={"system.currentTime": IsType("date")},
msg="'system.currentTime' should be a date",
),
DiagnosticTestCase(
id="system_hostname_nonempty",
checks={"system.hostname": NonEmptyStr()},
msg="'system.hostname' should be a non-empty string",
),
DiagnosticTestCase(
id="system_cpuAddrSize_positive",
checks={"system.cpuAddrSize": Gt(0)},
msg="'system.cpuAddrSize' should be greater than 0",
),
DiagnosticTestCase(
id="system_memLimitMB_positive",
checks={"system.memLimitMB": Gt(0)},
msg="'system.memLimitMB' should be greater than 0",
),
DiagnosticTestCase(
id="system_cpuArch_nonempty",
checks={"system.cpuArch": NonEmptyStr()},
msg="'system.cpuArch' should be a non-empty string",
),
DiagnosticTestCase(
id="system_numaEnabled_is_bool",
checks={"system.numaEnabled": IsType("bool")},
msg="'system.numaEnabled' should be a bool",
),
# The following three fields (numPhysicalCores, numCpuSockets, numNumaNodes) are
# observed in DocumentDB responses but are NOT listed in the MongoDB manual's
# hostInfo reference. The manual only documents numCores and
# numCoresAvailableToProcess under the system sub-document.
DiagnosticTestCase(
Comment thread
PatersonProjects marked this conversation as resolved.
id="system_numPhysicalCores_positive",
checks={"system.numPhysicalCores": Gt(0)},
msg="'system.numPhysicalCores' should be greater than 0",
),
DiagnosticTestCase(
id="system_numCpuSockets_positive",
checks={"system.numCpuSockets": Gt(0)},
msg="'system.numCpuSockets' should be greater than 0",
),
DiagnosticTestCase(
id="system_numNumaNodes_positive",
checks={"system.numNumaNodes": Gt(0)},
msg="'system.numNumaNodes' should be greater than 0",
),
DiagnosticTestCase(
id="os_type_nonempty",
checks={"os.type": NonEmptyStr()},
msg="'os.type' should be a non-empty string",
),
DiagnosticTestCase(
id="os_name_is_string",
checks={"os.name": IsType("string")},
msg="'os.name' should be a string",
),
DiagnosticTestCase(
id="os_version_is_string",
checks={"os.version": IsType("string")},
msg="'os.version' should be a string",
),
DiagnosticTestCase(
id="extra_versionString_is_string",
checks={"extra.versionString": IsType("string")},
msg="'extra.versionString' should be a string",
),
DiagnosticTestCase(
id="extra_pageSize_positive",
checks={"extra.pageSize": Gt(0)},
msg="'extra.pageSize' should be greater than 0",
),
DiagnosticTestCase(
id="system_numCores_positive",
checks={"system.numCores": Gte(1)},
msg="'system.numCores' should be at least 1",
),
DiagnosticTestCase(
id="system_numCoresAvailableToProcess_gte_neg1",
checks={"system.numCoresAvailableToProcess": Gte(-1)},
msg="'system.numCoresAvailableToProcess' should be >= -1",
),
DiagnosticTestCase(
id="system_memSizeMB_positive",
checks={"system.memSizeMB": Gt(0)},
msg="'system.memSizeMB' should be greater than 0",
),
]


@pytest.mark.parametrize("test", pytest_params(PROPERTY_TESTS))
def test_hostInfo_response_properties(collection, test):
"""Verifies hostInfo response fields have expected types and values."""
result = execute_admin_command(collection, {"hostInfo": 1})
assertProperties(result, test.checks, msg=test.msg, raw_res=True)


def test_hostInfo_memSizeMB_gte_memLimitMB(collection):
"""Verify system.memLimitMB does not exceed system.memSizeMB."""
result = execute_admin_command(collection, {"hostInfo": 1})
mem_limit = result.get("system", {}).get("memLimitMB")
assertProperties(
result,
{"system.memSizeMB": Gte(mem_limit)},
raw_res=True,
msg="'system.memSizeMB' should be >= 'system.memLimitMB'",
)


def test_hostInfo_extra_platform_specific_fields(collection):
"""Verify extra contains the OS-specific fields documented for the host platform."""
result = execute_admin_command(collection, {"hostInfo": 1})
os_type = result.get("os", {}).get("type")
if os_type == "Linux":
Comment thread
PatersonProjects marked this conversation as resolved.
checks = {
"extra.libcVersion": IsType("string"),
"extra.kernelVersion": IsType("string"),
"extra.numPages": Gt(0),
"extra.maxOpenFiles": Gt(0),
}
elif os_type == "Darwin":
checks = {
"extra.cpuString": IsType("string"),
}
else:
pytest.skip(f"Unrecognized os.type {os_type!r}; platform-specific fields not asserted")
assertProperties(
result, checks, raw_res=True, msg=f"extra should match documented {os_type} fields"
)
Loading