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
31 changes: 30 additions & 1 deletion test/asynchronous/test_index_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import asyncio
import os
import pathlib
import sys
import time
import uuid
Expand All @@ -27,6 +26,8 @@

import pytest

from test.asynchronous.utils import flaky

sys.path[0:0] = [""]

from pymongo.errors import OperationFailure
Expand Down Expand Up @@ -112,6 +113,18 @@ async def wait_for_ready(self, coll, name=_NAME, predicate=None):
return indices[0]
await asyncio.sleep(5)

async def drop_and_wait(self, coll, name):
"""Drop a search index and wait for it to be dropped."""
await coll.drop_search_index(name)
start = time.time()
while True:
indices = await (await coll.list_search_indexes(name)).to_list()
if not indices:
return
if (time.time() - start) / 60 > 5:
raise TimeoutError("Timed out waiting for index deletion")
await asyncio.sleep(5)


class TestSearchIndexIntegration(SearchIndexIntegrationBase):
db_name = "test_search_index"
Expand All @@ -138,12 +151,14 @@ async def test_comment_field(self):
class TestSearchIndexProse(SearchIndexIntegrationBase):
db_name = "test_search_index_prose"

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need reset_func for these?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, these all need to undo whatever successful parts of their execution ran between attempts.

async def test_case_1(self):
"""Driver can successfully create and list search indexes."""

# Create a new search index on ``self.coll0`` with the ``createSearchIndex`` helper. Use the following definition:
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = await self.coll0.create_search_index(model)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, _NAME)
Expand All @@ -156,6 +171,7 @@ async def test_case_1(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_2(self):
"""Driver can successfully create multiple indexes in batch."""

Expand All @@ -170,6 +186,8 @@ async def test_case_2(self):
await self.coll0.create_search_indexes(
[SearchIndexModel(i["definition"], i["name"]) for i in index_definitions]
)
for index in index_definitions:
self.addAsyncCleanup(self.drop_and_wait, self.coll0, index["name"])

# .Assert that the command returns an array containing the new indexes' names: ``["test-search-index-1", "test-search-index-2"]``.
indices = await (await self.coll0.list_search_indexes()).to_list()
Expand All @@ -188,12 +206,14 @@ async def test_case_2(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], definition)

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_3(self):
"""Driver can successfully drop search indexes."""

# Create a new search index on ``self.coll0``.
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = await self.coll0.create_search_index(model)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, "test-search-index")
Expand All @@ -215,12 +235,14 @@ async def test_case_3(self):
raise TimeoutError("Timed out waiting for index deletion")
await asyncio.sleep(5)

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_4(self):
"""Driver can update a search index."""

# Create a new search index on ``self.coll0``.
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = await self.coll0.create_search_index(model)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, _NAME)
Expand All @@ -245,6 +267,7 @@ async def test_case_4(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model2["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_5(self):
"""``dropSearchIndex`` suppresses namespace not found errors."""
# Create a driver-side collection object for a randomly generated collection name. Do not create this collection on the server.
Expand All @@ -253,6 +276,7 @@ async def test_case_5(self):
# Run a ``dropSearchIndex`` command and assert that no error is thrown.
await coll0.drop_search_index("foo")

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_6(self):
"""Driver can successfully create and list search indexes with non-default readConcern and writeConcern."""

Expand All @@ -265,6 +289,7 @@ async def test_case_6(self):
name = "test-search-index-case6"
model = {"name": name, "definition": {"mappings": {"dynamic": False}}}
resp = await coll0.create_search_index(model)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, name)

# Assert that the command returns the name of the index: ``"test-search-index-case6"``.
self.assertEqual(resp, name)
Expand All @@ -277,6 +302,7 @@ async def test_case_6(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
async def test_case_7(self):
"""Driver handles index types."""

Expand All @@ -297,6 +323,7 @@ async def test_case_7(self):
implicit_search_resp = await self.coll0.create_search_index(
model={"name": _NAME + "-implicit", "definition": search_definition}
)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME + "-implicit")

# Get the index definition.
resp = await (await self.coll0.list_search_indexes(name=implicit_search_resp)).next()
Expand All @@ -308,6 +335,7 @@ async def test_case_7(self):
explicit_search_resp = await self.coll0.create_search_index(
model={"name": _NAME + "-explicit", "type": "search", "definition": search_definition}
)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME + "-explicit")

# Get the index definition.
resp = await (await self.coll0.list_search_indexes(name=explicit_search_resp)).next()
Expand All @@ -323,6 +351,7 @@ async def test_case_7(self):
"definition": vector_search_definition,
}
)
self.addAsyncCleanup(self.drop_and_wait, self.coll0, _NAME + "-vector")

# Get the index definition.
resp = await (await self.coll0.list_search_indexes(name=explicit_vector_resp)).next()
Expand Down
31 changes: 30 additions & 1 deletion test/test_index_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import asyncio
import os
import pathlib
import sys
import time
import uuid
Expand All @@ -27,6 +26,8 @@

import pytest

from test.utils import flaky

sys.path[0:0] = [""]

from pymongo.errors import OperationFailure
Expand Down Expand Up @@ -112,6 +113,18 @@ def wait_for_ready(self, coll, name=_NAME, predicate=None):
return indices[0]
time.sleep(5)

def drop_and_wait(self, coll, name):
"""Drop a search index and wait for it to be dropped."""
coll.drop_search_index(name)
start = time.time()
while True:
indices = (coll.list_search_indexes(name)).to_list()
if not indices:
return
if (time.time() - start) / 60 > 5:
raise TimeoutError("Timed out waiting for index deletion")
time.sleep(5)


class TestSearchIndexIntegration(SearchIndexIntegrationBase):
db_name = "test_search_index"
Expand All @@ -136,12 +149,14 @@ def test_comment_field(self):
class TestSearchIndexProse(SearchIndexIntegrationBase):
db_name = "test_search_index_prose"

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_1(self):
"""Driver can successfully create and list search indexes."""

# Create a new search index on ``self.coll0`` with the ``createSearchIndex`` helper. Use the following definition:
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = self.coll0.create_search_index(model)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, _NAME)
Expand All @@ -154,6 +169,7 @@ def test_case_1(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_2(self):
"""Driver can successfully create multiple indexes in batch."""

Expand All @@ -168,6 +184,8 @@ def test_case_2(self):
self.coll0.create_search_indexes(
[SearchIndexModel(i["definition"], i["name"]) for i in index_definitions]
)
for index in index_definitions:
self.addCleanup(self.drop_and_wait, self.coll0, index["name"])

# .Assert that the command returns an array containing the new indexes' names: ``["test-search-index-1", "test-search-index-2"]``.
indices = (self.coll0.list_search_indexes()).to_list()
Expand All @@ -186,12 +204,14 @@ def test_case_2(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], definition)

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_3(self):
"""Driver can successfully drop search indexes."""

# Create a new search index on ``self.coll0``.
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = self.coll0.create_search_index(model)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, "test-search-index")
Expand All @@ -213,12 +233,14 @@ def test_case_3(self):
raise TimeoutError("Timed out waiting for index deletion")
time.sleep(5)

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_4(self):
"""Driver can update a search index."""

# Create a new search index on ``self.coll0``.
model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}}
resp = self.coll0.create_search_index(model)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME)

# Assert that the command returns the name of the index: ``"test-search-index"``.
self.assertEqual(resp, _NAME)
Expand All @@ -243,6 +265,7 @@ def test_case_4(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model2["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_5(self):
"""``dropSearchIndex`` suppresses namespace not found errors."""
# Create a driver-side collection object for a randomly generated collection name. Do not create this collection on the server.
Expand All @@ -251,6 +274,7 @@ def test_case_5(self):
# Run a ``dropSearchIndex`` command and assert that no error is thrown.
coll0.drop_search_index("foo")

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_6(self):
"""Driver can successfully create and list search indexes with non-default readConcern and writeConcern."""

Expand All @@ -263,6 +287,7 @@ def test_case_6(self):
name = "test-search-index-case6"
model = {"name": name, "definition": {"mappings": {"dynamic": False}}}
resp = coll0.create_search_index(model)
self.addCleanup(self.drop_and_wait, self.coll0, name)

# Assert that the command returns the name of the index: ``"test-search-index-case6"``.
self.assertEqual(resp, name)
Expand All @@ -275,6 +300,7 @@ def test_case_6(self):
self.assertIn("latestDefinition", index)
self.assertEqual(index["latestDefinition"], model["definition"])

@flaky(reason="PYTHON-6056", affects_cpython_linux=True)
def test_case_7(self):
"""Driver handles index types."""

Expand All @@ -295,6 +321,7 @@ def test_case_7(self):
implicit_search_resp = self.coll0.create_search_index(
model={"name": _NAME + "-implicit", "definition": search_definition}
)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME + "-implicit")

# Get the index definition.
resp = (self.coll0.list_search_indexes(name=implicit_search_resp)).next()
Expand All @@ -306,6 +333,7 @@ def test_case_7(self):
explicit_search_resp = self.coll0.create_search_index(
model={"name": _NAME + "-explicit", "type": "search", "definition": search_definition}
)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME + "-explicit")

# Get the index definition.
resp = (self.coll0.list_search_indexes(name=explicit_search_resp)).next()
Expand All @@ -321,6 +349,7 @@ def test_case_7(self):
"definition": vector_search_definition,
}
)
self.addCleanup(self.drop_and_wait, self.coll0, _NAME + "-vector")

# Get the index definition.
resp = (self.coll0.list_search_indexes(name=explicit_vector_resp)).next()
Expand Down
Loading