From c232f8bf66fc52da97f5ffb52279c969c5b038db Mon Sep 17 00:00:00 2001 From: binbin <83755740+binbinlv@users.noreply.github.com> Date: Fri, 18 Jun 2021 19:12:09 +0800 Subject: [PATCH] Update test case after code merge (#5868) * Update Mergify Signed-off-by: Xiangyu Wang * Update test case for interface change (#5794) Signed-off-by: Binbin Lv * [skip ci] update readme (#5811) Signed-off-by: LocoRichard * Update test case after code merge Signed-off-by: Binbin Lv * Remove unused argument Signed-off-by: Binbin Lv * Correct code annotation Signed-off-by: Binbin Lv * Fix test bug Signed-off-by: Binbin Lv Co-authored-by: Xiangyu Wang Co-authored-by: LocoRichard --- tests20/python_client/base/client_base.py | 11 ++- .../python_client/base/collection_wrapper.py | 4 +- tests20/python_client/check/func_check.py | 1 + tests20/python_client/common/common_func.py | 6 +- .../python_client/testcases/test_search.py | 91 +++++++++++++++++-- 5 files changed, 98 insertions(+), 15 deletions(-) diff --git a/tests20/python_client/base/client_base.py b/tests20/python_client/base/client_base.py index 939339803d..4a8c286d02 100644 --- a/tests20/python_client/base/client_base.py +++ b/tests20/python_client/base/client_base.py @@ -122,13 +122,13 @@ class TestcaseBase(Base): log.info("_connect: Connected") return res - def init_collection_wrap(self, name=None, data=None, schema=None, check_task=None, **kwargs): + def init_collection_wrap(self, name=None, schema=None, check_task=None, **kwargs): name = cf.gen_unique_str('coll_') if name is None else name schema = cf.gen_default_collection_schema() if schema is None else schema if self.connection_wrap.get_connection(alias='default')[0] is None: self._connect() collection_w = ApiCollectionWrapper() - collection_w.init_collection(name=name, data=data, schema=schema, + collection_w.init_collection(name=name, schema=schema, check_task=check_task, **kwargs) return collection_w @@ -153,7 +153,7 @@ class TestcaseBase(Base): expected: return collection and raw data """ log.info("Test case of search interface: initialize before test case") - self._connect() + conn = self._connect() collection_name = cf.gen_unique_str(prefix) vectors = [] binary_raw_vectors = [] @@ -171,5 +171,10 @@ class TestcaseBase(Base): # 3 insert data if specified if insert_data: collection_w, vectors, binary_raw_vectors = cf.insert_data(collection_w, nb, is_binary) + if nb <= 32000: + conn.flush([collection_w.name]) + assert collection_w.is_empty == False + assert collection_w.num_entities == nb + collection_w.load() return collection_w, vectors, binary_raw_vectors diff --git a/tests20/python_client/base/collection_wrapper.py b/tests20/python_client/base/collection_wrapper.py index e02e6c39f1..fe974bf971 100644 --- a/tests20/python_client/base/collection_wrapper.py +++ b/tests20/python_client/base/collection_wrapper.py @@ -82,8 +82,8 @@ class ApiCollectionWrapper: partition_names=None, output_fields=None, timeout=None, check_task=None, check_items=None, **kwargs): func_name = sys._getframe().f_code.co_name - res, check = api_request([self.collection.search, data, anns_field, param, limit, expr, partition_names, - output_fields, timeout], **kwargs) + res, check = api_request([self.collection.search, data, anns_field, param, limit, + expr, partition_names, output_fields, timeout], **kwargs) check_result = ResponseChecker(res, func_name, check_task, check_items, check, data=data, anns_field=anns_field, param=param, limit=limit, expr=expr, partition_names=partition_names, diff --git a/tests20/python_client/check/func_check.py b/tests20/python_client/check/func_check.py index 5a5ee3a59c..86cd0479ef 100644 --- a/tests20/python_client/check/func_check.py +++ b/tests20/python_client/check/func_check.py @@ -168,3 +168,4 @@ class ResponseChecker: log.info("search_results_check: limit (topK) " "searched for each query is correct") log.info("search_results_check: search_results_check: checked the searching results") + return True diff --git a/tests20/python_client/common/common_func.py b/tests20/python_client/common/common_func.py index 075481d3a2..961447629c 100644 --- a/tests20/python_client/common/common_func.py +++ b/tests20/python_client/common/common_func.py @@ -180,6 +180,7 @@ def gen_all_type_fields(): def gen_normal_expressions(): expressions = [ + "", "int64 > 0", "(int64 > 0 && int64 < 400) or (int64 > 500 && int64 < 1000)", "int64 not in [1, 2, 3]", @@ -295,10 +296,7 @@ def insert_data(collection_w, nb=3000, is_binary=False): else: default_data = gen_default_dataframe_data(nb // num) collection_w.insert(default_data, par[i].name) - vectors.extend(default_data) + vectors.append(default_data) log.info("insert_data: inserted data into collection %s (num_entities: %s)" % (collection_w.name, nb)) - collection_w.load() - assert collection_w.is_empty == False - assert collection_w.num_entities == nb return collection_w, vectors, binary_raw_vectors diff --git a/tests20/python_client/testcases/test_search.py b/tests20/python_client/testcases/test_search.py index f85f8f73ad..0c36536f2b 100644 --- a/tests20/python_client/testcases/test_search.py +++ b/tests20/python_client/testcases/test_search.py @@ -83,6 +83,7 @@ class TestCollectionSearch(TestcaseBase): "err_msg": "collection %s doesn't exist!" % collection_w.name}) @pytest.mark.tags(CaseLabel.L3) + @pytest.mark.xfail(reason="issue 5838") def test_search_with_empty_collection(self): """ target: test search with empty connection @@ -92,14 +93,21 @@ class TestCollectionSearch(TestcaseBase): log.info("Test case of search interface: test_search_with_empty_collection") # 1 initialize without data collection_w = self.init_collection_general(prefix)[0] - # 2 search collection without data + # 2 search collection without data before load log.info("test_search_with_empty_collection: Searching empty collection %s" % collection_w.name) vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)] collection_w.search(vectors[:default_nq], default_search_field, default_search_params, - default_limit, default_search_exp, + default_limit, default_search_exp, timeout=1, check_task=CheckTasks.err_res, check_items={"err_code": 1, "err_msg": "collection hasn't been loaded or has been released"}) + # 3 search collection without data after load + collection_w.load() + collection_w.search(vectors[:default_nq], default_search_field, default_search_params, + default_limit, default_search_exp, + check_task=CheckTasks.check_search_results, + check_items={"nq": default_nq, + "limit": 0}) @pytest.mark.tags(CaseLabel.L3) def test_search_with_empty_vectors(self): @@ -128,13 +136,15 @@ class TestCollectionSearch(TestcaseBase): """ log.info("Test case of search interface: test_search_param_missing") # 1 initialize without data - collection_w = self.init_collection_general(prefix)[0] + collection_w = self.init_collection_general(prefix, True)[0] # 2 search collection with missing parameters - log.info("test_search_param_missing: Searching collection %s with missing parameters" % collection_w.name) + log.info("test_search_param_missing: Searching collection %s " + "with missing parameters" % collection_w.name) try: collection_w.search() except TypeError as e: - assert "missing" and "'data', 'anns_field', 'param', 'limit', and 'expression'" in str(e) + assert "missing 4 required positional arguments: 'data', " \ + "'anns_field', 'param', and 'limit'" in str(e) log.info("test_search_no_collection: test PASS with expected assertion: %s" % e) @pytest.mark.tags(CaseLabel.L3) @@ -344,6 +354,41 @@ class TestCollectionSearch(TestcaseBase): check_items={"nq": default_nq, "limit": limit-deleted_entity_num}) + @pytest.mark.tags(CaseLabel.L3) + @pytest.mark.xfail(reason="issue 5858") + def test_search_new_data(self): + """ + target: test search new inserted data without load + method: 1 search the collection + 2 insert new data + 3 search the collection without load again + expected: new data should be searched + """ + log.info("test_search_new_data: search new data without another load") + # 1. initialize with data + limit = 1000 + nb_old = 500 + collection_w = self.init_collection_general(prefix, True, nb_old)[0] + # 2. search for original data after load + vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)] + log.info("test_search_new_data: searching for original data after load") + collection_w.search(vectors[:default_nq], default_search_field, + default_search_params, limit, default_search_exp, + check_task=CheckTasks.check_search_results, + check_items={"nq": default_nq, + "limit": nb_old}) + # 3. insert new data + nb_new = 300 + cf.insert_data(collection_w, nb_new, False) + conn = self.connection_wrap.get_connection()[0] + conn.flush([collection_w.name]) + # 4. search for new data without load + collection_w.search(vectors[:default_nq], default_search_field, + default_search_params, limit, default_search_exp, + check_task=CheckTasks.check_search_results, + check_items={"nq": default_nq, + "limit": nb_old+nb_new}) + @pytest.mark.tags(CaseLabel.L3) def test_search_after_different_index(self): """ @@ -474,6 +519,40 @@ class TestCollectionSearch(TestcaseBase): "limit": limit}) @pytest.mark.tags(CaseLabel.L3) + def test_search_index_partitions_fuzzy(self): + """ + target: test search from partitions + method: search from partitions with fuzzy + partition name + expected: searched successfully + """ + log.info("Test case of search interface: test_search_index_partitions_fuzzy") + # 1. initialize with data + collection_w = self.init_collection_general(prefix, True, 1000, 1)[0] + vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)] + # 2. create index + default_index = {"index_type": "IVF_FLAT", "params": {"nlist": 128}, "metric_type": "L2"} + collection_w.create_index("float_vector", default_index) + # 3. search through partitions + log.info("test_search_index_partitions_fuzzy: searching through partitions") + par = collection_w.partitions + entity_num = par[1].num_entities + limit = 1000 + collection_w.search(vectors[:default_nq], default_search_field, + default_search_params, limit, default_search_exp, + ["(.*)"], + check_task=CheckTasks.check_search_results, + check_items={"nq": default_nq, + "limit": limit}) + collection_w.search(vectors[:default_nq], default_search_field, + default_search_params, limit, default_search_exp, + ["search(.*)"], + check_task=CheckTasks.check_search_results, + check_items={"nq": default_nq, + "limit": entity_num}) + + @pytest.mark.tags(CaseLabel.L3) + @pytest.mark.xfail(reason="issue 5852") def test_search_index_partition_empty(self): """ target: test search the empty partition @@ -657,7 +736,7 @@ class TestCollectionSearch(TestcaseBase): @pytest.mark.tags(CaseLabel.L3) @pytest.mark.parametrize("expression, limit", zip(cf.gen_normal_expressions(), - [999, 898, 997, 2, 3])) + [1000, 999, 898, 997, 2, 3])) def test_search_with_expression(self, expression, limit): """ target: test search with different expressions