Skip to content

Commit c7a5f03

Browse files
authored
Merge pull request #512 from tisnik/lcore-636-split-config-unit-tests-
LCORE-636: split config unit tests
2 parents fe6b676 + 2eb441d commit c7a5f03

9 files changed

+744
-679
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
"""Unit tests for AuthenticationConfiguration model."""
2+
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from pydantic import ValidationError
8+
9+
from models.config import (
10+
AuthenticationConfiguration,
11+
Configuration,
12+
JwkConfiguration,
13+
LlamaStackConfiguration,
14+
ServiceConfiguration,
15+
UserDataCollection,
16+
)
17+
18+
from constants import (
19+
AUTH_MOD_NOOP,
20+
AUTH_MOD_K8S,
21+
AUTH_MOD_JWK_TOKEN,
22+
)
23+
24+
25+
def test_authentication_configuration() -> None:
26+
"""Test the AuthenticationConfiguration constructor."""
27+
28+
auth_config = AuthenticationConfiguration(
29+
module=AUTH_MOD_NOOP,
30+
skip_tls_verification=False,
31+
k8s_ca_cert_path=None,
32+
k8s_cluster_api=None,
33+
)
34+
assert auth_config is not None
35+
assert auth_config.module == AUTH_MOD_NOOP
36+
assert auth_config.skip_tls_verification is False
37+
assert auth_config.k8s_ca_cert_path is None
38+
assert auth_config.k8s_cluster_api is None
39+
40+
# try to retrieve JWK configuration
41+
with pytest.raises(
42+
ValueError,
43+
match="JWK configuration is only available for JWK token authentication module",
44+
):
45+
_ = auth_config.jwk_configuration
46+
47+
48+
def test_authentication_configuration_jwk_token() -> None:
49+
"""Test the AuthenticationConfiguration with JWK token."""
50+
51+
auth_config = AuthenticationConfiguration(
52+
module=AUTH_MOD_JWK_TOKEN,
53+
skip_tls_verification=False,
54+
k8s_ca_cert_path=None,
55+
k8s_cluster_api=None,
56+
jwk_config=JwkConfiguration(url="http://foo.bar.baz"),
57+
)
58+
assert auth_config is not None
59+
assert auth_config.module == AUTH_MOD_JWK_TOKEN
60+
assert auth_config.skip_tls_verification is False
61+
assert auth_config.k8s_ca_cert_path is None
62+
assert auth_config.k8s_cluster_api is None
63+
64+
# try to retrieve JWK configuration
65+
assert auth_config.jwk_configuration is not None
66+
67+
68+
def test_authentication_configuration_jwk_token_but_insufficient_config() -> None:
69+
"""Test the AuthenticationConfiguration with JWK token."""
70+
71+
with pytest.raises(ValidationError, match="JwkConfiguration"):
72+
AuthenticationConfiguration(
73+
module=AUTH_MOD_JWK_TOKEN,
74+
skip_tls_verification=False,
75+
k8s_ca_cert_path=None,
76+
k8s_cluster_api=None,
77+
jwk_config=JwkConfiguration(),
78+
)
79+
80+
81+
def test_authentication_configuration_jwk_token_but_not_config() -> None:
82+
"""Test the AuthenticationConfiguration with JWK token."""
83+
84+
with pytest.raises(
85+
ValidationError,
86+
match="Value error, JWK configuration must be specified when using JWK token",
87+
):
88+
AuthenticationConfiguration(
89+
module=AUTH_MOD_JWK_TOKEN,
90+
skip_tls_verification=False,
91+
k8s_ca_cert_path=None,
92+
k8s_cluster_api=None,
93+
# no JwkConfiguration
94+
)
95+
96+
97+
def test_authentication_configuration_jwk_broken_config() -> None:
98+
"""Test the AuthenticationConfiguration with JWK set, but not configured."""
99+
100+
auth_config = AuthenticationConfiguration(
101+
module=AUTH_MOD_JWK_TOKEN,
102+
skip_tls_verification=False,
103+
k8s_ca_cert_path=None,
104+
k8s_cluster_api=None,
105+
jwk_config=JwkConfiguration(url="http://foo.bar.baz"),
106+
)
107+
assert auth_config is not None
108+
109+
# emulate broken config
110+
auth_config.jwk_config = None
111+
# try to retrieve JWK configuration
112+
113+
with pytest.raises(ValueError, match="JWK configuration should not be None"):
114+
_ = auth_config.jwk_configuration
115+
116+
117+
def test_authentication_configuration_supported() -> None:
118+
"""Test the AuthenticationConfiguration constructor."""
119+
auth_config = AuthenticationConfiguration(
120+
module=AUTH_MOD_K8S,
121+
skip_tls_verification=False,
122+
k8s_ca_cert_path=None,
123+
k8s_cluster_api=None,
124+
)
125+
assert auth_config is not None
126+
assert auth_config.module == AUTH_MOD_K8S
127+
assert auth_config.skip_tls_verification is False
128+
assert auth_config.k8s_ca_cert_path is None
129+
assert auth_config.k8s_cluster_api is None
130+
131+
132+
def test_authentication_configuration_module_unsupported() -> None:
133+
"""Test the AuthenticationConfiguration constructor with module as None."""
134+
with pytest.raises(ValidationError, match="Unsupported authentication module"):
135+
AuthenticationConfiguration(
136+
module="non-existing-module",
137+
skip_tls_verification=False,
138+
k8s_ca_cert_path=None,
139+
k8s_cluster_api=None,
140+
)
141+
142+
143+
def test_authentication_configuration_in_config() -> None:
144+
"""Test the authentication configuration in main config."""
145+
cfg = Configuration(
146+
name="test_name",
147+
service=ServiceConfiguration(),
148+
llama_stack=LlamaStackConfiguration(
149+
use_as_library_client=True,
150+
library_client_config_path="tests/configuration/run.yaml",
151+
),
152+
user_data_collection=UserDataCollection(
153+
feedback_enabled=False, feedback_storage=None
154+
),
155+
mcp_servers=[],
156+
)
157+
assert cfg.authentication is not None
158+
assert cfg.authentication.module == AUTH_MOD_NOOP
159+
assert cfg.authentication.skip_tls_verification is False
160+
assert cfg.authentication.k8s_ca_cert_path is None
161+
assert cfg.authentication.k8s_cluster_api is None
162+
163+
cfg2 = Configuration(
164+
name="test_name",
165+
service=ServiceConfiguration(),
166+
llama_stack=LlamaStackConfiguration(
167+
use_as_library_client=True,
168+
library_client_config_path="tests/configuration/run.yaml",
169+
),
170+
user_data_collection=UserDataCollection(
171+
feedback_enabled=False, feedback_storage=None
172+
),
173+
mcp_servers=[],
174+
authentication=AuthenticationConfiguration(
175+
module=AUTH_MOD_K8S,
176+
skip_tls_verification=True,
177+
k8s_ca_cert_path="tests/configuration/server.crt",
178+
k8s_cluster_api=None,
179+
),
180+
)
181+
assert cfg2.authentication is not None
182+
assert cfg2.authentication.module == AUTH_MOD_K8S
183+
assert cfg2.authentication.skip_tls_verification is True
184+
assert cfg2.authentication.k8s_ca_cert_path == Path(
185+
"tests/configuration/server.crt"
186+
)
187+
assert cfg2.authentication.k8s_cluster_api is None
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""Unit tests for CORSConfiguration model."""
2+
3+
import pytest
4+
5+
from models.config import CORSConfiguration
6+
7+
8+
def test_cors_default_configuration() -> None:
9+
"""Test the CORS configuration."""
10+
cfg = CORSConfiguration()
11+
assert cfg is not None
12+
assert cfg.allow_origins == ["*"]
13+
assert cfg.allow_credentials is False
14+
assert cfg.allow_methods == ["*"]
15+
assert cfg.allow_headers == ["*"]
16+
17+
18+
def test_cors_custom_configuration_v1() -> None:
19+
"""Test the CORS configuration."""
20+
cfg = CORSConfiguration(
21+
allow_origins=["foo_origin", "bar_origin", "baz_origin"],
22+
allow_credentials=False,
23+
allow_methods=["foo_method", "bar_method", "baz_method"],
24+
allow_headers=["foo_header", "bar_header", "baz_header"],
25+
)
26+
assert cfg is not None
27+
assert cfg.allow_origins == ["foo_origin", "bar_origin", "baz_origin"]
28+
assert cfg.allow_credentials is False
29+
assert cfg.allow_methods == ["foo_method", "bar_method", "baz_method"]
30+
assert cfg.allow_headers == ["foo_header", "bar_header", "baz_header"]
31+
32+
33+
def test_cors_custom_configuration_v2() -> None:
34+
"""Test the CORS configuration."""
35+
cfg = CORSConfiguration(
36+
allow_origins=["foo_origin", "bar_origin", "baz_origin"],
37+
allow_credentials=True,
38+
allow_methods=["foo_method", "bar_method", "baz_method"],
39+
allow_headers=["foo_header", "bar_header", "baz_header"],
40+
)
41+
assert cfg is not None
42+
assert cfg.allow_origins == ["foo_origin", "bar_origin", "baz_origin"]
43+
assert cfg.allow_credentials is True
44+
assert cfg.allow_methods == ["foo_method", "bar_method", "baz_method"]
45+
assert cfg.allow_headers == ["foo_header", "bar_header", "baz_header"]
46+
47+
48+
def test_cors_custom_configuration_v3() -> None:
49+
"""Test the CORS configuration."""
50+
cfg = CORSConfiguration(
51+
allow_origins=["*"],
52+
allow_credentials=False,
53+
allow_methods=["foo_method", "bar_method", "baz_method"],
54+
allow_headers=["foo_header", "bar_header", "baz_header"],
55+
)
56+
assert cfg is not None
57+
assert cfg.allow_origins == ["*"]
58+
assert cfg.allow_credentials is False
59+
assert cfg.allow_methods == ["foo_method", "bar_method", "baz_method"]
60+
assert cfg.allow_headers == ["foo_header", "bar_header", "baz_header"]
61+
62+
63+
def test_cors_improper_configuration() -> None:
64+
"""Test the CORS configuration."""
65+
expected = (
66+
"Value error, Invalid CORS configuration: "
67+
+ "allow_credentials can not be set to true when allow origins contains '\\*' wildcard."
68+
+ "Use explicit origins or disable credential."
69+
)
70+
71+
with pytest.raises(ValueError, match=expected):
72+
# allow_credentials can not be true when allow_origins contains '*'
73+
CORSConfiguration(
74+
allow_origins=["*"],
75+
allow_credentials=True,
76+
allow_methods=["foo_method", "bar_method", "baz_method"],
77+
allow_headers=["foo_header", "bar_header", "baz_header"],
78+
)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Unit tests for DatabaseConfiguration model."""
2+
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from pydantic import ValidationError
8+
9+
from models.config import (
10+
PostgreSQLDatabaseConfiguration,
11+
SQLiteDatabaseConfiguration,
12+
DatabaseConfiguration,
13+
)
14+
15+
16+
def test_database_configuration(subtests) -> None:
17+
"""Test the database configuration handling."""
18+
with subtests.test(msg="PostgreSQL"):
19+
d1 = PostgreSQLDatabaseConfiguration(
20+
db="db",
21+
user="user",
22+
password="password",
23+
port=1234,
24+
ca_cert_path=Path("tests/configuration/server.crt"),
25+
)
26+
d = DatabaseConfiguration(postgres=d1)
27+
assert d is not None
28+
assert d.sqlite is None
29+
assert d.postgres is not None
30+
assert d.db_type == "postgres"
31+
assert d.config is d1
32+
33+
with subtests.test(msg="SQLite"):
34+
d1 = SQLiteDatabaseConfiguration(
35+
db_path="/tmp/foo/bar/baz",
36+
)
37+
d = DatabaseConfiguration(sqlite=d1)
38+
assert d is not None
39+
assert d.sqlite is not None
40+
assert d.postgres is None
41+
assert d.db_type == "sqlite"
42+
assert d.config is d1
43+
44+
45+
def test_no_databases_configuration() -> None:
46+
"""Test if no databases configuration is checked."""
47+
d = DatabaseConfiguration()
48+
assert d is not None
49+
50+
# default should be SQLite when nothing is provided
51+
assert d.db_type == "sqlite"
52+
53+
# simulate no DB configuration
54+
d.sqlite = None
55+
d.postgres = None
56+
57+
with pytest.raises(ValueError, match="No database configuration found"):
58+
# access property to call its getter
59+
_ = d.db_type
60+
61+
with pytest.raises(ValueError, match="No database configuration found"):
62+
# access property to call its getter
63+
_ = d.config
64+
65+
66+
def test_two_databases_configuration() -> None:
67+
"""Test if two databases configuration is checked."""
68+
d1 = PostgreSQLDatabaseConfiguration(db="db", user="user", password="password")
69+
d2 = SQLiteDatabaseConfiguration(db_path="foo_bar_baz")
70+
with pytest.raises(
71+
ValidationError, match="Only one database configuration can be provided"
72+
):
73+
DatabaseConfiguration(postgres=d1, sqlite=d2)

0 commit comments

Comments
 (0)