From e55e734b1e145af9bbf1a90bfed31c21efd788e3 Mon Sep 17 00:00:00 2001 From: Simon Moreno <30335873+simorenoh@users.noreply.github.com> Date: Wed, 5 Aug 2026 13:53:52 -0400 Subject: [PATCH 1/7] [cosmos] Namespace live-test databases to the run that owns them The Cosmos live tests are moving off per-run provisioned accounts and onto fixed, self-owned accounts that are shared with other language SDKs and with concurrent runs of this suite. Databases are the only account-scoped namespace the tests control, so every database created against a live account now carries a prefix identifying the run that created it. Adds RESOURCE_PREFIX / RUN_ID / unique_database_id() to test_config.py. The run id combines Build.BuildId with a random suffix: the build id groups every matrix leg of a single pipeline run, which is what an out-of-band cleanup pass matches on, while the suffix keeps parallel legs distinct. Two call sites embed the generated id rather than using it verbatim so their assertions still mean something: test_crud_database keeps a literal leading space for the "id can begin with space" case, and test_resource_id keeps its unicode and special-character payload. Also fixes a latent bug in the create_database_if_not_exists negative tests, which used a hardcoded "responses_test" id. Both calls now share one run-scoped id, so the second call is guaranteed to be the one exercising the already-exists path; previously a leftover database from any earlier run made the first call take that path too, and the test silently stopped testing what it claimed. Left alone deliberately: create_database_if_not_exists("test", ...) in test_crud*.py runs through TimeoutTransport with passthrough disabled and never reaches the service, test_proxy's database is emulator-only, and the id_with_illegal* cases are negative tests where creation is expected to fail. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cb8202b3-2717-4b4a-92af-0a0a4cb223f3 --- .../azure-cosmos/tests/test_auto_scale.py | 6 ++-- .../tests/test_auto_scale_async.py | 6 ++-- .../tests/test_backwards_compatibility.py | 8 ++--- .../test_backwards_compatibility_async.py | 8 ++--- sdk/cosmos/azure-cosmos/tests/test_config.py | 35 ++++++++++++++++++- .../tests/test_cosmos_http_logging_policy.py | 10 +++--- .../test_cosmos_http_logging_policy_async.py | 10 +++--- .../tests/test_cosmos_responses.py | 18 ++++++---- .../tests/test_cosmos_responses_async.py | 18 ++++++---- .../azure-cosmos/tests/test_crud_database.py | 11 +++--- .../tests/test_crud_database_async.py | 9 +++-- ...crud_response_payload_on_write_disabled.py | 10 +++--- ...esponse_payload_on_write_disabled_async.py | 8 ++--- .../tests/test_full_text_policy.py | 2 +- .../tests/test_full_text_policy_async.py | 2 +- .../tests/test_global_secondary_index_live.py | 2 +- .../tests/test_query_hybrid_search.py | 2 +- .../tests/test_query_hybrid_search_async.py | 2 +- .../tests/test_query_vector_similarity.py | 2 +- .../test_query_vector_similarity_async.py | 2 +- .../azure-cosmos/tests/test_resource_id.py | 10 +++--- .../tests/test_resource_id_async.py | 10 +++--- .../tests/test_streaming_failover.py | 2 +- sdk/cosmos/azure-cosmos/tests/test_utils.py | 3 +- .../azure-cosmos/tests/test_vector_policy.py | 2 +- .../tests/test_vector_policy_async.py | 2 +- 26 files changed, 121 insertions(+), 79 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/tests/test_auto_scale.py b/sdk/cosmos/azure-cosmos/tests/test_auto_scale.py index 634dd8c6b52b..4699372ca8b3 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_auto_scale.py +++ b/sdk/cosmos/azure-cosmos/tests/test_auto_scale.py @@ -72,7 +72,7 @@ def test_autoscale_create_container(self): self.created_database.delete_container(container_id) def test_autoscale_create_database(self): - database_id = "db_auto_scale_" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("auto-scale") try: # Testing auto_scale_settings for the create_database method created_database = self.key_client.create_database(database_id, offer_throughput=ThroughputProperties( @@ -87,7 +87,7 @@ def test_autoscale_create_database(self): self.key_client.delete_database(created_database.id) # Testing auto_scale_settings for the create_database_if_not_exists method - database_id = "db_auto_scale_2_" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("auto-scale-2") created_database = self.key_client.create_database_if_not_exists(database_id, offer_throughput=ThroughputProperties( auto_scale_max_throughput=9000, @@ -101,7 +101,7 @@ def test_autoscale_create_database(self): self.key_client.delete_database(database_id) def test_autoscale_replace_throughput(self): - database_id = "replace_db" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("replace-db") container_id = None try: created_database = self.key_client.create_database(database_id, offer_throughput=ThroughputProperties( diff --git a/sdk/cosmos/azure-cosmos/tests/test_auto_scale_async.py b/sdk/cosmos/azure-cosmos/tests/test_auto_scale_async.py index 7fa9c36f6163..43b0c26fb658 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_auto_scale_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_auto_scale_async.py @@ -82,7 +82,7 @@ async def test_autoscale_create_database_async(self): database_id = None try: # Testing auto_scale_settings for the create_database method - database_id = "db1_" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("db1") created_database = await self.key_client.create_database(database_id, offer_throughput=ThroughputProperties( auto_scale_max_throughput=5000, auto_scale_increment_percent=0)) @@ -95,7 +95,7 @@ async def test_autoscale_create_database_async(self): await self.key_client.delete_database(created_database.id) # Testing auto_scale_settings for the create_database_if_not_exists method - database_id = "db2_" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("db2") created_database = await self.key_client.create_database_if_not_exists(database_id, offer_throughput=ThroughputProperties( auto_scale_max_throughput=9000, auto_scale_increment_percent=11)) @@ -108,7 +108,7 @@ async def test_autoscale_create_database_async(self): await self.key_client.delete_database(database_id) async def test_replace_throughput_async(self): - database_id = "replace_db" + str(uuid.uuid4()) + database_id = test_config.unique_database_id("replace-db") container_id = None try: created_database = await self.key_client.create_database(database_id, offer_throughput=ThroughputProperties( diff --git a/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility.py b/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility.py index 4f4b2e9a1bfe..19a664d40505 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility.py +++ b/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility.py @@ -64,9 +64,9 @@ def test_populate_partition_key_range_statistics(self): def test_session_token_compatibility(self): # Verifying that behavior is unaffected across the board for using `session_token` on irrelevant methods # Database - database = self.client.create_database(str(uuid.uuid4()), session_token=str(uuid.uuid4())) + database = self.client.create_database(test_config.unique_database_id("backcompat"), session_token=str(uuid.uuid4())) assert database is not None - database2 = self.client.create_database_if_not_exists(str(uuid.uuid4()), session_token=str(uuid.uuid4())) + database2 = self.client.create_database_if_not_exists(test_config.unique_database_id("backcompat"), session_token=str(uuid.uuid4())) assert database2 is not None database_list = list(self.client.list_databases(session_token=str(uuid.uuid4()))) database_list2 = list(self.client.query_databases(query="select * from c", session_token=str(uuid.uuid4()))) @@ -109,9 +109,9 @@ def test_session_token_compatibility(self): def test_etag_match_condition_compatibility(self): # Verifying that behavior is unaffected across the board for using `etag`/`match_condition` on irrelevant methods # Database - database = self.client.create_database(str(uuid.uuid4()), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) + database = self.client.create_database(test_config.unique_database_id("backcompat"), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) assert database is not None - database2 = self.client.create_database_if_not_exists(str(uuid.uuid4()), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfNotModified) + database2 = self.client.create_database_if_not_exists(test_config.unique_database_id("backcompat"), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfNotModified) assert database2 is not None self.client.delete_database(database2.id, etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) try: diff --git a/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility_async.py b/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility_async.py index d9dcfd988cec..bcd391be9e0d 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_backwards_compatibility_async.py @@ -47,9 +47,9 @@ async def asyncTearDown(self): async def test_session_token_compatibility_async(self): # Verifying that behavior is unaffected across the board for using `session_token` on irrelevant methods # Database - database = await self.client.create_database(str(uuid.uuid4()), session_token=str(uuid.uuid4())) + database = await self.client.create_database(test_config.unique_database_id("backcompat"), session_token=str(uuid.uuid4())) assert database is not None - database2 = await self.client.create_database_if_not_exists(str(uuid.uuid4()), session_token=str(uuid.uuid4())) + database2 = await self.client.create_database_if_not_exists(test_config.unique_database_id("backcompat"), session_token=str(uuid.uuid4())) assert database2 is not None database_list = [db async for db in self.client.list_databases(session_token=str(uuid.uuid4()))] database_list2 = [db async for db in self.client.query_databases(query="select * from c", session_token=str(uuid.uuid4()))] @@ -93,9 +93,9 @@ async def test_session_token_compatibility_async(self): async def test_etag_match_condition_compatibility_async(self): # Verifying that behavior is unaffected across the board for using `etag`/`match_condition` on irrelevant methods # Database - database = await self.client.create_database(str(uuid.uuid4()), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) + database = await self.client.create_database(test_config.unique_database_id("backcompat"), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) assert database is not None - database2 = await self.client.create_database_if_not_exists(str(uuid.uuid4()), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfNotModified) + database2 = await self.client.create_database_if_not_exists(test_config.unique_database_id("backcompat"), etag=str(uuid.uuid4()), match_condition=MatchConditions.IfNotModified) assert database2 is not None await self.client.delete_database(database2.id, etag=str(uuid.uuid4()), match_condition=MatchConditions.IfModified) try: diff --git a/sdk/cosmos/azure-cosmos/tests/test_config.py b/sdk/cosmos/azure-cosmos/tests/test_config.py index 5b5e9fd061e5..a75d6120a33e 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_config.py +++ b/sdk/cosmos/azure-cosmos/tests/test_config.py @@ -36,6 +36,39 @@ SPLIT_TIMEOUT = 60*10 # timeout test at 10 minutes SLEEP_TIME = 30 # sleep for 30 seconds +# The live tests run against fixed, long-lived accounts that are shared with other +# language SDKs and with concurrent runs of this suite. Databases are the only +# account-scoped namespace we control, so every database this suite creates carries a +# prefix identifying the run that owns it. That keeps concurrent runs from colliding and +# lets cleanup delete only what a given run created. +RESOURCE_PREFIX = "PythonSDKTest" + + +def _build_run_id(): + # Build.BuildId is shared by every matrix leg of one pipeline run, which is what an + # out-of-band janitor matches on; the random suffix keeps parallel legs distinct. + build_id = os.getenv('BUILD_BUILDID') + suffix = uuid.uuid4().hex[:8] + return "{}-{}".format(build_id, suffix) if build_id else suffix + + +RUN_ID = _build_run_id() + + +def unique_database_id(label=""): + """Build a database id owned by this test run. + + Format: ``PythonSDKTest--