Skip to content

Commit 277ab1e

Browse files
committed
Adding Profile Tests
1 parent a76c07a commit 277ab1e

11 files changed

+1708
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
my_examples
22
.idea
3+
.env
34
.venv
45
.DS_Store
56
select_ai.egg-info

tests/conftest.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,35 @@
3333

3434
PYSAI_TEST_USER = "PYSAI_TEST_USER"
3535
PYSAI_OCI_CREDENTIAL_NAME = f"PYSAI_OCI_CREDENTIAL_{uuid.uuid4().hex.upper()}"
36+
_BASIC_SCHEMA_PRIVILEGES = (
37+
"CREATE SESSION",
38+
"CREATE TABLE",
39+
"UNLIMITED TABLESPACE",
40+
)
41+
42+
43+
def _ensure_test_user_exists(username: str, password: str):
44+
username_upper = username.upper()
45+
with select_ai.cursor() as cr:
46+
cr.execute(
47+
"SELECT 1 FROM dba_users WHERE username = :username",
48+
username=username_upper,
49+
)
50+
if cr.fetchone():
51+
return
52+
escaped_password = password.replace("\"", "\"\"")
53+
cr.execute(
54+
f"CREATE USER {username_upper} IDENTIFIED BY \"{escaped_password}\""
55+
)
56+
select_ai.db.get_connection().commit()
57+
58+
59+
def _grant_basic_schema_privileges(username: str):
60+
username_upper = username.upper()
61+
with select_ai.cursor() as cr:
62+
for privilege in _BASIC_SCHEMA_PRIVILEGES:
63+
cr.execute(f"GRANT {privilege} TO {username_upper}")
64+
select_ai.db.get_connection().commit()
3665

3766

3867
def get_env_value(name, default_value=None, required=False):
@@ -93,6 +122,11 @@ def test_env(pytestconfig):
93122
@pytest.fixture(autouse=True, scope="session")
94123
def setup_test_user(test_env):
95124
select_ai.connect(**test_env.connect_params(admin=True))
125+
_ensure_test_user_exists(
126+
username=test_env.test_user,
127+
password=test_env.test_user_password,
128+
)
129+
_grant_basic_schema_privileges(username=test_env.test_user)
96130
select_ai.grant_privileges(users=[test_env.test_user])
97131
select_ai.grant_http_access(
98132
users=[test_env.test_user],
@@ -146,6 +180,7 @@ def oci_credential(connect, test_env):
146180
"private_key": get_env_value("OCI_PRIVATE_KEY", required=True),
147181
"fingerprint": get_env_value("OCI_FINGERPRINT", required=True),
148182
}
183+
print(credential)
149184
select_ai.create_credential(credential, replace=True)
150185
yield credential
151186
select_ai.delete_credential(PYSAI_OCI_CREDENTIAL_NAME)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) 2025, Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Universal Permissive License v 1.0 as shown at
5+
# http://oss.oracle.com/licenses/upl.
6+
# -----------------------------------------------------------------------------
7+
8+
"""
9+
2000 - Synthetic data generation tests
10+
"""
11+
12+
import uuid
13+
14+
import pytest
15+
import select_ai
16+
from select_ai import Profile, ProfileAttributes, SyntheticDataAttributes, SyntheticDataParams
17+
18+
PROFILE_PREFIX = f"PYSAI_2000_{uuid.uuid4().hex.upper()}"
19+
20+
21+
def _build_attributes(record_count=1, **kwargs):
22+
return SyntheticDataAttributes(
23+
object_name="people",
24+
record_count=record_count,
25+
**kwargs,
26+
)
27+
28+
29+
@pytest.fixture(scope="module")
30+
def synthetic_provider(oci_compartment_id):
31+
return select_ai.OCIGenAIProvider(
32+
oci_compartment_id=oci_compartment_id,
33+
oci_apiformat="GENERIC",
34+
)
35+
36+
37+
@pytest.fixture(scope="module")
38+
def synthetic_profile_attributes(oci_credential, synthetic_provider):
39+
return ProfileAttributes(
40+
credential_name=oci_credential["credential_name"],
41+
object_list=[
42+
{"owner": "ADMIN", "name": "people"},
43+
{"owner": "ADMIN", "name": "gymnast"},
44+
],
45+
provider=synthetic_provider,
46+
)
47+
48+
49+
@pytest.fixture(scope="module")
50+
def synthetic_profile(synthetic_profile_attributes):
51+
profile = Profile(
52+
profile_name=f"{PROFILE_PREFIX}_SYNC",
53+
attributes=synthetic_profile_attributes,
54+
description="Synthetic data test profile",
55+
replace=True,
56+
)
57+
yield profile
58+
try:
59+
profile.delete(force=True)
60+
except Exception:
61+
pass
62+
63+
64+
def test_2000_generate_with_full_params(synthetic_profile):
65+
"""Generate synthetic data with full parameter set"""
66+
params = SyntheticDataParams(sample_rows=10, priority="HIGH")
67+
attributes = _build_attributes(
68+
record_count=5,
69+
params=params,
70+
user_prompt="age must be greater than 20",
71+
)
72+
result = synthetic_profile.generate_synthetic_data(attributes)
73+
assert result is None
74+
75+
76+
def test_2001_generate_minimum_fields(synthetic_profile):
77+
"""Generate synthetic data with minimum fields"""
78+
attributes = _build_attributes()
79+
result = synthetic_profile.generate_synthetic_data(attributes)
80+
assert result is None
81+
82+
83+
def test_2002_generate_zero_sample_rows(synthetic_profile):
84+
"""Generate synthetic data with zero sample rows"""
85+
params = SyntheticDataParams(sample_rows=0, priority="HIGH")
86+
attributes = _build_attributes(params=params)
87+
result = synthetic_profile.generate_synthetic_data(attributes)
88+
assert result is None
89+
90+
91+
def test_2003_generate_single_sample_row(synthetic_profile):
92+
"""Generate synthetic data with single sample row"""
93+
params = SyntheticDataParams(sample_rows=1, priority="HIGH")
94+
attributes = _build_attributes(params=params)
95+
result = synthetic_profile.generate_synthetic_data(attributes)
96+
assert result is None
97+
98+
99+
def test_2004_generate_low_priority(synthetic_profile):
100+
"""Generate synthetic data with low priority"""
101+
params = SyntheticDataParams(sample_rows=1, priority="LOW")
102+
attributes = _build_attributes(params=params)
103+
result = synthetic_profile.generate_synthetic_data(attributes)
104+
assert result is None
105+
106+
107+
def test_2005_generate_missing_object_name(synthetic_profile):
108+
"""Missing object_name raises error"""
109+
attributes = SyntheticDataAttributes(record_count=1)
110+
with pytest.raises(Exception):
111+
synthetic_profile.generate_synthetic_data(attributes)
112+
113+
114+
def test_2006_generate_invalid_priority(synthetic_profile):
115+
"""Invalid priority raises error"""
116+
params = SyntheticDataParams(sample_rows=1, priority="CRITICAL")
117+
attributes = _build_attributes(params=params)
118+
with pytest.raises(Exception):
119+
synthetic_profile.generate_synthetic_data(attributes)
120+
121+
122+
def test_2007_generate_negative_record_count(synthetic_profile):
123+
"""Negative record count raises error"""
124+
attributes = _build_attributes(record_count=-5)
125+
with pytest.raises(Exception):
126+
synthetic_profile.generate_synthetic_data(attributes)
127+
128+
129+
def test_2008_generate_with_none_attributes(synthetic_profile):
130+
"""Passing None as attributes raises error"""
131+
with pytest.raises(Exception):
132+
synthetic_profile.generate_synthetic_data(None)
133+
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) 2025, Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Universal Permissive License v 1.0 as shown at
5+
# http://oss.oracle.com/licenses/upl.
6+
# -----------------------------------------------------------------------------
7+
8+
"""
9+
2100 - Synthetic data generation tests (async)
10+
"""
11+
12+
import uuid
13+
14+
import pytest
15+
import select_ai
16+
from select_ai import AsyncProfile, ProfileAttributes, SyntheticDataAttributes, SyntheticDataParams
17+
18+
PROFILE_PREFIX = f"PYSAI_2100_{uuid.uuid4().hex.upper()}"
19+
20+
21+
def _build_attributes(record_count=1, **kwargs):
22+
return SyntheticDataAttributes(
23+
object_name="people",
24+
record_count=record_count,
25+
**kwargs,
26+
)
27+
28+
29+
@pytest.fixture(scope="module")
30+
def async_synthetic_provider(oci_compartment_id):
31+
return select_ai.OCIGenAIProvider(
32+
oci_compartment_id=oci_compartment_id,
33+
oci_apiformat="GENERIC",
34+
)
35+
36+
37+
@pytest.fixture(scope="module")
38+
def async_synthetic_profile_attributes(oci_credential, async_synthetic_provider):
39+
return ProfileAttributes(
40+
credential_name=oci_credential["credential_name"],
41+
object_list=[
42+
{"owner": "ADMIN", "name": "people"},
43+
{"owner": "ADMIN", "name": "gymnast"},
44+
],
45+
provider=async_synthetic_provider,
46+
)
47+
48+
49+
@pytest.fixture(scope="module")
50+
async def async_synthetic_profile(async_synthetic_profile_attributes):
51+
profile = await AsyncProfile(
52+
profile_name=f"{PROFILE_PREFIX}_ASYNC",
53+
attributes=async_synthetic_profile_attributes,
54+
description="Synthetic data async test profile",
55+
replace=True,
56+
)
57+
yield profile
58+
try:
59+
await profile.delete(force=True)
60+
except Exception:
61+
pass
62+
63+
64+
@pytest.mark.anyio
65+
async def test_2100_generate_with_full_params(async_synthetic_profile):
66+
"""Generate synthetic data with full parameter set"""
67+
params = SyntheticDataParams(sample_rows=10, priority="HIGH")
68+
attributes = _build_attributes(
69+
record_count=5,
70+
params=params,
71+
user_prompt="age must be greater than 20",
72+
)
73+
result = await async_synthetic_profile.generate_synthetic_data(attributes)
74+
assert result is None
75+
76+
77+
@pytest.mark.anyio
78+
async def test_2101_generate_minimum_fields(async_synthetic_profile):
79+
"""Generate synthetic data with minimum fields"""
80+
attributes = _build_attributes()
81+
result = await async_synthetic_profile.generate_synthetic_data(attributes)
82+
assert result is None
83+
84+
85+
@pytest.mark.anyio
86+
async def test_2102_generate_zero_sample_rows(async_synthetic_profile):
87+
"""Generate synthetic data with zero sample rows"""
88+
params = SyntheticDataParams(sample_rows=0, priority="HIGH")
89+
attributes = _build_attributes(params=params)
90+
result = await async_synthetic_profile.generate_synthetic_data(attributes)
91+
assert result is None
92+
93+
94+
@pytest.mark.anyio
95+
async def test_2103_generate_single_sample_row(async_synthetic_profile):
96+
"""Generate synthetic data with single sample row"""
97+
params = SyntheticDataParams(sample_rows=1, priority="HIGH")
98+
attributes = _build_attributes(params=params)
99+
result = await async_synthetic_profile.generate_synthetic_data(attributes)
100+
assert result is None
101+
102+
103+
@pytest.mark.anyio
104+
async def test_2104_generate_low_priority(async_synthetic_profile):
105+
"""Generate synthetic data with low priority"""
106+
params = SyntheticDataParams(sample_rows=1, priority="LOW")
107+
attributes = _build_attributes(params=params)
108+
result = await async_synthetic_profile.generate_synthetic_data(attributes)
109+
assert result is None
110+
111+
112+
@pytest.mark.anyio
113+
async def test_2105_generate_missing_object_name(async_synthetic_profile):
114+
"""Missing object_name raises error"""
115+
attributes = SyntheticDataAttributes(record_count=1)
116+
with pytest.raises(Exception):
117+
await async_synthetic_profile.generate_synthetic_data(attributes)
118+
119+
120+
@pytest.mark.anyio
121+
async def test_2106_generate_invalid_priority(async_synthetic_profile):
122+
"""Invalid priority raises error"""
123+
params = SyntheticDataParams(sample_rows=1, priority="CRITICAL")
124+
attributes = _build_attributes(params=params)
125+
with pytest.raises(Exception):
126+
await async_synthetic_profile.generate_synthetic_data(attributes)
127+
128+
129+
@pytest.mark.anyio
130+
async def test_2107_generate_negative_record_count(async_synthetic_profile):
131+
"""Negative record count raises error"""
132+
attributes = _build_attributes(record_count=-5)
133+
with pytest.raises(Exception):
134+
await async_synthetic_profile.generate_synthetic_data(attributes)
135+
136+
137+
@pytest.mark.anyio
138+
async def test_2108_generate_with_none_attributes(async_synthetic_profile):
139+
"""Passing None as attributes raises error"""
140+
with pytest.raises(Exception):
141+
await async_synthetic_profile.generate_synthetic_data(None)

tests/profiles/test_1200_profile.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,15 @@ def test_1207():
206206
assert profile.attributes.provider.model == "meta.llama-3.1-70b-instruct"
207207

208208

209-
def test_1208(oci_credential):
209+
def test_1208(oci_credential, oci_compartment_id):
210210
"""Set multiple attributes for a Profile"""
211211
profile = Profile(PYSAI_1200_PROFILE)
212212
profile_attrs = ProfileAttributes(
213213
credential_name=oci_credential["credential_name"],
214214
provider=select_ai.OCIGenAIProvider(
215215
model="meta.llama-4-maverick-17b-128e-instruct-fp8",
216216
region="us-chicago-1",
217+
oci_compartment_id=oci_compartment_id,
217218
oci_apiformat="GENERIC",
218219
),
219220
object_list=[{"owner": "ADMIN", "name": "gymnasts"}],

0 commit comments

Comments
 (0)