mirror of https://github.com/milvus-io/milvus.git
Add, enable and xfail test cases (#7071)
* Add, enable and xfail test cases Signed-off-by: Binbin Lv <binbin.lv@zilliz.com> * Modify the test case label Signed-off-by: Binbin Lv <binbin.lv@zilliz.com>pull/7083/head
parent
d9a5ca645a
commit
3c6a807fd2
|
@ -5,7 +5,7 @@
|
|||
String cron_timezone = "TZ=Asia/Shanghai"
|
||||
String cron_string = BRANCH_NAME == "master" ? "50 22 * * * " : ""
|
||||
|
||||
int total_timeout_minutes = 90
|
||||
int total_timeout_minutes = 120
|
||||
int e2e_timeout_seconds = 60 * 60
|
||||
|
||||
pipeline {
|
||||
|
|
|
@ -610,6 +610,7 @@ class TestInsertBinary:
|
|||
assert stats[row_count] == default_nb
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.skip(reason="issue 7027")
|
||||
def test_insert_binary_multi_times(self, connect, binary_collection):
|
||||
'''
|
||||
target: test insert entities multi times and final flush
|
||||
|
|
|
@ -4,7 +4,7 @@ log_date_format = %Y-%m-%d %H:%M:%S
|
|||
|
||||
log_cli = true
|
||||
log_level = 20
|
||||
addopts = -x
|
||||
#addopts = -x
|
||||
|
||||
timeout = 360
|
||||
|
||||
|
|
|
@ -72,11 +72,12 @@ pushd "${ROOT}/tests/docker"
|
|||
else
|
||||
if [[ "${MILVUS_CLIENT}" == "pymilvus" ]]; then
|
||||
export MILVUS_PYTEST_WORKSPACE="/milvus/tests/python_test"
|
||||
docker-compose run --rm pytest /bin/bash -c "pytest -n ${PARALLEL_NUM} --ip ${MILVUS_SERVICE_IP} --port ${MILVUS_SERVICE_PORT} ${@:-}"
|
||||
docker-compose run --rm pytest /bin/bash -c "pytest -n ${PARALLEL_NUM} --ip ${MILVUS_SERVICE_IP} \
|
||||
--port ${MILVUS_SERVICE_PORT} ${@:-} -x"
|
||||
elif [[ "${MILVUS_CLIENT}" == "pymilvus-orm" ]]; then
|
||||
export MILVUS_PYTEST_WORKSPACE="/milvus/tests20/python_client"
|
||||
docker-compose run --rm pytest /bin/bash -c "pytest -n ${PARALLEL_NUM} --host ${MILVUS_SERVICE_IP} --port ${MILVUS_SERVICE_PORT} \
|
||||
--html=\${CI_LOG_PATH}/report.html --self-contained-html ${@:-}"
|
||||
--html=\${CI_LOG_PATH}/report.html --self-contained-html ${@:-} -x"
|
||||
fi
|
||||
fi
|
||||
popd
|
||||
|
|
|
@ -81,3 +81,14 @@ class ApiUtilityWrapper:
|
|||
check_result = ResponseChecker(res, func_name, check_task, check_items, is_succ,
|
||||
timeout=timeout, using=using).run()
|
||||
return res, check_result
|
||||
|
||||
def calc_distance(self, vectors_left, vectors_right, params=None, timeout=None,
|
||||
using="default", check_task=None, check_items=None):
|
||||
timeout = TIMEOUT if timeout is None else timeout
|
||||
|
||||
func_name = sys._getframe().f_code.co_name
|
||||
res, is_succ = api_request([self.ut.calc_distance, vectors_left, vectors_right,
|
||||
params, timeout, using])
|
||||
check_result = ResponseChecker(res, func_name, check_task, check_items, is_succ,
|
||||
timeout=timeout, using=using).run()
|
||||
return res, check_result
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from utils.util_log import test_log as log
|
||||
from common import common_type as ct
|
||||
from common import common_func as cf
|
||||
from common.common_type import CheckTasks, Connect_Object_Name
|
||||
# from common.code_mapping import ErrorCode, ErrorMessage
|
||||
from pymilvus_orm import Collection, Partition
|
||||
|
@ -53,6 +54,10 @@ class ResponseChecker:
|
|||
# Query interface of collection and partition that response check
|
||||
result = self.check_query_results(self.response, self.func_name, self.check_items)
|
||||
|
||||
elif self.check_task == CheckTasks.check_distance:
|
||||
# Calculate distance interface that response check
|
||||
result = self.check_distance(self.response, self.func_name, self.check_items)
|
||||
|
||||
# Add check_items here if something new need verify
|
||||
|
||||
return result
|
||||
|
@ -212,3 +217,20 @@ class ResponseChecker:
|
|||
# for i in range(len(exp_res)):
|
||||
# assert_entity_equal(exp=exp_res[i], actual=query_res[i])
|
||||
|
||||
@staticmethod
|
||||
def check_distance(distance_res, func_name, check_items):
|
||||
if func_name != 'calc_distance':
|
||||
log.warning("The function name is {} rather than {}".format(func_name, "calc_distance"))
|
||||
if not isinstance(distance_res, list):
|
||||
raise Exception("The distance result to check isn't list type object")
|
||||
if len(check_items) == 0:
|
||||
raise Exception("No expect values found in the check task")
|
||||
vectors_l = check_items["vectors_l"]
|
||||
vectors_r = check_items["vectors_r"]
|
||||
metric = check_items.get("metric", "L2")
|
||||
sqrt = check_items.get("sqrt", False)
|
||||
cf.compare_distance_2d_vector(vectors_l, vectors_r,
|
||||
distance_res,
|
||||
metric, sqrt)
|
||||
|
||||
return True
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import random
|
||||
import math
|
||||
import string
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
@ -13,7 +14,7 @@ import threading
|
|||
import traceback
|
||||
|
||||
"""" Methods of processing data """
|
||||
l2 = lambda x, y: np.linalg.norm(np.array(x) - np.array(y))
|
||||
#l2 = lambda x, y: np.linalg.norm(np.array(x) - np.array(y))
|
||||
|
||||
|
||||
def gen_unique_str(str_value=None):
|
||||
|
@ -313,7 +314,7 @@ def gen_search_param(index_type, metric_type="L2"):
|
|||
search_params.append(nsg_search_param)
|
||||
elif index_type == "ANNOY":
|
||||
for search_k in [1000, 5000]:
|
||||
annoy_search_param = {"metric_type": metric_type, "params": {"search_length": search_k}}
|
||||
annoy_search_param = {"metric_type": metric_type, "params": {"search_k": search_k}}
|
||||
search_params.append(annoy_search_param)
|
||||
else:
|
||||
log.error("Invalid index_type.")
|
||||
|
@ -353,6 +354,14 @@ def gen_normal_expressions_field(field):
|
|||
return expressions
|
||||
|
||||
|
||||
def l2(x, y):
|
||||
return np.linalg.norm(np.array(x) - np.array(y))
|
||||
|
||||
|
||||
def ip(x, y):
|
||||
return np.inner(np.array(x), np.array(y))
|
||||
|
||||
|
||||
def jaccard(x, y):
|
||||
x = np.asarray(x, np.bool)
|
||||
y = np.asarray(y, np.bool)
|
||||
|
@ -382,6 +391,27 @@ def superstructure(x, y):
|
|||
y = np.asarray(y, np.bool)
|
||||
return 1 - np.double(np.bitwise_and(x, y).sum()) / np.count_nonzero(x)
|
||||
|
||||
def compare_distance_2d_vector(x, y, distance, metric, sqrt):
|
||||
for i in range(len(x)):
|
||||
for j in range(len(y)):
|
||||
if metric == "L2":
|
||||
distance_i = l2(x[i], y[j])
|
||||
if not sqrt:
|
||||
distance_i = math.pow(distance_i, 2)
|
||||
elif metric == "IP":
|
||||
distance_i = ip(x[i], y[j])
|
||||
elif metric == "HAMMING":
|
||||
distance_i = hamming(x[i], y[j])
|
||||
elif metric == "TANIMOTO":
|
||||
distance_i = tanimoto(x[i], y[j])
|
||||
elif metric == "JACCARD":
|
||||
distance_i = jaccard(x[i], y[j])
|
||||
else:
|
||||
raise Exception("metric type is invalid")
|
||||
assert abs(distance_i - distance[i][j]) < ct.epsilon
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def modify_file(file_path_list, is_modify=False, input_content=""):
|
||||
"""
|
||||
|
|
|
@ -114,6 +114,21 @@ get_invalid_ints = [
|
|||
"a".join("a" for i in range(256))
|
||||
]
|
||||
|
||||
get_invalid_dict = [
|
||||
[],
|
||||
1,
|
||||
[1, "2", 3],
|
||||
(1,),
|
||||
None,
|
||||
"",
|
||||
" ",
|
||||
"12-s",
|
||||
{1: 1},
|
||||
{"中文": 1},
|
||||
{"%$#": ["a"]},
|
||||
{"a".join("a" for i in range(256)): "a"}
|
||||
]
|
||||
|
||||
get_dict_without_host_port = [
|
||||
{"host": "host"},
|
||||
{"port": "port"},
|
||||
|
@ -158,6 +173,7 @@ class CheckTasks:
|
|||
check_partition_property = "check_partition_property"
|
||||
check_search_results = "check_search_results"
|
||||
check_query_results = "check_query_results"
|
||||
check_distance = "check_distance"
|
||||
|
||||
|
||||
class CaseLabel:
|
||||
|
|
|
@ -199,6 +199,11 @@ def get_invalid_partition_name(request):
|
|||
yield request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=ct.get_invalid_dict)
|
||||
def get_invalid_vector_dict(request):
|
||||
yield request.param
|
||||
|
||||
|
||||
# for test exit in the future
|
||||
# @pytest.hookimpl(hookwrapper=True, tryfirst=True)
|
||||
# def pytest_runtest_makereport():
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[pytest]
|
||||
|
||||
|
||||
addopts = --host localhost --html=/tmp/ci_logs/report.html --self-contained-html -v -x
|
||||
addopts = --host localhost --html=/tmp/ci_logs/report.html --self-contained-html -v
|
||||
# -;addopts = --host 172.28.255.155 --html=/tmp/report.html
|
||||
# python3 -W ignore -m pytest
|
||||
|
||||
|
|
|
@ -525,6 +525,43 @@ class TestCollectionSearchInvalid(TestcaseBase):
|
|||
check_items={"err_code": 1,
|
||||
"err_msg": "PartitonName: %s not found" % deleted_par_name})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6731")
|
||||
@pytest.mark.parametrize("index, params",
|
||||
zip(ct.all_index_types[:9],
|
||||
ct.default_index_params[:9]))
|
||||
def test_search_different_index_invalid_params(self, nq, dim, index, params, auto_id, _async):
|
||||
"""
|
||||
target: test search with different index
|
||||
method: test search with different index
|
||||
expected: searched successfully
|
||||
"""
|
||||
# 1. initialize with data
|
||||
collection_w, _, _, insert_ids = self.init_collection_general(prefix, True, 5000,
|
||||
partition_num=1,
|
||||
auto_id=auto_id,
|
||||
dim=dim, is_index=True)
|
||||
vectors = [[random.random() for _ in range(dim)] for _ in range(nq)]
|
||||
# 2. create different index
|
||||
if params.get("m"):
|
||||
if (dim % params["m"]) != 0:
|
||||
params["m"] = dim//4
|
||||
log.info("test_search_different_index_invalid_params: Creating index-%s" % index)
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "L2"}
|
||||
collection_w.create_index("float_vector", default_index)
|
||||
log.info("test_search_different_index_invalid_params: Created index-%s" % index)
|
||||
collection_w.load()
|
||||
# 3. search
|
||||
log.info("test_search_different_index_invalid_params: Searching after creating index-%s" % index)
|
||||
collection_w.search(vectors[:nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp, _async=_async,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": nq,
|
||||
"ids": insert_ids,
|
||||
"limit": default_limit,
|
||||
"_async": _async})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_search_index_partition_not_existed(self):
|
||||
"""
|
||||
|
@ -902,6 +939,7 @@ class TestCollectionSearch(TestcaseBase):
|
|||
"_async": _async})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6997")
|
||||
def test_search_partition_after_release_load(self, nb, nq, dim, auto_id, _async):
|
||||
"""
|
||||
target: search the pre-released collection after load
|
||||
|
@ -1044,44 +1082,6 @@ class TestCollectionSearch(TestcaseBase):
|
|||
"_async": _async})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6731")
|
||||
@pytest.mark.parametrize("index, params",
|
||||
zip(ct.all_index_types[:9],
|
||||
ct.default_index_params[:9]))
|
||||
def test_search_after_different_index(self, nq, dim, index, params, auto_id, _async):
|
||||
"""
|
||||
target: test search with different index
|
||||
method: test search with different index
|
||||
expected: searched successfully
|
||||
"""
|
||||
# 1. initialize with data
|
||||
collection_w, _, _, insert_ids = self.init_collection_general(prefix, True, 5000,
|
||||
partition_num=1,
|
||||
auto_id=auto_id,
|
||||
dim=dim, is_index=True)
|
||||
vectors = [[random.random() for _ in range(dim)] for _ in range(nq)]
|
||||
# 2. create different index
|
||||
if params.get("m"):
|
||||
if (dim % params["m"]) != 0:
|
||||
params["m"] = dim//4
|
||||
log.info("test_search_after_different_index: Creating index-%s" % index)
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "L2"}
|
||||
collection_w.create_index("float_vector", default_index)
|
||||
log.info("test_search_after_different_index: Created index-%s" % index)
|
||||
collection_w.load()
|
||||
# 3. search
|
||||
log.info("test_search_after_different_index: Searching after creating index-%s" % index)
|
||||
collection_w.search(vectors[:nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp, _async=_async,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": nq,
|
||||
"ids": insert_ids,
|
||||
"limit": default_limit,
|
||||
"_async": _async})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6731")
|
||||
@pytest.mark.parametrize("index, params",
|
||||
zip(ct.all_index_types[:9],
|
||||
ct.default_index_params[:9]))
|
||||
|
@ -1100,6 +1100,9 @@ class TestCollectionSearch(TestcaseBase):
|
|||
if params.get("m"):
|
||||
if (dim % params["m"]) != 0:
|
||||
params["m"] = dim//4
|
||||
if params.get("PQM"):
|
||||
if (dim % params["PQM"]) != 0:
|
||||
params["PQM"] = dim//4
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "L2"}
|
||||
collection_w.create_index("float_vector", default_index)
|
||||
collection_w.load()
|
||||
|
@ -1118,11 +1121,10 @@ class TestCollectionSearch(TestcaseBase):
|
|||
"_async": _async})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6731")
|
||||
@pytest.mark.parametrize("index, params",
|
||||
zip(ct.all_index_types[:9],
|
||||
ct.default_index_params[:9]))
|
||||
def test_search_after_index_different_metric_type(self, nq, dim, index, params, auto_id, _async):
|
||||
def test_search_after_index_different_metric_type(self, dim, index, params, auto_id, _async):
|
||||
"""
|
||||
target: test search with different metric type
|
||||
method: test search with different metric type
|
||||
|
@ -1133,11 +1135,13 @@ class TestCollectionSearch(TestcaseBase):
|
|||
partition_num=1,
|
||||
auto_id=auto_id,
|
||||
dim=dim, is_index=True)
|
||||
vectors = [[random.random() for _ in range(dim)] for _ in range(nq)]
|
||||
# 2. create different index
|
||||
if params.get("m"):
|
||||
if (dim % params["m"]) != 0:
|
||||
params["m"] = dim//4
|
||||
if params.get("PQM"):
|
||||
if (dim % params["PQM"]) != 0:
|
||||
params["PQM"] = dim//4
|
||||
log.info("test_search_after_index_different_metric_type: Creating index-%s" % index)
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "IP"}
|
||||
collection_w.create_index("float_vector", default_index)
|
||||
|
@ -1145,6 +1149,7 @@ class TestCollectionSearch(TestcaseBase):
|
|||
collection_w.load()
|
||||
# 3. search
|
||||
search_params = cf.gen_search_param(index, "IP")
|
||||
vectors = [[random.random() for _ in range(dim)] for _ in range(default_nq)]
|
||||
for search_param in search_params:
|
||||
log.info("Searching with search params: {}".format(search_param))
|
||||
collection_w.search(vectors[:default_nq], default_search_field,
|
||||
|
@ -1465,7 +1470,6 @@ class TestCollectionSearch(TestcaseBase):
|
|||
assert abs(res[0]._distances[0] - min(distance_0, distance_1)) <= epsilon
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 6569")
|
||||
def test_search_binary_tanimoto_flat_index(self, nq, dim, auto_id, _async):
|
||||
"""
|
||||
target: search binary_collection, and check the result: distance
|
||||
|
|
|
@ -8,14 +8,16 @@ from common.common_type import CaseLabel, CheckTasks
|
|||
|
||||
prefix = "utility"
|
||||
default_schema = cf.gen_default_collection_schema()
|
||||
default_int64_field_name = ct.default_int64_field_name
|
||||
default_field_name = ct.default_float_vec_field_name
|
||||
default_index_params = {"index_type": "IVF_SQ8", "metric_type": "L2", "params": {"nlist": 64}}
|
||||
default_dim = ct.default_dim
|
||||
default_nb = ct.default_nb
|
||||
|
||||
|
||||
class TestUtilityParams(TestcaseBase):
|
||||
""" Test case of index interface """
|
||||
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_has_collection_name_invalid(self, get_invalid_collection_name):
|
||||
"""
|
||||
|
@ -139,10 +141,126 @@ class TestUtilityParams(TestcaseBase):
|
|||
log.error(str(ex))
|
||||
assert "invalid" or "illegal" in str(ex)
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_left_vector_invalid_type(self, get_invalid_vector_dict):
|
||||
"""
|
||||
target: test calculated distance with invalid vectors
|
||||
method: input invalid vectors type
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
invalid_vector = get_invalid_vector_dict
|
||||
if not isinstance(invalid_vector, dict):
|
||||
self.utility_wrap.calc_distance(invalid_vector, invalid_vector,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "Left vectors array is invalid"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
@pytest.mark.xfail(reason="issue 7038")
|
||||
def test_calc_distance_left_vector_invalid_value(self, get_invalid_vector_dict):
|
||||
"""
|
||||
target: test calculated distance with invalid vectors
|
||||
method: input invalid vectors value
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
invalid_vector = get_invalid_vector_dict
|
||||
if isinstance(invalid_vector, dict):
|
||||
self.utility_wrap.calc_distance(invalid_vector, invalid_vector,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "Left vectors array is empty"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_right_vector_invalid_type(self, get_invalid_vector_dict):
|
||||
"""
|
||||
target: test calculated distance with invalid vectors
|
||||
method: input invalid vectors type
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
invalid_vector = get_invalid_vector_dict
|
||||
vector = cf.gen_vectors(default_nb, default_dim)
|
||||
op_l = {"float_vectors": vector}
|
||||
if not isinstance(invalid_vector, dict):
|
||||
self.utility_wrap.calc_distance(op_l, invalid_vector,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "Right vectors array is invalid"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_right_vector_invalid_value(self, get_invalid_vector_dict):
|
||||
"""
|
||||
target: test calculated distance with invalid vectors
|
||||
method: input invalid vectors value
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
invalid_vector = get_invalid_vector_dict
|
||||
vector = cf.gen_vectors(default_nb, default_dim)
|
||||
op_l = {"float_vectors": vector}
|
||||
if isinstance(invalid_vector, dict):
|
||||
self.utility_wrap.calc_distance(op_l, invalid_vector,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "Cannot calculate distance between "
|
||||
"vectors with different dimension"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_invalid_using(self):
|
||||
"""
|
||||
target: test calculated distance with invalid using
|
||||
method: input invalid using
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
vectors_l = cf.gen_vectors(5, 64)
|
||||
vectors_r = cf.gen_vectors(10, 64)
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
params = {"metric": "L2", "sqrt": True}
|
||||
using = "empty"
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params, using=using,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "should create connect"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_not_match_dim(self):
|
||||
"""
|
||||
target: test calculated distance with invalid vectors
|
||||
method: input invalid vectors type and value
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
dim = 129
|
||||
vector_l = cf.gen_vectors(default_nb, default_dim)
|
||||
vector_r = cf.gen_vectors(default_nb, dim)
|
||||
op_l = {"float_vectors": vector_l}
|
||||
op_r = {"float_vectors": vector_r}
|
||||
ut = ApiUtilityWrapper()
|
||||
ut.calc_distance(op_l, op_r,
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={"err_code": 1,
|
||||
"err_msg": "Cannot calculate distance between "
|
||||
"vectors with different dimension"})
|
||||
|
||||
class TestUtilityBase(TestcaseBase):
|
||||
""" Test case of index interface """
|
||||
|
||||
@pytest.fixture(scope="function", params=[True, False])
|
||||
def sqrt(self, request):
|
||||
yield request.param
|
||||
|
||||
@pytest.fixture(scope="function", params=["L2", "IP"])
|
||||
def metric(self, request):
|
||||
yield request.param
|
||||
|
||||
@pytest.fixture(scope="function", params=["HAMMING", "TANIMOTO", "JACCARD"])
|
||||
def metric_binary(self, request):
|
||||
yield request.param
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_has_collection(self):
|
||||
"""
|
||||
|
@ -386,6 +504,299 @@ class TestUtilityBase(TestcaseBase):
|
|||
res, _ = self.utility_wrap.index_building_progress(c_name)
|
||||
assert res["indexed_rows"] == nb
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_default(self):
|
||||
"""
|
||||
target: test calculated distance with default params
|
||||
method: calculated distance between two random vectors
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
vectors_l = cf.gen_vectors(default_nb, default_dim)
|
||||
vectors_r = cf.gen_vectors(default_nb, default_dim)
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
self.utility_wrap.calc_distance(op_l, op_r,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_default_sqrt(self, metric):
|
||||
"""
|
||||
target: test calculated distance with default param
|
||||
method: calculated distance with default sqrt
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
vectors_l = cf.gen_vectors(default_nb, default_dim)
|
||||
vectors_r = cf.gen_vectors(default_nb, default_dim)
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
params = {"metric": metric}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_default_metric(self, sqrt):
|
||||
"""
|
||||
target: test calculated distance with default param
|
||||
method: calculated distance with default metric
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
vectors_l = cf.gen_vectors(default_nb, default_dim)
|
||||
vectors_r = cf.gen_vectors(default_nb, default_dim)
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
params = {"sqrt": sqrt}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 7064")
|
||||
def test_calc_distance_binary_metric(self, metric_binary):
|
||||
"""
|
||||
target: test calculate distance with binary vectors
|
||||
method: calculate distance between binary vectors
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
raw_vectors_l, vectors_l = cf.gen_binary_vectors(nb, default_dim)
|
||||
raw_vectors_r, vectors_r = cf.gen_binary_vectors(nb, default_dim)
|
||||
op_l = {"bin_vectors": vectors_l}
|
||||
op_r = {"bin_vectors": vectors_r}
|
||||
params = {"metric": metric_binary}
|
||||
if metric_binary == "HAMMING":
|
||||
vectors_l = raw_vectors_l
|
||||
vectors_r = raw_vectors_r
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric_binary})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_calc_distance_from_collection_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance from collection entities
|
||||
method: both left and right vectors are from collection
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb)
|
||||
middle = len(insert_ids) // 2
|
||||
vectors = vectors[0].loc[:, default_field_name]
|
||||
vectors_l = vectors[:middle]
|
||||
vectors_r = []
|
||||
for i in range(middle):
|
||||
vectors_r.append(vectors[middle+i])
|
||||
op_l = {"ids": insert_ids[:middle], "collection": collection_w.name,
|
||||
"field": default_field_name}
|
||||
op_r = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"field": default_field_name}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_from_collections(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance between entities from collections
|
||||
method: calculated distance between entities from two collections
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
prefix_1 = "utility_distance"
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb)
|
||||
collection_w_1, vectors_1, _, insert_ids_1 = self.init_collection_general(prefix_1, True, nb)
|
||||
vectors_l = vectors[0].loc[:, default_field_name]
|
||||
vectors_r = vectors_1[0].loc[:, default_field_name]
|
||||
op_l = {"ids": insert_ids, "collection": collection_w.name,
|
||||
"field": default_field_name}
|
||||
op_r = {"ids": insert_ids_1, "collection": collection_w_1.name,
|
||||
"field": default_field_name}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_left_vector_and_collection_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance from collection entities
|
||||
method: set left vectors as random vectors, right vectors from collection
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb)
|
||||
middle = len(insert_ids) // 2
|
||||
vectors = vectors[0].loc[:, default_field_name]
|
||||
vectors_l = cf.gen_vectors(nb, default_dim)
|
||||
vectors_r = []
|
||||
for i in range(middle):
|
||||
vectors_r.append(vectors[middle + i])
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
op_r = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"field": default_field_name}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_calc_distance_right_vector_and_collection_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance from collection entities
|
||||
method: set right vectors as random vectors, left vectors from collection
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb)
|
||||
middle = len(insert_ids) // 2
|
||||
vectors = vectors[0].loc[:, default_field_name]
|
||||
vectors_l = vectors[:middle]
|
||||
vectors_r = cf.gen_vectors(nb, default_dim)
|
||||
op_l = {"ids": insert_ids[:middle], "collection": collection_w.name,
|
||||
"field": default_field_name}
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 7046")
|
||||
def test_calc_distance_from_partition_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance from one partition entities
|
||||
method: both left and right vectors are from partition
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb, partition_num=1)
|
||||
partitions = collection_w.partitions
|
||||
middle = len(insert_ids) // 2
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
for i in range(len(partitions)):
|
||||
vectors_l = vectors[i].loc[:, default_field_name]
|
||||
vectors_r = vectors[i].loc[:, default_field_name]
|
||||
op_l = {"ids": insert_ids[:middle], "collection": collection_w.name,
|
||||
"partition": partitions[i].name, "field": default_field_name}
|
||||
op_r = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"partition": partitions[i].name, "field": default_field_name}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 7046")
|
||||
def test_calc_distance_from_partitions(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance between entities from partitions
|
||||
method: calculate distance between entities from two partitions
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb, partition_num=1)
|
||||
partitions = collection_w.partitions
|
||||
middle = len(insert_ids) // 2
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
vectors_l = vectors[0].loc[:, default_field_name]
|
||||
vectors_r = vectors[1].loc[:, default_field_name]
|
||||
op_l = {"ids": insert_ids[:middle], "collection": collection_w.name,
|
||||
"partition": partitions[0].name, "field": default_field_name}
|
||||
op_r = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"partition": partitions[1].name, "field": default_field_name}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 7046")
|
||||
def test_calc_distance_left_vectors_and_partition_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance between vectors and partition entities
|
||||
method: set left vectors as random vectors, right vectors are entities
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb, partition_num=1)
|
||||
middle = len(insert_ids) // 2
|
||||
partitions = collection_w.partitions
|
||||
vectors_l = cf.gen_vectors(nb // 2, default_dim)
|
||||
op_l = {"float_vectors": vectors_l}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
for i in range(len(partitions)):
|
||||
vectors_r = vectors[i].loc[:, default_field_name]
|
||||
op_r = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"partition": partitions[i].name, "field": default_field_name}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.xfail(reason="issue 7046")
|
||||
def test_calc_distance_right_vectors_and_partition_ids(self, metric, sqrt):
|
||||
"""
|
||||
target: test calculated distance between vectors and partition entities
|
||||
method: set right vectors as random vectors, left vectors are entities
|
||||
expected: distance calculated successfully
|
||||
"""
|
||||
self._connect()
|
||||
nb = 10
|
||||
collection_w, vectors, _, insert_ids = self.init_collection_general(prefix, True, nb, partition_num=1)
|
||||
middle = len(insert_ids) // 2
|
||||
partitions = collection_w.partitions
|
||||
vectors_r = cf.gen_vectors(nb // 2, default_dim)
|
||||
op_r = {"float_vectors": vectors_r}
|
||||
params = {"metric": metric, "sqrt": sqrt}
|
||||
for i in range(len(partitions)):
|
||||
vectors_l = vectors[i].loc[:, default_field_name]
|
||||
op_l = {"ids": insert_ids[middle:], "collection": collection_w.name,
|
||||
"partition": partitions[i].name, "field": default_field_name}
|
||||
self.utility_wrap.calc_distance(op_l, op_r, params,
|
||||
check_task=CheckTasks.check_distance,
|
||||
check_items={"vectors_l": vectors_l,
|
||||
"vectors_r": vectors_r,
|
||||
"metric": metric,
|
||||
"sqrt": sqrt})
|
||||
|
||||
class TestUtilityAdvanced(TestcaseBase):
|
||||
""" Test case of index interface """
|
||||
|
|
Loading…
Reference in New Issue