Skip to content

Commit 3447cfb

Browse files
authored
Merge branch 'main' into secure_sign_model
2 parents 4d80397 + 46c50a4 commit 3447cfb

63 files changed

Lines changed: 379 additions & 255 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ dependencies = [
7373
"marshmallow==3.26.2,<4", # this version is needed for pytest-jira
7474
"pytest-html>=4.1.1",
7575
"fire",
76-
"llama_stack_client>=0.5.0,<0.6",
76+
"llama_stack_client>=0.6.0,<0.7",
7777
"pytest-xdist==3.8.0",
7878
"dictdiffer>=0.9.0",
7979
"pytest>=9.0.0",

tests/model_registry/mcp_servers/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
CALCULATOR_SERVER_NAME: str = "calculator"
2+
CALCULATOR_PROVIDER: str = "Math Community"
13
MCP_CATALOG_SOURCE_ID: str = "test_mcp_servers"
24
MCP_CATALOG_SOURCE_NAME: str = "Test MCP Servers"
35
MCP_CATALOG_API_PATH: str = "/api/mcp_catalog/v1alpha1/"

tests/model_serving/model_server/kserve/components/__init__.py renamed to tests/model_registry/mcp_servers/search/__init__.py

File renamed without changes.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from typing import Self
2+
3+
import pytest
4+
from simple_logger.logger import get_logger
5+
6+
from tests.model_registry.mcp_servers.constants import CALCULATOR_PROVIDER, CALCULATOR_SERVER_NAME
7+
from tests.model_registry.utils import execute_get_command
8+
9+
LOGGER = get_logger(name=__name__)
10+
11+
12+
@pytest.mark.usefixtures("mcp_servers_configmap_patch")
13+
class TestMCPServerFiltering:
14+
"""RHOAIENG-51584: Tests for MCP server filterQuery functionality."""
15+
16+
@pytest.mark.parametrize(
17+
"filter_query, expected_count, expected_name, field_check",
18+
[
19+
pytest.param(
20+
f"provider='{CALCULATOR_PROVIDER}'",
21+
1,
22+
CALCULATOR_SERVER_NAME,
23+
("provider", CALCULATOR_PROVIDER),
24+
id="by_provider",
25+
),
26+
pytest.param("tags='math'", 1, CALCULATOR_SERVER_NAME, None, id="by_tags"),
27+
],
28+
)
29+
def test_filter_by_field(
30+
self: Self,
31+
mcp_catalog_rest_urls: list[str],
32+
model_registry_rest_headers: dict[str, str],
33+
filter_query: str,
34+
expected_count: int,
35+
expected_name: str,
36+
field_check: tuple[str, str] | None,
37+
):
38+
"""TC-API-003, TC-API-005: Test filtering MCP servers by provider and tags."""
39+
response = execute_get_command(
40+
url=f"{mcp_catalog_rest_urls[0]}mcp_servers",
41+
headers=model_registry_rest_headers,
42+
params={"filterQuery": filter_query},
43+
)
44+
items = response.get("items", [])
45+
assert len(items) == expected_count, (
46+
f"Expected {expected_count} server(s) for '{filter_query}', got {len(items)}"
47+
)
48+
assert items[0]["name"] == expected_name
49+
if field_check:
50+
assert items[0][field_check[0]] == field_check[1]
51+
52+
def test_filter_options(
53+
self: Self,
54+
mcp_catalog_rest_urls: list[str],
55+
model_registry_rest_headers: dict[str, str],
56+
):
57+
"""TC-API-026: Test that filter_options endpoint returns available filter fields."""
58+
url = f"{mcp_catalog_rest_urls[0]}mcp_servers/filter_options"
59+
LOGGER.info(f"Requesting filter_options from: {url}")
60+
61+
response = execute_get_command(
62+
url=url,
63+
headers=model_registry_rest_headers,
64+
)
65+
LOGGER.info(f"filter_options full response: {response}")
66+
67+
filters = response["filters"]
68+
69+
expected_filter_fields = {"description", "provider", "license", "tags"}
70+
actual_filter_fields = set(filters.keys())
71+
assert expected_filter_fields == actual_filter_fields
72+
73+
def test_pagination_with_filters(
74+
self: Self,
75+
mcp_catalog_rest_urls: list[str],
76+
model_registry_rest_headers: dict[str, str],
77+
):
78+
"""TC-API-032: Test that pagination works correctly with filterQuery."""
79+
base_url = f"{mcp_catalog_rest_urls[0]}mcp_servers"
80+
filter_query = "license='MIT'"
81+
82+
# First page
83+
response = execute_get_command(
84+
url=base_url,
85+
headers=model_registry_rest_headers,
86+
params={"filterQuery": filter_query, "pageSize": "1"},
87+
)
88+
first_page_items = response.get("items", [])
89+
assert len(first_page_items) == 1, f"Expected 1 item on first page, got {len(first_page_items)}"
90+
next_page_token = response.get("nextPageToken")
91+
assert next_page_token, "Expected nextPageToken for second page"
92+
93+
# Second page
94+
response = execute_get_command(
95+
url=base_url,
96+
headers=model_registry_rest_headers,
97+
params={"filterQuery": filter_query, "pageSize": "1", "nextPageToken": next_page_token},
98+
)
99+
second_page_items = response.get("items", [])
100+
assert len(second_page_items) == 1, f"Expected 1 item on second page, got {len(second_page_items)}"
101+
102+
collected_names = {first_page_items[0]["name"], second_page_items[0]["name"]}
103+
assert collected_names == {"weather-api", CALCULATOR_SERVER_NAME}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from typing import Self
2+
3+
import pytest
4+
from simple_logger.logger import get_logger
5+
6+
from tests.model_registry.utils import execute_get_command
7+
8+
LOGGER = get_logger(name=__name__)
9+
10+
11+
@pytest.mark.usefixtures("mcp_servers_configmap_patch")
12+
class TestMCPServerOrdering:
13+
"""RHOAIENG-51584: Tests for MCP server ordering functionality."""
14+
15+
@pytest.mark.xfail(reason="RHOAIENG-52448: sortOrder/orderBy not working, fix in PR #2367")
16+
@pytest.mark.parametrize(
17+
"sort_order",
18+
[
19+
pytest.param("ASC", id="ascending"),
20+
pytest.param("DESC", id="descending"),
21+
],
22+
)
23+
def test_ordering_by_name(
24+
self: Self,
25+
mcp_catalog_rest_urls: list[str],
26+
model_registry_rest_headers: dict[str, str],
27+
sort_order: str,
28+
):
29+
"""TC-API-014: Test ordering MCP servers by name ASC/DESC."""
30+
response = execute_get_command(
31+
url=f"{mcp_catalog_rest_urls[0]}mcp_servers",
32+
headers=model_registry_rest_headers,
33+
params={"orderBy": "name", "sortOrder": sort_order},
34+
)
35+
actual_names = [s["name"] for s in response.get("items", [])]
36+
expected_names = sorted(actual_names, reverse=(sort_order == "DESC"))
37+
assert actual_names == expected_names

tests/model_serving/model_runtime/image_validation/test_verify_serving_runtime_images.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@
2020

2121
LOGGER = get_logger(name=__name__)
2222

23-
pytestmark = [
24-
pytest.mark.downstream_only,
25-
pytest.mark.skip_must_gather,
26-
pytest.mark.smoke,
27-
]
23+
pytestmark = [pytest.mark.downstream_only, pytest.mark.skip_must_gather, pytest.mark.smoke]
2824

2925

3026
@pytest.mark.parametrize("serving_runtime_pods_for_runtime", RUNTIME_CONFIGS, indirect=True)

tests/model_serving/model_runtime/mlserver/basic_model_deployment/test_mlserver_basic_model_deployment.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
pytestmark = pytest.mark.usefixtures("valid_aws_config")
2828

2929

30-
@pytest.mark.smoke
3130
@pytest.mark.parametrize(
3231
(
3332
"model_namespace",
@@ -50,6 +49,7 @@
5049
model_format_name=ModelFormat.LIGHTGBM,
5150
deployment_type=RAW_DEPLOYMENT_TYPE,
5251
),
52+
marks=pytest.mark.tier1,
5353
),
5454
pytest.param(
5555
get_model_namespace_dict(
@@ -64,6 +64,7 @@
6464
model_format_name=ModelFormat.ONNX,
6565
deployment_type=RAW_DEPLOYMENT_TYPE,
6666
),
67+
marks=pytest.mark.tier1,
6768
),
6869
pytest.param(
6970
get_model_namespace_dict(
@@ -78,6 +79,7 @@
7879
model_format_name=ModelFormat.SKLEARN,
7980
deployment_type=RAW_DEPLOYMENT_TYPE,
8081
),
82+
marks=pytest.mark.smoke,
8183
),
8284
pytest.param(
8385
get_model_namespace_dict(
@@ -92,6 +94,7 @@
9294
model_format_name=ModelFormat.XGBOOST,
9395
deployment_type=RAW_DEPLOYMENT_TYPE,
9496
),
97+
marks=pytest.mark.tier1,
9598
),
9699
],
97100
indirect=[

tests/model_serving/model_runtime/openvino/test_ovms_model_deployment.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
pytestmark = pytest.mark.usefixtures("valid_aws_config")
3333

3434

35-
@pytest.mark.smoke
3635
@pytest.mark.parametrize(
3736
(
3837
"protocol",
@@ -59,6 +58,7 @@
5958
deployment_type=RAW_DEPLOYMENT_TYPE,
6059
protocol_type=Protocols.REST,
6160
),
61+
marks=pytest.mark.smoke,
6262
),
6363
pytest.param(
6464
REST_PROTOCOL_TYPE_DICT,
@@ -76,6 +76,7 @@
7676
deployment_type=RAW_DEPLOYMENT_TYPE,
7777
protocol_type=Protocols.REST,
7878
),
79+
marks=pytest.mark.tier1,
7980
),
8081
pytest.param(
8182
REST_PROTOCOL_TYPE_DICT,
@@ -93,6 +94,7 @@
9394
deployment_type=RAW_DEPLOYMENT_TYPE,
9495
protocol_type=Protocols.REST,
9596
),
97+
marks=pytest.mark.tier1,
9698
),
9799
],
98100
indirect=[

tests/model_serving/model_runtime/openvino/test_ovms_smoke.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
from ocp_resources.pod import Pod
2020

2121

22-
@pytest.mark.smoke
2322
@pytest.mark.parametrize(
2423
"model_namespace",
25-
[pytest.param({"name": "ovms-smoke"}, id="ovms-smoke")],
24+
[pytest.param({"name": "ovms-smoke"}, id="ovms-smoke", marks=pytest.mark.smoke)],
2625
indirect=["model_namespace"],
2726
)
2827
class TestOVMSSmokeInOpenShift:

tests/model_serving/model_runtime/triton/basic_model_deployment/test_dali_model.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
)
3131

3232

33-
@pytest.mark.gpu
3433
@pytest.mark.parametrize(
3534
("protocol", "model_namespace", "s3_models_storage_uri", "triton_serving_runtime", "triton_inference_service"),
3635
[
@@ -44,6 +43,7 @@
4443
**BASE_RAW_DEPLOYMENT_CONFIG,
4544
},
4645
id="dali-raw-rest-deployment",
46+
marks=[pytest.mark.tier1, pytest.mark.gpu],
4747
),
4848
pytest.param(
4949
{"protocol_type": Protocols.GRPC},
@@ -55,6 +55,7 @@
5555
**BASE_RAW_DEPLOYMENT_CONFIG,
5656
},
5757
id="dali-raw-grpc-deployment",
58+
marks=[pytest.mark.tier1, pytest.mark.gpu],
5859
),
5960
],
6061
indirect=True,

0 commit comments

Comments
 (0)