Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: [cherry-pick]add restful api case #38978

Open
wants to merge 1 commit into
base: 2.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 98 additions & 1 deletion tests/restful_client_v2/api/milvus.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,17 @@ def __init__(self, endpoint, token):
self.name_list = []
self.headers = self.update_headers()

def wait_load_completed(self, collection_name, db_name="default", timeout=5):
t0 = time.time()
while True and time.time() - t0 < timeout:
rsp = self.collection_describe(collection_name, db_name=db_name)
if "data" in rsp and "load" in rsp["data"] and rsp["data"]["load"] == "LoadStateLoaded":
logger.info(f"collection {collection_name} load completed in {time.time() - t0} seconds")
break
else:
time.sleep(1)


@classmethod
def update_headers(cls, headers=None):
if headers is not None:
Expand Down Expand Up @@ -479,6 +490,92 @@ def collection_drop(self, payload, db_name="default"):
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def refresh_load(self, collection_name, db_name="default"):
"""Refresh load collection"""
url = f"{self.endpoint}/v2/vectordb/collections/refresh_load"
payload = {
"collectionName": collection_name
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def alter_collection_properties(self, collection_name, properties, db_name="default"):
"""Alter collection properties"""
url = f"{self.endpoint}/v2/vectordb/collections/alter_properties"
payload = {
"collectionName": collection_name,
"properties": properties
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def drop_collection_properties(self, collection_name, delete_keys, db_name="default"):
"""Drop collection properties"""
url = f"{self.endpoint}/v2/vectordb/collections/drop_properties"
payload = {
"collectionName": collection_name,
"deleteKeys": delete_keys
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def alter_field_properties(self, collection_name, field_name, field_params, db_name="default"):
"""Alter field properties"""
url = f"{self.endpoint}/v2/vectordb/collections/fields/alter_properties"
payload = {
"collectionName": collection_name,
"fieldName": field_name,
"fieldParams": field_params
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def alter_index_properties(self, collection_name, index_name, properties, db_name="default"):
"""Alter index properties"""
url = f"{self.endpoint}/v2/vectordb/indexes/alter_properties"
payload = {
"collectionName": collection_name,
"indexName": index_name,
"properties": properties
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()

def drop_index_properties(self, collection_name, index_name, delete_keys, db_name="default"):
"""Drop index properties"""
url = f"{self.endpoint}/v2/vectordb/indexes/drop_properties"
payload = {
"collectionName": collection_name,
"indexName": index_name,
"deleteKeys": delete_keys
}
if self.db_name is not None:
payload["dbName"] = self.db_name
if db_name != "default":
payload["dbName"] = db_name
response = self.post(url, headers=self.update_headers(), data=payload)
return response.json()


class PartitionClient(Requests):

Expand Down Expand Up @@ -748,7 +845,7 @@ def index_create(self, payload, db_name="default"):
res = response.json()
return res

def index_describe(self, db_name="default", collection_name=None, index_name=None):
def index_describe(self, collection_name=None, index_name=None, db_name="default",):
url = f'{self.endpoint}/v2/vectordb/indexes/describe'
if self.db_name is not None:
db_name = self.db_name
Expand Down
152 changes: 152 additions & 0 deletions tests/restful_client_v2/testcases/test_collection_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1406,3 +1406,155 @@ def test_create_collections_with_invalid_api_key(self):
}
rsp = client.collection_create(payload)
assert rsp['code'] == 1800


@pytest.mark.L0
class TestCollectionProperties(TestBase):
"""Test collection property operations"""

def test_refresh_load_collection(self):
"""
target: test refresh load collection
method: create collection, refresh load
expected: refresh load success
"""
name = gen_collection_name()
dim = 128
client = self.collection_client
payload = {
"collectionName": name,
"dimension": dim,
}
rsp = client.collection_create(payload)
assert rsp['code'] == 0

# release collection
client.collection_release(collection_name=name)
# load collection
client.collection_load(collection_name=name)
client.wait_load_completed(collection_name=name)
# refresh load
rsp = client.refresh_load(collection_name=name)

assert rsp['code'] == 0

def test_alter_collection_properties(self):
"""
target: test alter collection properties
method: create collection, alter properties
expected: alter properties success
"""
name = gen_collection_name()
dim = 128
client = self.collection_client
payload = {
"collectionName": name,
"dimension": dim,
}
rsp = client.collection_create(payload)
assert rsp['code'] == 0
client.collection_release(collection_name=name)
# alter properties
properties = {"mmap.enabled": "true"}
rsp = client.alter_collection_properties(name, properties)
assert rsp['code'] == 0
rsp = client.collection_describe(name)
enabled_mmap = False
for prop in rsp['data']['properties']:
if prop['key'] == "mmap.enabled":
assert prop['value'] == "true"
enabled_mmap = True
assert enabled_mmap

def test_drop_collection_properties(self):
"""
target: test drop collection properties
method: create collection, alter properties, drop properties
expected: drop properties success
"""
name = gen_collection_name()
dim = 128
client = self.collection_client
payload = {
"collectionName": name,
"dimension": dim,
}
rsp = client.collection_create(payload)
assert rsp['code'] == 0
client.collection_release(collection_name=name)

# alter properties
properties = {"mmap.enabled": "true"}
rsp = client.alter_collection_properties(name, properties)
assert rsp['code'] == 0
rsp = client.collection_describe(name)
enabled_mmap = False
for prop in rsp['data']['properties']:
if prop['key'] == "mmap.enabled":
assert prop['value'] == "true"
enabled_mmap = True
assert enabled_mmap

# drop properties
delete_keys = ["mmap.enabled"]
rsp = client.drop_collection_properties(name, delete_keys)
assert rsp['code'] == 0
rsp = client.collection_describe(name)
enabled_mmap = False
for prop in rsp['data']['properties']:
if prop['key'] == "mmap.enabled":
enabled_mmap = True
assert not enabled_mmap

def test_alter_field_properties(self):
"""
target: test alter field properties
method: create collection with varchar field, alter field properties
expected: alter field properties success
"""
name = gen_collection_name()
dim = 128
client = self.collection_client
payload = {
"collectionName": name,
"schema": {
"autoId": True,
"enableDynamicField": True,
"fields": [
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": True, "elementTypeParams": {}},
{"fieldName": "user_id", "dataType": "Int64", "isPartitionKey": True,
"elementTypeParams": {}},
{"fieldName": "word_count", "dataType": "Int64", "elementTypeParams": {}},
{"fieldName": "book_describe", "dataType": "VarChar", "elementTypeParams": {"max_length": "256"}},
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": f"{dim}"}},
{"fieldName": "image_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": f"{dim}"}},
]
}
}
rsp = client.collection_create(payload)
assert rsp['code'] == 0
# release collection
client.collection_release(collection_name=name)

# describe collection
rsp = client.collection_describe(name)
for field in rsp['data']['fields']:
if field['name'] == "book_describe":
for p in field['params']:
if p['key'] == "max_length":
assert p['value'] == "256"

# alter field properties
field_params = {"max_length": "100"}
rsp = client.alter_field_properties(name, "book_describe", field_params)
assert rsp['code'] == 0

# describe collection
rsp = client.collection_describe(name)
for field in rsp['data']['fields']:
if field['name'] == "book_describe":
for p in field['params']:
if p['key'] == "max_length":
assert p['value'] == "100"