import pytest import requests from .fixtures import create_collection, drop_collection, upsert_random_points from .utils import kill_all_processes, start_cluster COLL_NAME = "test_collection" @pytest.fixture(scope="module") def setup(tmp_path_factory: pytest.TempPathFactory): extra_env = { "QDRANT__SERVICE__SLOW_QUERY_SECS": "0.001", # "Always" try to trigger slow search issue } tmp_path = tmp_path_factory.mktemp("qdrant") peer_api_uris, _peer_dirs, _bootstrap_uri = start_cluster( tmp_path=tmp_path, num_peers=1, extra_env=extra_env ) uri = peer_api_uris[0] yield uri kill_all_processes() @pytest.fixture def setup_with_big_collection(setup): uri = setup create_collection(uri, COLL_NAME) upsert_random_points(uri, 10000, collection_name=COLL_NAME, with_sparse_vector=False) yield uri drop_collection(uri, COLL_NAME) def get_issues(uri): response = requests.get( f"{uri}/issues", ) assert response.ok return response.json()["result"]["issues"] def search_with_city_filter(uri): response = requests.post( f"{uri}/collections/{COLL_NAME}/points/search", json={ "vector": [0.2, 0.1, 0.9, 0.7], "limit": 1000, "filter": {"must": [{"key": "city", "match": {"any": ["London", "Moscow"]}}]}, }, ) assert response.ok, response.json() def test_unindexed_field_is_gone_when_deleting_collection(setup_with_big_collection): uri = setup_with_big_collection expected_issue_code = "UNINDEXED_FIELD/test_collection/city" issues = get_issues(uri) assert expected_issue_code not in [issue["code"] for issue in issues] search_with_city_filter(uri) issues = get_issues(uri) # check the issue is now active assert expected_issue_code in [issue["id"] for issue in issues] # delete collection drop_collection(uri, COLL_NAME) # check the issue is not active anymore issues = get_issues(uri) assert expected_issue_code not in [issue["id"] for issue in issues] def test_unindexed_field_is_gone_when_indexing(setup_with_big_collection): uri = setup_with_big_collection expected_issue_code = "UNINDEXED_FIELD/test_collection/city" issues = get_issues(uri) assert expected_issue_code not in [issue["id"] for issue in issues] search_with_city_filter(uri) issues = get_issues(uri) # check the issue is now active issue_present = False solution = None timestamp = None for issue in issues: if issue["id"] == expected_issue_code: issue_present = True solution = issue["solution"]["immediate"]["action"] timestamp = issue["timestamp"] break assert issue_present assert solution is not None assert timestamp is not None # search again search_with_city_filter(uri) issues = get_issues(uri) # check the timestamp has not changed issue_present = False for issue in issues: if issue["id"] == expected_issue_code: issue_present = True assert timestamp == issue["timestamp"] break assert issue_present assert solution is not None assert timestamp is not None assert solution == { "method": "PUT", "uri": f"/collections/{COLL_NAME}/index", "body": {"field_name": "city", "field_schema": "keyword"}, "headers": {"content-type": "application/json"}, } # use provided solution to create index response = requests.request( method=solution["method"], url=uri + solution["uri"], params={"wait": "true"}, json=solution["body"], ) assert response.ok # check the issue is not active anymore issues = get_issues(uri) assert expected_issue_code not in [issue["id"] for issue in issues] # search again search_with_city_filter(uri) # check the issue is not triggered again issues = get_issues(uri) assert expected_issue_code not in [issue["id"] for issue in issues]