-
Notifications
You must be signed in to change notification settings - Fork 12
Added index type tests for single #253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| """Tests for single field index key sort order BSON type validation. | ||
|
|
||
| Verifies that single field index key values (sort order specifiers) reject | ||
| invalid BSON types and accept valid numeric types. | ||
| """ | ||
|
|
||
| import pytest | ||
| from bson import Decimal128, Int64 | ||
|
|
||
| from documentdb_tests.framework.assertions import assertFailureCode, assertNotError | ||
| from documentdb_tests.framework.bson_type_validator import ( | ||
| BsonType, | ||
| BsonTypeTestCase, | ||
| generate_bson_acceptance_test_cases, | ||
| generate_bson_rejection_test_cases, | ||
| ) | ||
| from documentdb_tests.framework.error_codes import CANNOT_CREATE_INDEX_ERROR | ||
| from documentdb_tests.framework.executor import execute_command | ||
|
|
||
| pytestmark = pytest.mark.index | ||
|
|
||
| SINGLE_KEY_SORT_ORDER_PARAMS = [ | ||
| BsonTypeTestCase( | ||
| id="sort_order", | ||
| msg="single key sort order should reject non-numeric types", | ||
| keyword="sort_order", | ||
| valid_types=[BsonType.DOUBLE, BsonType.INT, BsonType.LONG, BsonType.DECIMAL], | ||
| default_error_code=CANNOT_CREATE_INDEX_ERROR, | ||
| valid_inputs={ | ||
| BsonType.DOUBLE: 1.0, | ||
| BsonType.INT: 1, | ||
| BsonType.LONG: Int64(1), | ||
| BsonType.DECIMAL: Decimal128("1"), | ||
| }, | ||
| ), | ||
| ] | ||
|
|
||
|
|
||
| REJECTION_CASES = generate_bson_rejection_test_cases(SINGLE_KEY_SORT_ORDER_PARAMS) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("bson_type,sample_value,spec", REJECTION_CASES) | ||
| def test_single_key_sort_order_rejected(collection, bson_type, sample_value, spec): | ||
| """Test single field index creation rejects invalid BSON types for key sort order.""" | ||
| result = execute_command( | ||
| collection, | ||
| { | ||
| "createIndexes": collection.name, | ||
| "indexes": [{"key": {"a": sample_value}, "name": "test_idx"}], | ||
| }, | ||
| ) | ||
| assertFailureCode(result, spec.expected_code(bson_type), msg=spec.msg) | ||
|
|
||
|
|
||
| ACCEPTANCE_CASES = generate_bson_acceptance_test_cases(SINGLE_KEY_SORT_ORDER_PARAMS) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("bson_type,sample_value,spec", ACCEPTANCE_CASES) | ||
| def test_single_key_sort_order_accepted(collection, bson_type, sample_value, spec): | ||
| """Test single field index creation accepts valid BSON types for key sort order. | ||
|
|
||
| Note: This is a type validation test, not a functional test. We only verify | ||
| the command does not error — we do not check listIndexes to confirm the index | ||
| was created with the correct option value. | ||
| """ | ||
| result = execute_command( | ||
| collection, | ||
| { | ||
| "createIndexes": collection.name, | ||
| "indexes": [{"key": {"a": sample_value}, "name": "test_idx"}], | ||
| }, | ||
| ) | ||
| assertNotError(result, msg=f"sort order should accept {bson_type.value}") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| """Tests for single field index creation. | ||
|
|
||
| Validates valid argument handling, idempotency, and duplicate prevention. | ||
| """ | ||
|
|
||
| import pytest | ||
|
|
||
| from documentdb_tests.compatibility.tests.core.indexes.commands.utils.index_test_case import ( | ||
| IndexTestCase, | ||
| index_created_response, | ||
| ) | ||
| from documentdb_tests.framework.assertions import assertSuccessPartial | ||
| from documentdb_tests.framework.executor import execute_command | ||
| from documentdb_tests.framework.parametrize import pytest_params | ||
|
|
||
| pytestmark = pytest.mark.index | ||
|
|
||
| CREATION_SUCCESS_TESTS: list[IndexTestCase] = [ | ||
| IndexTestCase( | ||
| id="creation_ascending", | ||
| indexes=({"key": {"a": 1}, "name": "a_1"},), | ||
| msg="Ascending order succeeds", | ||
| ), | ||
| IndexTestCase( | ||
| id="creation_descending", | ||
| indexes=({"key": {"a": -1}, "name": "a_neg1"},), | ||
| msg="Descending order succeeds", | ||
| ), | ||
| IndexTestCase( | ||
| id="creation_dot_notation", | ||
| indexes=({"key": {"a.b": 1}, "name": "a.b_1"},), | ||
| msg="Dot notation field succeeds", | ||
| ), | ||
| ] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing: multiple fields in a single createIndexes call. |
||
|
|
||
|
|
||
| @pytest.mark.parametrize("test", pytest_params(CREATION_SUCCESS_TESTS)) | ||
| def test_single_creation_success(collection, test): | ||
| """Test single field index creation with valid arguments.""" | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": list(test.indexes)}, | ||
| ) | ||
| assertSuccessPartial(result, index_created_response(), test.msg) | ||
|
|
||
|
|
||
| def test_single_creation_on_nonexistent_collection(collection): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the same as above |
||
| """Test createIndexes on non-existent collection creates collection and index.""" | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"x": 1}, "name": "x_1"}]}, | ||
| ) | ||
| assertSuccessPartial( | ||
| result, | ||
| {"ok": 1.0, "numIndexesBefore": 1, "numIndexesAfter": 2}, | ||
| msg="Should create collection and index", | ||
| ) | ||
|
|
||
|
|
||
| def test_single_creation_idempotent(collection): | ||
| """Test creating same index twice is idempotent.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| assertSuccessPartial( | ||
| result, | ||
| {"ok": 1.0, "numIndexesBefore": 2, "numIndexesAfter": 2}, | ||
| msg="Duplicate index creation should be no-op", | ||
| ) | ||
|
|
||
|
|
||
| def test_single_creation_different_sort_creates_two(collection): | ||
| """Test creating index with same field but different sort order creates two indexes.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": -1}, "name": "a_neg1"}]}, | ||
| ) | ||
| assertSuccessPartial( | ||
| result, | ||
| {"ok": 1.0, "numIndexesBefore": 2, "numIndexesAfter": 3}, | ||
| msg="Different sort order should create separate index", | ||
| ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing: dropIndexes after creation. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| """Tests for single field index error cases. | ||
|
|
||
| Validates invalid sort values, field name errors, and index conflicts. | ||
| """ | ||
|
|
||
| import pytest | ||
|
|
||
| from documentdb_tests.compatibility.tests.core.indexes.commands.utils.index_test_case import ( | ||
| IndexTestCase, | ||
| ) | ||
| from documentdb_tests.framework.assertions import assertFailureCode | ||
| from documentdb_tests.framework.error_codes import ( | ||
| CANNOT_CREATE_INDEX_ERROR, | ||
| INDEX_KEY_SPECS_CONFLICT_ERROR, | ||
| INDEX_OPTIONS_CONFLICT_ERROR, | ||
| ) | ||
| from documentdb_tests.framework.executor import execute_command | ||
| from documentdb_tests.framework.parametrize import pytest_params | ||
|
|
||
| pytestmark = pytest.mark.index | ||
|
|
||
| CREATION_ERROR_TESTS: list[IndexTestCase] = [ | ||
| IndexTestCase( | ||
| id="invalid_sort_zero", | ||
| indexes=({"key": {"a": 0}, "name": "a_0"},), | ||
| error_code=CANNOT_CREATE_INDEX_ERROR, | ||
| msg="Sort order 0 should fail", | ||
| ), | ||
| IndexTestCase( | ||
| id="invalid_dollar_prefix", | ||
| indexes=({"key": {"$field": 1}, "name": "dollar_1"},), | ||
| error_code=CANNOT_CREATE_INDEX_ERROR, | ||
| msg="$ prefix field should fail", | ||
| ), | ||
| IndexTestCase( | ||
| id="invalid_empty_field", | ||
| indexes=({"key": {"": 1}, "name": "empty_1"},), | ||
| error_code=CANNOT_CREATE_INDEX_ERROR, | ||
| msg="Empty field name should fail", | ||
| ), | ||
| ] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("test", pytest_params(CREATION_ERROR_TESTS)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing: empty key {}. |
||
| def test_single_creation_error(collection, test): | ||
| """Test single field index creation with invalid arguments.""" | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": list(test.indexes)}, | ||
| ) | ||
| assertFailureCode(result, test.error_code, test.msg) | ||
|
|
||
|
|
||
| CONFLICT_ERROR_TESTS: list[IndexTestCase] = [ | ||
| IndexTestCase( | ||
| id="conflict_same_field_different_name", | ||
| setup_indexes=[{"key": {"a": 1}, "name": "a_1"}], | ||
| indexes=({"key": {"a": 1}, "name": "a_different"},), | ||
| error_code=INDEX_OPTIONS_CONFLICT_ERROR, | ||
| msg="Same field/order with different name should fail", | ||
| ), | ||
| IndexTestCase( | ||
| id="conflict_same_name_different_field", | ||
| setup_indexes=[{"key": {"a": 1}, "name": "my_idx"}], | ||
| indexes=({"key": {"b": 1}, "name": "my_idx"},), | ||
| error_code=INDEX_KEY_SPECS_CONFLICT_ERROR, | ||
| msg="Same name with different field should fail", | ||
| ), | ||
| ] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("test", pytest_params(CONFLICT_ERROR_TESTS)) | ||
| def test_single_conflict_error(collection, test): | ||
| """Test single field index creation conflicts.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": list(test.setup_indexes)}, | ||
| ) | ||
| result = execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": list(test.indexes)}, | ||
| ) | ||
| assertFailureCode(result, test.error_code, test.msg) | ||
|
|
||
|
|
||
| def test_single_option_conflict_same_key_name(collection): | ||
| """Test recreating index with same key+name but different options fails.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| result = execute_command( | ||
| collection, | ||
| { | ||
| "createIndexes": collection.name, | ||
| "indexes": [{"key": {"a": 1}, "name": "a_1", "unique": True}], | ||
| }, | ||
| ) | ||
| assertFailureCode( | ||
| result, | ||
| INDEX_KEY_SPECS_CONFLICT_ERROR, | ||
| msg="Same key+name with different options should fail", | ||
| ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where are partial index , sparse and hidden properties tested for index creation success and failure. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| """Tests for single field index properties. | ||
|
|
||
| Validates NaN and Infinity handling on single field indexes. | ||
| """ | ||
|
|
||
| import pytest | ||
|
|
||
| from documentdb_tests.framework.assertions import ( | ||
| assertSuccess, | ||
| assertSuccessNaN, | ||
| ) | ||
| from documentdb_tests.framework.executor import execute_command | ||
|
|
||
| pytestmark = pytest.mark.index | ||
|
|
||
|
|
||
| def test_single_nan_indexed_and_queryable(collection): | ||
| """Test NaN in indexed field is queryable.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| collection.insert_one({"_id": 1, "a": float("nan")}) | ||
| result = execute_command(collection, {"find": collection.name, "filter": {"a": float("nan")}}) | ||
| assertSuccessNaN(result, [{"_id": 1, "a": float("nan")}], msg="Should find NaN document") | ||
|
|
||
|
|
||
| def test_single_infinity_indexed(collection): | ||
| """Test Infinity in indexed field is queryable.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| collection.insert_one({"_id": 1, "a": float("inf")}) | ||
| result = execute_command(collection, {"find": collection.name, "filter": {"a": float("inf")}}) | ||
| assertSuccess(result, [{"_id": 1, "a": float("inf")}], msg="Should find Infinity document") | ||
|
|
||
|
|
||
| def test_single_negative_infinity_indexed(collection): | ||
| """Test -Infinity in indexed field is queryable.""" | ||
| execute_command( | ||
| collection, | ||
| {"createIndexes": collection.name, "indexes": [{"key": {"a": 1}, "name": "a_1"}]}, | ||
| ) | ||
| collection.insert_one({"_id": 1, "a": float("-inf")}) | ||
| result = execute_command(collection, {"find": collection.name, "filter": {"a": float("-inf")}}) | ||
| assertSuccess(result, [{"_id": 1, "a": float("-inf")}], msg="Should find -Infinity document") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is INT(1) would fail