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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# macOS
.DS_Store

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import pytest

from documentdb_tests.compatibility.tests.core.collections.commands.utils.command_test_case import (
CommandContext,
CommandTestCase,
)
from documentdb_tests.compatibility.tests.core.collections.commands.utils.target_collection import (
NamedCollection,
)
from documentdb_tests.framework.assertions import assertResult
from documentdb_tests.framework.executor import execute_command
from documentdb_tests.framework.parametrize import pytest_params

# Property [Basic Drop Response]: drop returns ok:1 with expected fields
# for various collection states.
DROP_BASIC_TESTS: list[CommandTestCase] = [
CommandTestCase(
"with_documents",
docs=[{"_id": 1, "a": 1}],
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should return nIndexesWas, ns, and ok",
),
CommandTestCase(
"empty_collection",
target_collection=NamedCollection(),
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Explicitly created empty collection should have nIndexesWas=1",
),
CommandTestCase(
"nonexistent",
command={"drop": "nonexistent_coll_xyz"},
expected={"ok": 1.0},
msg="Non-existent collection drop should return ok:1",
),
]

# Property [Special Name Acceptance]: drop accepts collection names with
# spaces, unicode, and dots.
DROP_SPECIAL_NAME_TESTS: list[CommandTestCase] = [
CommandTestCase(
"spaces",
target_collection=NamedCollection(suffix=" spaces"),
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with spaces in name",
),
CommandTestCase(
"unicode",
target_collection=NamedCollection(suffix="_drôp_ünïcödé"),
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with unicode in name",
),
CommandTestCase(
"dots",
target_collection=NamedCollection(suffix=".dots"),
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with dots in name",
),
]

# Property [Null Document Values]: drop succeeds regardless of null values
# in documents.
DROP_NULL_HANDLING_TESTS: list[CommandTestCase] = [
CommandTestCase(
"null_document_values",
docs=[{"_id": 1, "a": None}, {"_id": 2, "b": None, "c": None}],
command=lambda ctx: {"drop": ctx.collection},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Drop should succeed regardless of null document values",
),
]

DROP_BASIC_ALL_TESTS: list[CommandTestCase] = (
DROP_BASIC_TESTS + DROP_SPECIAL_NAME_TESTS + DROP_NULL_HANDLING_TESTS
)


@pytest.mark.collection_mgmt
@pytest.mark.parametrize("test", pytest_params(DROP_BASIC_ALL_TESTS))
def test_drop_basic(database_client, collection, test):
"""Test basic drop command response."""
collection = test.prepare(database_client, collection)
ctx = CommandContext.from_collection(collection)
result = execute_command(collection, test.build_command(ctx))
assertResult(
result,
expected=test.build_expected(ctx),
error_code=test.error_code,
msg=test.msg,
raw_res=True,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import pytest

from documentdb_tests.compatibility.tests.core.collections.commands.utils.command_test_case import (
CommandContext,
CommandTestCase,
)
from documentdb_tests.framework.assertions import assertResult
from documentdb_tests.framework.error_codes import INVALID_NAMESPACE_ERROR
from documentdb_tests.framework.executor import execute_command
from documentdb_tests.framework.parametrize import pytest_params

# Property [Invalid Name Type]: drop rejects non-string name values with
# INVALID_NAMESPACE_ERROR.
DROP_INVALID_NAME_TYPE_TESTS: list[CommandTestCase] = [
CommandTestCase(
"null",
command={"drop": None},
error_code=INVALID_NAMESPACE_ERROR,
msg="Null collection name should fail with InvalidNamespace",
),
CommandTestCase(
"integer",
command={"drop": 123},
error_code=INVALID_NAMESPACE_ERROR,
msg="Integer collection name should fail with InvalidNamespace",
),
CommandTestCase(
"boolean",
command={"drop": True},
error_code=INVALID_NAMESPACE_ERROR,
msg="Boolean collection name should fail with InvalidNamespace",
),
CommandTestCase(
"double",
command={"drop": 1.5},
error_code=INVALID_NAMESPACE_ERROR,
msg="Double collection name should fail with InvalidNamespace",
),
CommandTestCase(
"object",
command={"drop": {"a": 1}},
error_code=INVALID_NAMESPACE_ERROR,
msg="Object collection name should fail with InvalidNamespace",
),
CommandTestCase(
"array",
command={"drop": [1, 2]},
error_code=INVALID_NAMESPACE_ERROR,
msg="Array collection name should fail with InvalidNamespace",
),
]

# Property [Invalid Name Value]: drop rejects invalid string name values
# with INVALID_NAMESPACE_ERROR.
DROP_INVALID_NAME_VALUE_TESTS: list[CommandTestCase] = [
CommandTestCase(
"empty_string",
command={"drop": ""},
error_code=INVALID_NAMESPACE_ERROR,
msg="Empty string name should fail with InvalidNamespace",
),
CommandTestCase(
"null_byte",
command={"drop": "test\x00coll"},
error_code=INVALID_NAMESPACE_ERROR,
msg="Name with null byte should fail with InvalidNamespace",
),
CommandTestCase(
"just_dot",
command={"drop": "."},
error_code=INVALID_NAMESPACE_ERROR,
msg="Single dot name should fail with InvalidNamespace",
),
CommandTestCase(
"leading_dot",
command={"drop": ".test"},
error_code=INVALID_NAMESPACE_ERROR,
msg="Leading dot name should fail with InvalidNamespace",
),
]

DROP_INVALID_NAME_TESTS: list[CommandTestCase] = (
DROP_INVALID_NAME_TYPE_TESTS + DROP_INVALID_NAME_VALUE_TESTS
)


@pytest.mark.collection_mgmt
@pytest.mark.parametrize("test", pytest_params(DROP_INVALID_NAME_TESTS))
def test_drop_invalid_names(database_client, collection, test):
"""Test drop command rejects invalid collection names."""
collection = test.prepare(database_client, collection)
ctx = CommandContext.from_collection(collection)
result = execute_command(collection, test.build_command(ctx))
assertResult(
result,
expected=test.build_expected(ctx),
error_code=test.error_code,
msg=test.msg,
raw_res=True,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import pytest

from documentdb_tests.compatibility.tests.core.collections.commands.utils.command_test_case import (
CommandContext,
CommandTestCase,
)
from documentdb_tests.framework.assertions import assertResult
from documentdb_tests.framework.error_codes import (
FAILED_TO_PARSE_ERROR,
TYPE_MISMATCH_ERROR,
UNRECOGNIZED_COMMAND_FIELD_ERROR,
)
from documentdb_tests.framework.executor import execute_command
from documentdb_tests.framework.parametrize import pytest_params

# Property [writeConcern Acceptance]: drop accepts valid writeConcern options.
DROP_WRITE_CONCERN_SUCCESS_TESTS: list[CommandTestCase] = [
CommandTestCase(
"w1",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": 1}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with w:1",
),
CommandTestCase(
"majority",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": "majority"}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with w:majority",
),
CommandTestCase(
"w0",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": 0}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with w:0",
),
CommandTestCase(
"wtimeout",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": 1, "wtimeout": 1000}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with wtimeout",
),
CommandTestCase(
"journal",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": 1, "j": True}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with j:true",
),
CommandTestCase(
"empty_object",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with empty writeConcern",
),
]

# Property [writeConcern Rejection]: drop rejects invalid writeConcern values.
DROP_WRITE_CONCERN_ERROR_TESTS: list[CommandTestCase] = [
CommandTestCase(
"non_object",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": "invalid"},
error_code=TYPE_MISMATCH_ERROR,
msg="Non-object writeConcern should fail with 14",
),
CommandTestCase(
"negative_w",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "writeConcern": {"w": -1}},
error_code=FAILED_TO_PARSE_ERROR,
msg="w:-1 should fail with error code 9",
),
]

# Property [comment Acceptance]: drop accepts comment of any BSON type.
DROP_COMMENT_TESTS: list[CommandTestCase] = [
CommandTestCase(
"string",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "comment": "dropping collection"},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with string comment",
),
CommandTestCase(
"integer",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "comment": 42},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with integer comment",
),
CommandTestCase(
"object",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "comment": {"reason": "cleanup"}},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with object comment",
),
CommandTestCase(
"array",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "comment": [1, 2, 3]},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with array comment",
),
CommandTestCase(
"boolean",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "comment": True},
expected=lambda ctx: {"nIndexesWas": 1, "ns": ctx.namespace, "ok": 1.0},
msg="Should succeed with boolean comment",
),
]

# Property [Unrecognized Field Rejection]: drop rejects unrecognized fields.
DROP_UNRECOGNIZED_FIELD_TESTS: list[CommandTestCase] = [
CommandTestCase(
"unknown_field",
docs=[{"_id": 1}],
command=lambda ctx: {"drop": ctx.collection, "unknownField": 1},
error_code=UNRECOGNIZED_COMMAND_FIELD_ERROR,
msg="Unrecognized field should fail with 40415",
),
]

DROP_OPTIONS_TESTS: list[CommandTestCase] = (
DROP_WRITE_CONCERN_SUCCESS_TESTS
+ DROP_WRITE_CONCERN_ERROR_TESTS
+ DROP_COMMENT_TESTS
+ DROP_UNRECOGNIZED_FIELD_TESTS
)


@pytest.mark.collection_mgmt
@pytest.mark.parametrize("test", pytest_params(DROP_OPTIONS_TESTS))
def test_drop_options(database_client, collection, test):
"""Test drop command option acceptance and rejection."""
collection = test.prepare(database_client, collection)
ctx = CommandContext.from_collection(collection)
result = execute_command(collection, test.build_command(ctx))
assertResult(
result,
expected=test.build_expected(ctx),
error_code=test.error_code,
msg=test.msg,
raw_res=True,
)
Loading
Loading