diff --git a/tests/python_client/common/common_func.py b/tests/python_client/common/common_func.py index bf491b265c..b143844642 100644 --- a/tests/python_client/common/common_func.py +++ b/tests/python_client/common/common_func.py @@ -56,7 +56,9 @@ def gen_unique_str(str_value=None): return "test_" + prefix if str_value is None else str_value + "_" + prefix -def gen_str_by_length(length=8): +def gen_str_by_length(length=8, letters_only=False): + if letters_only: + return "".join(random.choice(string.ascii_letters) for _ in range(length)) return "".join(random.choice(string.ascii_letters + string.digits) for _ in range(length)) diff --git a/tests/python_client/common/common_type.py b/tests/python_client/common/common_type.py index 78c1baccc0..43e27e3972 100644 --- a/tests/python_client/common/common_type.py +++ b/tests/python_client/common/common_type.py @@ -256,3 +256,4 @@ class CaseLabel: L3 = "L3" Loadbalance = "Loadbalance" # loadbalance testcases which need to be run in multi query nodes ClusterOnly = "ClusterOnly" # For functions only suitable to cluster mode + MultiQueryNodes = "MultiQueryNodes" # for 8 query nodes configs tests, such as resource group diff --git a/tests/python_client/testcases/test_resourcegroup.py b/tests/python_client/testcases/test_resourcegroup.py index 29b580565d..c8b428ae49 100644 --- a/tests/python_client/testcases/test_resourcegroup.py +++ b/tests/python_client/testcases/test_resourcegroup.py @@ -6,10 +6,18 @@ from common import common_type as ct from common.common_type import CaseLabel, CheckTasks from utils.util_pymilvus import * +config_nodes = 8 + -@pytest.mark.skip(reason="will cause concurrent problems") class TestResourceGroupParams(TestcaseBase): - @pytest.mark.tags(CaseLabel.L0) + + @pytest.fixture(scope="function", params=ct.get_invalid_strs) + def invalid_names(self, request): + if request.param is None: + pytest.skip("None schema is valid") + yield request.param + + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_rg_default(self): """ method: @@ -27,7 +35,7 @@ class TestResourceGroupParams(TestcaseBase): self._connect() rgs, _ = self.utility_wrap.list_resource_groups() rgs_count = len(rgs) - default_rg_init_available_node = 1 + default_rg_init_available_node = config_nodes default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, "num_available_node": default_rg_init_available_node, @@ -101,7 +109,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_name", ["", None]) def test_create_rg_empty(self, rg_name): """ @@ -113,17 +121,9 @@ class TestResourceGroupParams(TestcaseBase): ct.err_msg: "`resource_group_name` value {} is illegal".format(rg_name)} self.init_resource_group(name=rg_name, check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) - def test_create_rg_valid_names(self): - """ - method: create a rg with a valid name(what are valid names?) - verify: create a rg successfully - """ - pass - - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_name", [[], 1, [1, "2", 3], (1,), {1: 1}, None]) - def test_create_rg_illegal_names(self, rg_name): + def test_create_n_drop_rg_illegal_names(self, rg_name): """ method: create a rg with an invalid name(what are invalid names? types, length, chinese,symbols) verify: fail with error msg @@ -132,10 +132,12 @@ class TestResourceGroupParams(TestcaseBase): error = {ct.err_code: 999, ct.err_msg: "`resource_group_name` value {} is illegal".format(rg_name)} self.init_resource_group(rg_name, check_task=ct.CheckTasks.err_res, check_items=error) - - @pytest.mark.tags(CaseLabel.L1) + # verify drop fail with error if illegal names + self.utility_wrap.drop_resource_group(rg_name, check_task=ct.CheckTasks.err_res, check_items=error) + + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_name", [" ", "12-s", "12 s", "(mn)", "中文", "%$#", "qw$_o90", "1ns_", "a".join("a" for i in range(256))]) - def test_create_rg_invalid_names(self, rg_name): + def test_create_n_drop_rg_invalid_names(self, rg_name): """ method: create a rg with an invalid name(what are invalid names? types, length, chinese,symbols) verify: fail with error msg @@ -144,25 +146,38 @@ class TestResourceGroupParams(TestcaseBase): error = {ct.err_code: 999, ct.err_msg: "Invalid resource group name"} self.init_resource_group(rg_name, check_task=ct.CheckTasks.err_res, check_items=error) + # verify drop succ with invalid names + self.utility_wrap.drop_resource_group(rg_name) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_create_rg_max_length_name(self): """ method: create a rg with a max length name verify: create a rg successfully """ - pass + name_max_length = 255 + rg_name = cf.gen_str_by_length(name_max_length, letters_only=True) + self.init_resource_group(name=rg_name) + self.utility_wrap.describe_resource_group(name=rg_name, + check_task=ct.CheckTasks.check_rg_property, + check_items={"name": rg_name}) + rg_name = cf.gen_str_by_length(name_max_length + 1) + error = {ct.err_code: 999, + ct.err_msg: "Invalid resource group name"} + self.init_resource_group(name=rg_name, + check_task=ct.CheckTasks.err_res, + check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_create_rg_dup_name(self): """ method: - 1. create a rg with name abc + 1. create a rg with name starts with "_" 2. create a rg with name abc again verify: fail with error msg when creating with a dup name """ self._connect() - rg_name = cf.gen_unique_str('rg') + rg_name = cf.gen_unique_str('_rg') self.init_resource_group(name=rg_name) self.utility_wrap.describe_resource_group(name=rg_name, check_task=ct.CheckTasks.check_rg_property, @@ -173,7 +188,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_create_rg_dropped_name(self): """ method: @@ -207,7 +222,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=ct.CheckTasks.check_rg_property, check_items={"name": rg_name}) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_create_max_number_rgs(self): """ method: @@ -233,7 +248,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_drop_rg_non_existing(self): """ method: drop a rg with a non-existing name @@ -245,7 +260,7 @@ class TestResourceGroupParams(TestcaseBase): self.utility_wrap.drop_resource_group(name=rg_name) assert rgs_count == len(self.utility_wrap.list_resource_groups()[0]) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_name", ["", None]) def test_drop_rg_empty_name(self, rg_name): """ @@ -257,15 +272,7 @@ class TestResourceGroupParams(TestcaseBase): ct.err_msg: "`resource_group_name` value {} is illegal".format(rg_name)} self.utility_wrap.drop_resource_group(name=rg_name, check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) - def test_drop_rg_invalid_names(self): - """ - method: drop a rg with invalid names(null, chinese, symbols) - verify: drop fail with error msg - """ - pass - - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_drop_rg_twice(self): """ method: @@ -288,7 +295,7 @@ class TestResourceGroupParams(TestcaseBase): self.utility_wrap.drop_resource_group(name=rg_name) assert rgs_count == len(self.utility_wrap.list_resource_groups()[0]) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_drop_default_rg(self): """ method: @@ -300,7 +307,7 @@ class TestResourceGroupParams(TestcaseBase): """ self._connect() rgs_count = len(self.utility_wrap.list_resource_groups()[0]) - default_rg_init_available_node = 1 + default_rg_init_available_node = config_nodes default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, "num_available_node": default_rg_init_available_node, @@ -320,7 +327,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=CheckTasks.check_rg_property, check_items=default_rg_info) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_name", ["", None]) def test_describe_rg_empty_name(self, rg_name): """ @@ -332,7 +339,7 @@ class TestResourceGroupParams(TestcaseBase): ct.err_msg: "`resource_group_name` value {} is illegal".format(rg_name)} self.utility_wrap.drop_resource_group(name=rg_name, check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_describe_rg_invalid_names(self): """ method: describe a rg with an invalid name(what are invalid names? types, length, chinese,symbols) @@ -340,7 +347,7 @@ class TestResourceGroupParams(TestcaseBase): """ pass - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_describe_rg_non_existing(self): """ method: describe a non-existing rg @@ -353,7 +360,7 @@ class TestResourceGroupParams(TestcaseBase): check_task=ct.CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L1) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_describe_default_rg(self): """ method: describe the default rg @@ -361,7 +368,7 @@ class TestResourceGroupParams(TestcaseBase): num_outgoing_node and num_incoming_node """ self._connect() - default_rg_init_available_node = 1 + default_rg_init_available_node = config_nodes default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, "num_available_node": default_rg_init_available_node, @@ -374,9 +381,8 @@ class TestResourceGroupParams(TestcaseBase): check_items=default_rg_info) -@pytest.mark.skip(reason="debugging") class TestTransferNode(TestcaseBase): - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_transfer_node_default(self): """ Method: @@ -443,7 +449,7 @@ class TestTransferNode(TestcaseBase): ) self.utility_wrap.drop_resource_group(name=rg1_name) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("with_growing", [True, False]) def test_transfer_node_from_default_rg(self, with_growing): """ @@ -477,7 +483,7 @@ class TestTransferNode(TestcaseBase): ) default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, - "num_available_node": 1, + "num_available_node": config_nodes, "num_loaded_replica": {collection_w.name: 1}, "num_outgoing_node": {}, "num_incoming_node": {} @@ -510,7 +516,7 @@ class TestTransferNode(TestcaseBase): check_items=rg_info) default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, - "num_available_node": 0, + "num_available_node": config_nodes - 1, "num_loaded_replica": {collection_w.name: 1}, "num_outgoing_node": {collection_w.name: 1}, "num_incoming_node": {} @@ -561,7 +567,7 @@ class TestTransferNode(TestcaseBase): check_items=rg_info) default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, - "num_available_node": 1, + "num_available_node": config_nodes, "num_loaded_replica": {collection_w.name: 1}, "num_outgoing_node": {}, "num_incoming_node": {} @@ -570,8 +576,8 @@ class TestTransferNode(TestcaseBase): check_task=CheckTasks.check_rg_property, check_items=default_rg_info) - @pytest.mark.skip(reason="issue #22224") - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.xfail(reason="issue #22224") + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("num_node", [0, 99, -1, 0.5, True, "str"]) def test_transfer_node_with_wrong_num_node(self, num_node): """ @@ -585,16 +591,18 @@ class TestTransferNode(TestcaseBase): self.init_resource_group(rg_name) # transfer replicas - error = {ct.err_code: 999, - ct.err_msg: 'failed to transfer node between resource group, err=nodes not enough'} + error = {ct.err_code: 999, ct.err_msg: f"failed to transfer node between resource group, err=nodes not enough"} + if num_node in [0, -1]: + error = {ct.err_code: 999, ct.err_msg: f"transfer node num can't be [{num_node}]"} + if type(num_node) is not int: + error = {ct.err_code: 999, ct.err_msg: 'expected one of: int'} self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rg_name, num_node=num_node, check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.skip(reason="issue #22224") - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("num_replica", [0, 99, -1, 0.5, True, "str"]) def test_transfer_replica_with_wrong_num_replica(self, num_replica): """ @@ -611,8 +619,14 @@ class TestTransferNode(TestcaseBase): self.init_resource_group(rg_name) # transfer replicas - error = {ct.err_code: 999, - ct.err_msg: 'failed to transfer replica between resource group, err=NotHealthy'} + error = {ct.err_code: 999, ct.err_msg: f"failed to transfer replica between resource group, err=nodes not enough"} + if not type(num_replica) in [int, bool]: + error = {ct.err_code: 999, ct.err_msg: 'expected one of: int'} + if num_replica in [0, -1]: + error = {ct.err_code: 999, ct.err_msg: f"transfer replica num can't be [{num_replica}]"} + if num_replica == 99: + error = {ct.err_code: 999, ct.err_msg: f"only found [1] replicas in source resource group[__default_resource_group]"} + self.utility_wrap.transfer_replica(source=ct.default_resource_group_name, target=rg_name, collection_name=collection_w.name, @@ -620,7 +634,7 @@ class TestTransferNode(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_load_collection_with_no_available_node(self): """ Method: @@ -651,7 +665,7 @@ class TestTransferNode(TestcaseBase): # 4. transfer query node from default to rgA self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rg_name, - num_node=1) + num_node=config_nodes) # 5. load the collection with default rg error = {ct.err_code: 999, ct.err_msg: 'failed to load collection, err=failed to spawn replica for collection[nodes not enough]'} @@ -659,8 +673,8 @@ class TestTransferNode(TestcaseBase): # 6. load the collection with rgA rg_info = {"name": rg_name, - "capacity": 1, - "num_available_node": 1, + "capacity": config_nodes, + "num_available_node": config_nodes, "num_loaded_replica": {}, "num_outgoing_node": {}, "num_incoming_node": {} @@ -683,8 +697,8 @@ class TestTransferNode(TestcaseBase): ) # check rgA info rg_info = {"name": rg_name, - "capacity": 1, - "num_available_node": 1, + "capacity": config_nodes, + "num_available_node": config_nodes, "num_loaded_replica": {collection_w.name: 1}, "num_outgoing_node": {}, "num_incoming_node": {} @@ -696,7 +710,7 @@ class TestTransferNode(TestcaseBase): # 7. transfer query node from rgA to default rg self.utility_wrap.transfer_node(source=rg_name, target=ct.default_resource_group_name, - num_node=1) + num_node=config_nodes) # verify search keeps succ collection_w.search(vectors[:nq], ct.default_float_vec_field_name, @@ -712,7 +726,7 @@ class TestTransferNode(TestcaseBase): "capacity": 0, "num_available_node": 0, "num_loaded_replica": {}, - "num_outgoing_node": {collection_w.name: 1}, + "num_outgoing_node": {collection_w.name: config_nodes}, "num_incoming_node": {} } self.utility_wrap.describe_resource_group(name=rg_name, @@ -720,10 +734,10 @@ class TestTransferNode(TestcaseBase): check_items=rg_info) default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, - "num_available_node": 1, + "num_available_node": config_nodes, "num_loaded_replica": {}, "num_outgoing_node": {}, - "num_incoming_node": {collection_w.name: 1} + "num_incoming_node": {collection_w.name: config_nodes} } self.utility_wrap.describe_resource_group(name=ct.default_resource_group_name, check_task=CheckTasks.check_rg_property, @@ -732,7 +746,7 @@ class TestTransferNode(TestcaseBase): # 8. load the collection with default rg collection_w.load() - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("replicas", [1, 3]) def test_load_collection_with_multi_replicas_multi_rgs(self, replicas): """ @@ -761,11 +775,13 @@ class TestTransferNode(TestcaseBase): _resource_groups=[rgA_name, rgB_name], check_task=CheckTasks.err_res, check_items=error) + error = {ct.err_code: 999, + ct.err_msg: "failed to load collection, err=load operation can't use default resource group and other resource group together"} collection_w.load(replica_number=replicas, _resource_groups=[ct.default_resource_group_name, rgB_name], check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_names", [[""], ["non_existing"], "不合法"]) def test_load_collection_with_empty_rg_name(self, rg_names): """ @@ -780,7 +796,7 @@ class TestTransferNode(TestcaseBase): collection_w.load(_resource_groups=rg_names, check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_load_partition_with_no_available_node(self): """ Method: @@ -804,16 +820,16 @@ class TestTransferNode(TestcaseBase): collection_w = self.init_collection_wrap() partition_name = cf.gen_unique_str('par') partition_w = self.init_partition_wrap(collection_w, partition_name) - data = cf.gen_default_list_data(nb=3000) + data = cf.gen_default_list_data(nb=2000) ins_res, _ = partition_w.insert(data) collection_w.create_index(ct.default_float_vec_field_name, ct.default_flat_index) # 3. create a rgA rg_name = cf.gen_unique_str('rg') self.init_resource_group(rg_name) - # 4. transfer query node from default to rgA + # 4. transfer all query nodes from default to rgA self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rg_name, - num_node=1) + num_node=config_nodes) # 5. load the collection with default rg error = {ct.err_code: 999, ct.err_msg: 'failed to load partitions, err=failed to spawn replica for collection[nodes not enough]'} @@ -835,8 +851,8 @@ class TestTransferNode(TestcaseBase): ) # check rgA info rg_info = {"name": rg_name, - "capacity": 1, - "num_available_node": 1, + "capacity": config_nodes, + "num_available_node": config_nodes, "num_loaded_replica": {collection_w.name: 1}, "num_outgoing_node": {}, "num_incoming_node": {} @@ -845,10 +861,20 @@ class TestTransferNode(TestcaseBase): check_task=CheckTasks.check_rg_property, check_items=rg_info) + # verify replica + replicas = partition_w.get_replicas() + num_nodes_for_replicas = 0 + assert len(replicas[0].groups) == 1 + for rep in replicas[0].groups: + assert rep.resource_group == rg_name + assert rep.num_outbound_node == {} + num_nodes_for_replicas += len(rep.group_nodes) + assert num_nodes_for_replicas == config_nodes + # 7. transfer query node from rgA to default rg self.utility_wrap.transfer_node(source=rg_name, target=ct.default_resource_group_name, - num_node=1) + num_node=config_nodes) # verify search keeps succ partition_w.search(vectors[:nq], ct.default_float_vec_field_name, @@ -864,7 +890,7 @@ class TestTransferNode(TestcaseBase): "capacity": 0, "num_available_node": 0, "num_loaded_replica": {}, - "num_outgoing_node": {collection_w.name: 1}, + "num_outgoing_node": {collection_w.name: config_nodes}, "num_incoming_node": {} } self.utility_wrap.describe_resource_group(name=rg_name, @@ -872,10 +898,10 @@ class TestTransferNode(TestcaseBase): check_items=rg_info) default_rg_info = {"name": ct.default_resource_group_name, "capacity": ct.default_resource_group_capacity, - "num_available_node": 1, + "num_available_node": config_nodes, "num_loaded_replica": {}, "num_outgoing_node": {}, - "num_incoming_node": {collection_w.name: 1} + "num_incoming_node": {collection_w.name: config_nodes} } self.utility_wrap.describe_resource_group(name=ct.default_resource_group_name, check_task=CheckTasks.check_rg_property, @@ -884,7 +910,7 @@ class TestTransferNode(TestcaseBase): # 8. load the collection without rg specified partition_w.load() - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("replicas", [1, 3]) def test_load_partition_with_multi_replicas_multi_rgs(self, replicas): """ @@ -916,11 +942,13 @@ class TestTransferNode(TestcaseBase): _resource_groups=[rgA_name, rgB_name], check_task=CheckTasks.err_res, check_items=error) + error = {ct.err_code: 999, + ct.err_msg: "failed to load partitions, err=load operation should use collection's resource group"} partition_w.load(replica_number=replicas, _resource_groups=[ct.default_resource_group_name, rgB_name], check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("rg_names", [[""], ["non_existing"], "不合法", [ct.default_resource_group_name, None]]) def test_load_partition_with_empty_rg_name(self, rg_names): """ @@ -941,12 +969,10 @@ class TestTransferNode(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) -@pytest.mark.skip(reason="need 8 query nodes for this test") # run the multi node tests with 8 query nodes class TestResourceGroupMultiNodes(TestcaseBase): - @pytest.mark.tags(CaseLabel.L0) - @pytest.mark.parametrize("with_growing", [True, False]) - def test_load_with_multi_collections_one_rg(self, with_growing): + @pytest.mark.tags(CaseLabel.MultiQueryNodes) + def test_load_with_multi_collections_one_rg(self): """ Method: 1. prepare collectionA and collectionB @@ -956,9 +982,80 @@ class TestResourceGroupMultiNodes(TestcaseBase): verify the rg state verify the replicas state for both collections """ - pass + self._connect() + dim = ct.default_dim + # create a collectionA and collectionB + collection_w_a = self.init_collection_wrap(shards_num=2) + collection_w_b = self.init_collection_wrap(shards_num=2) + nb = 400 + for i in range(5): + collection_w_a.insert(cf.gen_default_list_data(nb=nb, dim=dim)) + collection_w_b.insert(cf.gen_default_list_data(nb=nb, dim=dim)) + collection_w_a.flush() + collection_w_b.flush() + collection_w_a.create_index(ct.default_float_vec_field_name, ct.default_index) + collection_w_b.create_index(ct.default_float_vec_field_name, ct.default_index) - @pytest.mark.tags(CaseLabel.L0) + # create a rgA + rg_name = cf.gen_unique_str('rg') + self.init_resource_group(rg_name) + # transfer 4 nodes to rgA + num_nodes_to_rg = 4 + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rg_name, + num_node=num_nodes_to_rg) + + # load 1 replica of collectionA to rgA + collection_w_a.load(replica_number=1, + _resource_groups=[rg_name]) + # load 3 replica of collectionB to rgA + collection_w_b.load(replica_number=3, + _resource_groups=[rg_name]) + + # verify rg state + rg_info = {"name": rg_name, + "capacity": num_nodes_to_rg, + "num_available_node": num_nodes_to_rg, + "num_loaded_replica": {collection_w_a.name: 1, collection_w_b.name: 3}, + "num_outgoing_node": {}, + "num_incoming_node": {} + } + self.utility_wrap.describe_resource_group(name=rg_name, + check_task=CheckTasks.check_rg_property, + check_items=rg_info) + + # verify replica state + replicas = collection_w_a.get_replicas() + num_nodes_for_replicas = 0 + assert len(replicas[0].groups) == 1 + for rep in replicas[0].groups: + assert rep.resource_group == rg_name + assert rep.num_outbound_node == {} + num_nodes_for_replicas += len(rep.group_nodes) + assert num_nodes_for_replicas == num_nodes_to_rg + + replicas = collection_w_b.get_replicas() + num_nodes_for_replicas = 0 + assert len(replicas[0].groups) == 3 + for rep in replicas[0].groups: + assert rep.resource_group == rg_name + assert rep.num_outbound_node == {} + num_nodes_for_replicas += len(rep.group_nodes) + assert num_nodes_for_replicas == num_nodes_to_rg + + # verify search succ on both collections + nq = 5 + vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] + collection_w_a.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit) + collection_w_b.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit) + + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("with_growing", [True, False]) def test_load_with_replicas_and_nodes_num(self, with_growing): """ @@ -1124,7 +1221,7 @@ class TestResourceGroupMultiNodes(TestcaseBase): "limit": ct.default_limit} ) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("with_growing", [True, False]) def test_load_with_replicas_and_rgs_num(self, with_growing): """ @@ -1234,8 +1331,232 @@ class TestResourceGroupMultiNodes(TestcaseBase): "limit": ct.default_limit} ) - @pytest.mark.xfail(reason='issue #22217') - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) + @pytest.mark.parametrize("with_growing", [True, False]) + def test_transfer_multi_replicas_from_to_default_rg(self, with_growing): + """ + Method: + 1. prepare a collection with multi segments + 2. create rgA with 4 nodes + 3. reload 3 replicas into default rg + 4. transfer 3 replicas from default rg to rgA + 5. release and reload 3 replicas into rgA + 6. transfer 3 replicas from rgA to default rg + """ + self._connect() + rgA_name = cf.gen_unique_str('rgA') + self.init_resource_group(name=rgA_name) + + # transfer 4 nodes to rgA + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgA_name, + num_node=4) + + dim = 128 + collection_w = self.init_collection_wrap(shards_num=4) + insert_ids = [] + nb = 500 + for i in range(5): + res, _ = collection_w.insert(cf.gen_default_list_data(nb=nb, dim=dim, start=i * nb)) + collection_w.flush() + insert_ids.extend(res.primary_keys) + collection_w.create_index(ct.default_float_vec_field_name, ct.default_flat_index) + + # release collection and reload 2 replicas into rgA + num_replica = 3 + collection_w.load(replica_number=num_replica, _resource_groups=[ct.default_resource_group_name]) + + # make growing + if with_growing: + res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=6 * nb)) + insert_ids.extend(res.primary_keys) + + # transfer 1/2/3 replicas from default rg to rgA + self.utility_wrap.transfer_replica(source=ct.default_resource_group_name, target=rgA_name, + collection_name=collection_w.name, + num_replica=1) + # verify search succ + nq = 5 + vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] + collection_w.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + # release and reload 3 replicas into rgA + collection_w.release() + collection_w.load(replica_number=num_replica, _resource_groups=[rgA_name]) + + # make growing + if with_growing: + res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=7 * nb)) + insert_ids.extend(res.primary_keys) + + # transfer 1/2/3 replicas from rgA to default rg + self.utility_wrap.transfer_replica(source=rgA_name, target=ct.default_resource_group_name, + collection_name=collection_w.name, + num_replica=1) + # verify search succ + collection_w.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + + @pytest.mark.tags(CaseLabel.MultiQueryNodes) + @pytest.mark.parametrize("with_growing", [True, False]) + def test_transfer_multi_replicas_into_one_rg(self, with_growing): + """ + Method: + 1. prepare a collection with multi segments + 2. create rgA with 2 nodes and rgB with 3 nodes + 7. reload 2 replicas into rgA + 8. transfer 2 replicas from rgA to rgB + """ + self._connect() + rgA_name = cf.gen_unique_str('rgA') + self.init_resource_group(name=rgA_name) + rgB_name = cf.gen_unique_str('rgB') + self.init_resource_group(name=rgB_name) + + # transfer 1 nodes to rgA, 2 nodes to rgB + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgA_name, + num_node=2) + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgB_name, + num_node=3) + + dim = 128 + collection_w = self.init_collection_wrap(shards_num=4) + insert_ids = [] + nb = 500 + for i in range(5): + res, _ = collection_w.insert(cf.gen_default_list_data(nb=nb, dim=dim, start=i * nb)) + collection_w.flush() + insert_ids.extend(res.primary_keys) + collection_w.create_index(ct.default_float_vec_field_name, ct.default_flat_index) + + # release collection and reload 2 replicas into rgA + num_replica = 2 + collection_w.load(replica_number=num_replica, _resource_groups=[rgA_name]) + + # make growing + if with_growing: + res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=6 * nb)) + insert_ids.extend(res.primary_keys) + + # verify replicas + replicas = collection_w.get_replicas() + assert len(replicas[0].groups) == num_replica + for rep in replicas[0].groups: + assert rep.resource_group in [rgA_name] + assert rep.num_outbound_node == {} + assert len(rep.group_nodes) == 1 # 1 node for each replica + + # transfer 2 replicas from rgA to rgB + self.utility_wrap.transfer_replica(source=rgA_name, target=rgB_name, + collection_name=collection_w.name, + num_replica=num_replica) + + # verify replicas + replicas = collection_w.get_replicas() + assert len(replicas[0].groups) == num_replica + for rep in replicas[0].groups: + assert rep.resource_group in [rgB_name] + assert rep.num_outbound_node == {rgA_name: 1} + + # verify rg state + rgA_info = {"name": rgA_name, + "capacity": 2, + "num_available_node": 2, + "num_loaded_replica": {}, + "num_outgoing_node": {}, + "num_incoming_node": {collection_w.name: 2} + } + self.utility_wrap.describe_resource_group(name=rgA_name, + check_task=CheckTasks.check_rg_property, + check_items=rgA_info) + rgB_info = {"name": rgB_name, + "capacity": 3, + "num_available_node": 3, + "num_loaded_replica": {collection_w.name: 2}, + "num_outgoing_node": {collection_w.name: 2}, + "num_incoming_node": {} + } + self.utility_wrap.describe_resource_group(name=rgB_name, + check_task=CheckTasks.check_rg_property, + check_items=rgB_info) + + # verify search succ + nq = 5 + vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] + collection_w.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + + # wait transfer completed for replicas + time.sleep(60) + # make growing + if with_growing: + res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=7 * nb)) + insert_ids.extend(res.primary_keys) + + rgA_info = {"name": rgA_name, + "capacity": 2, + "num_available_node": 2, + "num_loaded_replica": {}, + "num_outgoing_node": {}, + "num_incoming_node": {} + } + self.utility_wrap.describe_resource_group(name=rgA_name, + check_task=CheckTasks.check_rg_property, + check_items=rgA_info) + rgB_info = {"name": rgB_name, + "capacity": 3, + "num_available_node": 3, + "num_loaded_replica": {collection_w.name: 2}, + "num_outgoing_node": {}, + "num_incoming_node": {} + } + self.utility_wrap.describe_resource_group(name=rgB_name, + check_task=CheckTasks.check_rg_property, + check_items=rgB_info) + + # verify search succ + collection_w.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + + # verify replicas + replicas = collection_w.get_replicas() + assert len(replicas[0].groups) == num_replica + for rep in replicas[0].groups: + assert rep.resource_group in [rgB_name] + assert rep.num_outbound_node == {} + assert 1 <= len(rep.group_nodes) <= 2 # 1-2 node for each replica + + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("with_growing", [True, False]) def test_transfer_replica_into_same_rg(self, with_growing): """ @@ -1248,10 +1569,8 @@ class TestResourceGroupMultiNodes(TestcaseBase): verify fail with error 6. transfer 1 replica from rgA to rgB verify fail with error - 7. release the collection - 8. reload the collection with 2 replicas in default rg and rgA - 9. transfer 1 replica from rgA to default rg - verify fail with error + 7. release collection and reload 2 replicas into rgA + 8. transfer 2 replicas from rgA to rgB """ self._connect() rgA_name = cf.gen_unique_str('rgA') @@ -1262,10 +1581,10 @@ class TestResourceGroupMultiNodes(TestcaseBase): # transfer 1 nodes to rgA, 2 nodes to rgB self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rgA_name, - num_node=1) + num_node=2) self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rgB_name, - num_node=2) + num_node=3) dim = 128 collection_w = self.init_collection_wrap(shards_num=4) @@ -1312,45 +1631,26 @@ class TestResourceGroupMultiNodes(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) - # release the collection - collection_w.release() - # reload the collection into default rg and rgA - # TODO: not able to load replicas into default rg with customized rgs - collection_w.load(replica_number=2, _resource_groups=[rgA_name, ct.default_resource_group_name]) - - # make growing - if with_growing: - res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=7 * nb)) - insert_ids.extend(res.primary_keys) - - # transfer 1 replica from rgA to default rg - error = {ct.err_code: 999, - ct.err_msg: f'found [1] replicas of same collection in target resource group[{ct.default_resource_group_name}], dynamically increase replica num is unsupported'} - self.utility_wrap.transfer_replica(source=rgA_name, target=ct.default_resource_group_name, - collection_name=collection_w.name, num_replica=1, - check_task=CheckTasks.err_res, - check_items=error) - - # verify search succ - nq = 5 - vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] - collection_w.search(vectors[:nq], - ct.default_float_vec_field_name, - ct.default_search_params, - ct.default_limit, - check_task=CheckTasks.check_search_results, - check_items={"nq": nq, - "ids": insert_ids.copy(), - "limit": ct.default_limit} - ) - - @pytest.mark.tags(CaseLabel.L0) - def test_transfer_nodes_back(self): + @pytest.mark.tags(CaseLabel.MultiQueryNodes) + def test_load_multi_rgs_with_default_rg(self): + """ + Method: + 1. prepare a rgA with 2 nodes + 2. create a collection + 3. load the collection into rgA and default rg + verify fail with error msg + 4. load the collection into rgA and rgB + verify search succ + 5. transfer replica from rgB to default rg + verify search succ + 6. transfer node from rgA to default rgA + verify fail with error + 7. transfer node from rgB to default rgB + 8. verify search succ + """ self._connect() - - rgA_name = "rgA" + rgA_name = cf.gen_unique_str('rgA') self.init_resource_group(name=rgA_name) - self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rgA_name, num_node=2) @@ -1364,8 +1664,23 @@ class TestResourceGroupMultiNodes(TestcaseBase): insert_ids.extend(res.primary_keys) collection_w.create_index(ct.default_float_vec_field_name, ct.default_flat_index) - collection_w.load(replica_number=2, _resource_groups=[rgA_name, ct.default_resource_group_name]) + # load the collection with rgA and default rg + error = {ct.err_code: 999, + ct.err_msg: f"failed to load collection, err=load operation can't use default resource group and other resource group together"} + collection_w.load(replica_number=2, + _resource_groups=[rgA_name, ct.default_resource_group_name], + check_task=CheckTasks.err_res, + check_items=error) + rgB_name = cf.gen_unique_str('rgB') + self.init_resource_group(name=rgB_name) + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgB_name, + num_node=2) + + # load the collection into rgA and rgB + collection_w.load(replica_number=2, + _resource_groups=[rgA_name, rgB_name]) nq = 5 vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] # verify search succ @@ -1378,11 +1693,35 @@ class TestResourceGroupMultiNodes(TestcaseBase): "ids": insert_ids.copy(), "limit": ct.default_limit} ) - self.utility_wrap.transfer_node(source=rgA_name, - target=ct.default_resource_group_name, - num_node=2) - - time.sleep(10) + # transfer the replica from rgB to default rg + self.utility_wrap.transfer_replica(source=rgB_name, + target=ct.default_resource_group_name, + collection_name=collection_w.name, + num_replica=1) + + time.sleep(1) + collection_w.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + + # transfer all nodes back to default rg + error = {ct.err_code: 999, + ct.err_msg: f"can't transfer node, cause the resource group[{rgA_name}] and the resource group[{ct.default_resource_group_name}] loaded same collection"} + self.utility_wrap.transfer_node(source=rgA_name, + target=ct.default_resource_group_name, + num_node=2, + check_task=CheckTasks.err_res, + check_items=error) + self.utility_wrap.transfer_node(source=rgB_name, + target=ct.default_resource_group_name, + num_node=2) + time.sleep(1) collection_w.search(vectors[:nq], ct.default_float_vec_field_name, ct.default_search_params, @@ -1392,10 +1731,9 @@ class TestResourceGroupMultiNodes(TestcaseBase): "ids": insert_ids.copy(), "limit": ct.default_limit} ) - collection_w.get_replicas() - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_transfer_replica_not_enough_replicas_to_transfer(self): """ Method: @@ -1425,7 +1763,7 @@ class TestResourceGroupMultiNodes(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) def test_transfer_replica_non_existing_rg(self): """ Method: @@ -1458,17 +1796,17 @@ class TestResourceGroupMultiNodes(TestcaseBase): check_task=CheckTasks.err_res, check_items=error) - @pytest.mark.tags(CaseLabel.L0) + @pytest.mark.tags(CaseLabel.MultiQueryNodes) @pytest.mark.parametrize("with_growing", [True, False]) - def test_transfer_node_(self, with_growing): + def test_transfer_node_when_there_same_collection(self, with_growing): """ Method: 1. prepare a collection - 2. prepare rgA and rgB, both with 1 node - 3. load 2 replicas into rgA and rgB - verify search succ, replica info, rg state - 4. transfer the node from rgA to rgB + 2. prepare rgA and rgB and rgC, both with 2 node + 3. load 3 replicas into rgA, rgB and rgC verify search succ, replica info, rg state + 4. transfer 1 node from rgA to rgB + verify fail with error """ dim = 128 collection_w = self.init_collection_wrap(shards_num=4) @@ -1480,32 +1818,37 @@ class TestResourceGroupMultiNodes(TestcaseBase): insert_ids.extend(res.primary_keys) collection_w.create_index(ct.default_float_vec_field_name, ct.default_index) + num_node =2 rgA_name = cf.gen_unique_str('rgA') self.init_resource_group(rgA_name) self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rgA_name, - num_node=1) + num_node=num_node) rgB_name = cf.gen_unique_str('rgB') self.init_resource_group(rgB_name) self.utility_wrap.transfer_node(source=ct.default_resource_group_name, target=rgB_name, - num_node=1) + num_node=num_node) + rgC_name = cf.gen_unique_str('rgC') + self.init_resource_group(rgC_name) + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgC_name, + num_node=num_node) # make growing if with_growing: res, _ = collection_w.insert(cf.gen_default_list_data(nb, dim=dim, start=6 * nb)) insert_ids.extend(res.primary_keys) # load 2 replicas into rgA and rgB - collection_w.load(replica_number=2, _resource_groups=[rgA_name, rgB_name]) + replica_num = 3 + collection_w.load(replica_number=replica_num, _resource_groups=[rgA_name, rgB_name, rgC_name]) replicas = collection_w.get_replicas() - assert len(replicas[0].groups) == 2 + assert len(replicas[0].groups) == replica_num for rep in replicas[0].groups: - assert rep.resource_group in [rgA_name, rgB_name] + assert rep.resource_group in [rgA_name, rgB_name, rgC_name] assert rep.num_outbound_node == {} - assert len(rep.group_nodes) == 1 # one replica for each node - - # TODO: verify rg state + assert len(rep.group_nodes) == num_node # 2 node for each replica nq = 5 vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] @@ -1521,26 +1864,91 @@ class TestResourceGroupMultiNodes(TestcaseBase): ) # transfer node from rgA to rgB - self.utility_wrap.transfer_node(source=rgA_name, target=rgB_name, num_node=1) + error = {ct.err_code: 999, + ct.err_msg: f"can't transfer node, cause the resource group[{rgA_name}] and the resource group[{rgB_name}] loaded same collection, err=resource group doesn't exist"} + self.utility_wrap.transfer_node(source=rgA_name, target=rgB_name, + num_node=1, + check_task=CheckTasks.err_res, + check_items=error) - # TODO: verify rg state - # TODO: verify replica state - # replicas = collection_w.get_replicas() - # assert len(replicas[0].groups) == 2 - # for rep in replicas[0].groups: - # assert rep.resource_group in [rgA_name, rgB_name] - # assert rep.num_outbound_node == {} - # assert len(rep.group_nodes) == 1 # one replica for each node + @pytest.mark.tags(CaseLabel.MultiQueryNodes) + @pytest.mark.parametrize("with_growing", [True, False]) + def test_transfer_node_n_replicas_to_default_rg(self, with_growing): + """ + Method: + 1. create 2 collections: c1 and c2 + 2. create 2 rgs: rgA(1 node) and rgB(0 node) + 3. load c1 and c2 with 1 replica into default rg + 4. transfer 1 node from default rg to rgB and transfer replica of c2 from default to rgB + 5. transfer replica of c1 from default to rgB + """ + dim = 128 + collection_w_a = self.init_collection_wrap(shards_num=4) + collection_w_b = self.init_collection_wrap(shards_num=4) + insert_ids = [] + nb = 500 + for i in range(5): + res, _ = collection_w_a.insert(cf.gen_default_list_data(nb=nb, dim=dim, start=i * nb)) + collection_w_a.flush() + res, _ = collection_w_b.insert(cf.gen_default_list_data(nb=nb, dim=dim, start=i * nb)) + collection_w_b.flush() + insert_ids.extend(res.primary_keys) + collection_w_a.create_index(ct.default_float_vec_field_name, ct.default_index) + collection_w_b.create_index(ct.default_float_vec_field_name, ct.default_index) + # prepare rg + num_node = 2 + rgA_name = cf.gen_unique_str('rgA') + self.init_resource_group(rgA_name) + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgA_name, + num_node=num_node) + rgB_name = cf.gen_unique_str('rgB') + self.init_resource_group(rgB_name) + + # load collections + collection_w_a.load() + collection_w_b.load() + + # make growing + if with_growing: + res, _ = collection_w_a.insert(cf.gen_default_list_data(nb, dim=dim, start=6 * nb)) + res, _ = collection_w_b.insert(cf.gen_default_list_data(nb, dim=dim, start=6 * nb)) + insert_ids.extend(res.primary_keys) + + # transfer 1 node from default rg to rgB and transfer replica of c2 from default to rgB + self.utility_wrap.transfer_node(source=ct.default_resource_group_name, + target=rgB_name, + num_node=1) + self.utility_wrap.transfer_replica(source=ct.default_resource_group_name, + target=rgB_name, + collection_name=collection_w_b.name, + num_replica=1) + + # transfer replica of c1 from default to rgB + self.utility_wrap.transfer_replica(source=ct.default_resource_group_name, + target=rgB_name, + collection_name=collection_w_a.name, + num_replica=1) + + # verify search succ nq = 5 vectors = [[random.random() for _ in range(dim)] for _ in range(nq)] - # verify search succ - collection_w.search(vectors[:nq], - ct.default_float_vec_field_name, - ct.default_search_params, - ct.default_limit, - check_task=CheckTasks.check_search_results, - check_items={"nq": nq, - "ids": insert_ids.copy(), - "limit": ct.default_limit} - ) \ No newline at end of file + collection_w_a.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + ) + collection_w_b.search(vectors[:nq], + ct.default_float_vec_field_name, + ct.default_search_params, + ct.default_limit, + check_task=CheckTasks.check_search_results, + check_items={"nq": nq, + "ids": insert_ids.copy(), + "limit": ct.default_limit} + )