matrixone-python-sdk 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matrixone/__init__.py +155 -0
- matrixone/account.py +723 -0
- matrixone/async_client.py +3913 -0
- matrixone/async_metadata_manager.py +311 -0
- matrixone/async_orm.py +123 -0
- matrixone/async_vector_index_manager.py +633 -0
- matrixone/base_client.py +208 -0
- matrixone/client.py +4672 -0
- matrixone/config.py +452 -0
- matrixone/connection_hooks.py +286 -0
- matrixone/exceptions.py +89 -0
- matrixone/logger.py +782 -0
- matrixone/metadata.py +820 -0
- matrixone/moctl.py +219 -0
- matrixone/orm.py +2277 -0
- matrixone/pitr.py +646 -0
- matrixone/pubsub.py +771 -0
- matrixone/restore.py +411 -0
- matrixone/search_vector_index.py +1176 -0
- matrixone/snapshot.py +550 -0
- matrixone/sql_builder.py +844 -0
- matrixone/sqlalchemy_ext/__init__.py +161 -0
- matrixone/sqlalchemy_ext/adapters.py +163 -0
- matrixone/sqlalchemy_ext/dialect.py +534 -0
- matrixone/sqlalchemy_ext/fulltext_index.py +895 -0
- matrixone/sqlalchemy_ext/fulltext_search.py +1686 -0
- matrixone/sqlalchemy_ext/hnsw_config.py +194 -0
- matrixone/sqlalchemy_ext/ivf_config.py +252 -0
- matrixone/sqlalchemy_ext/table_builder.py +351 -0
- matrixone/sqlalchemy_ext/vector_index.py +1721 -0
- matrixone/sqlalchemy_ext/vector_type.py +948 -0
- matrixone/version.py +580 -0
- matrixone_python_sdk-0.1.0.dist-info/METADATA +706 -0
- matrixone_python_sdk-0.1.0.dist-info/RECORD +122 -0
- matrixone_python_sdk-0.1.0.dist-info/WHEEL +5 -0
- matrixone_python_sdk-0.1.0.dist-info/entry_points.txt +5 -0
- matrixone_python_sdk-0.1.0.dist-info/licenses/LICENSE +200 -0
- matrixone_python_sdk-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +19 -0
- tests/offline/__init__.py +20 -0
- tests/offline/conftest.py +77 -0
- tests/offline/test_account.py +703 -0
- tests/offline/test_async_client_query_comprehensive.py +1218 -0
- tests/offline/test_basic.py +54 -0
- tests/offline/test_case_sensitivity.py +227 -0
- tests/offline/test_connection_hooks_offline.py +287 -0
- tests/offline/test_dialect_schema_handling.py +609 -0
- tests/offline/test_explain_methods.py +346 -0
- tests/offline/test_filter_logical_in.py +237 -0
- tests/offline/test_fulltext_search_comprehensive.py +795 -0
- tests/offline/test_ivf_config.py +249 -0
- tests/offline/test_join_methods.py +281 -0
- tests/offline/test_join_sqlalchemy_compatibility.py +276 -0
- tests/offline/test_logical_in_method.py +237 -0
- tests/offline/test_matrixone_version_parsing.py +264 -0
- tests/offline/test_metadata_offline.py +557 -0
- tests/offline/test_moctl.py +300 -0
- tests/offline/test_moctl_simple.py +251 -0
- tests/offline/test_model_support_offline.py +359 -0
- tests/offline/test_model_support_simple.py +225 -0
- tests/offline/test_pinecone_filter_offline.py +377 -0
- tests/offline/test_pitr.py +585 -0
- tests/offline/test_pubsub.py +712 -0
- tests/offline/test_query_update.py +283 -0
- tests/offline/test_restore.py +445 -0
- tests/offline/test_snapshot_comprehensive.py +384 -0
- tests/offline/test_sql_escaping_edge_cases.py +551 -0
- tests/offline/test_sqlalchemy_integration.py +382 -0
- tests/offline/test_sqlalchemy_vector_integration.py +434 -0
- tests/offline/test_table_builder.py +198 -0
- tests/offline/test_unified_filter.py +398 -0
- tests/offline/test_unified_transaction.py +495 -0
- tests/offline/test_vector_index.py +238 -0
- tests/offline/test_vector_operations.py +688 -0
- tests/offline/test_vector_type.py +174 -0
- tests/offline/test_version_core.py +328 -0
- tests/offline/test_version_management.py +372 -0
- tests/offline/test_version_standalone.py +652 -0
- tests/online/__init__.py +20 -0
- tests/online/conftest.py +216 -0
- tests/online/test_account_management.py +194 -0
- tests/online/test_advanced_features.py +344 -0
- tests/online/test_async_client_interfaces.py +330 -0
- tests/online/test_async_client_online.py +285 -0
- tests/online/test_async_model_insert_online.py +293 -0
- tests/online/test_async_orm_online.py +300 -0
- tests/online/test_async_simple_query_online.py +802 -0
- tests/online/test_async_transaction_simple_query.py +300 -0
- tests/online/test_basic_connection.py +130 -0
- tests/online/test_client_online.py +238 -0
- tests/online/test_config.py +90 -0
- tests/online/test_config_validation.py +123 -0
- tests/online/test_connection_hooks_new_online.py +217 -0
- tests/online/test_dialect_schema_handling_online.py +331 -0
- tests/online/test_filter_logical_in_online.py +374 -0
- tests/online/test_fulltext_comprehensive.py +1773 -0
- tests/online/test_fulltext_label_online.py +433 -0
- tests/online/test_fulltext_search_online.py +842 -0
- tests/online/test_ivf_stats_online.py +506 -0
- tests/online/test_logger_integration.py +311 -0
- tests/online/test_matrixone_query_orm.py +540 -0
- tests/online/test_metadata_online.py +579 -0
- tests/online/test_model_insert_online.py +255 -0
- tests/online/test_mysql_driver_validation.py +213 -0
- tests/online/test_orm_advanced_features.py +2022 -0
- tests/online/test_orm_cte_integration.py +269 -0
- tests/online/test_orm_online.py +270 -0
- tests/online/test_pinecone_filter.py +708 -0
- tests/online/test_pubsub_operations.py +352 -0
- tests/online/test_query_methods.py +225 -0
- tests/online/test_query_update_online.py +433 -0
- tests/online/test_search_vector_index.py +557 -0
- tests/online/test_simple_fulltext_online.py +915 -0
- tests/online/test_snapshot_comprehensive.py +998 -0
- tests/online/test_sqlalchemy_engine_integration.py +336 -0
- tests/online/test_sqlalchemy_integration.py +425 -0
- tests/online/test_transaction_contexts.py +1219 -0
- tests/online/test_transaction_insert_methods.py +356 -0
- tests/online/test_transaction_query_methods.py +288 -0
- tests/online/test_unified_filter_online.py +529 -0
- tests/online/test_vector_comprehensive.py +706 -0
- tests/online/test_version_management.py +291 -0
tests/online/conftest.py
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
# Copyright 2021 - 2022 Matrix Origin
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
"""
|
18
|
+
Pytest configuration for online tests
|
19
|
+
|
20
|
+
This file ensures that fixtures are properly registered for online tests.
|
21
|
+
"""
|
22
|
+
|
23
|
+
import pytest
|
24
|
+
import pytest_asyncio
|
25
|
+
import asyncio
|
26
|
+
from typing import Tuple
|
27
|
+
from matrixone import Client, AsyncClient
|
28
|
+
from matrixone.logger import create_default_logger
|
29
|
+
from .test_config import online_config
|
30
|
+
|
31
|
+
|
32
|
+
@pytest.fixture(scope="session")
|
33
|
+
def event_loop():
|
34
|
+
"""Create an instance of the default event loop for the test session."""
|
35
|
+
policy = asyncio.get_event_loop_policy()
|
36
|
+
loop = policy.new_event_loop()
|
37
|
+
yield loop
|
38
|
+
loop.close()
|
39
|
+
|
40
|
+
|
41
|
+
def pytest_configure(config):
|
42
|
+
"""Configure pytest with online test settings"""
|
43
|
+
config.addinivalue_line("markers", "online: mark test as requiring database connection")
|
44
|
+
config.addinivalue_line("markers", "slow: mark test as slow running")
|
45
|
+
|
46
|
+
|
47
|
+
class DatabaseTestHelper:
|
48
|
+
"""Helper class for database operations in tests"""
|
49
|
+
|
50
|
+
def __init__(self):
|
51
|
+
self.logger = create_default_logger()
|
52
|
+
|
53
|
+
def create_client(self, host: str, port: int, user: str, password: str, database: str) -> Client:
|
54
|
+
"""Create a synchronous client"""
|
55
|
+
return Client()
|
56
|
+
|
57
|
+
def connect_client(self, client: Client, host: str, port: int, user: str, password: str, database: str) -> bool:
|
58
|
+
"""Connect a client and return success status"""
|
59
|
+
try:
|
60
|
+
client.connect(host=host, port=port, user=user, password=password, database=database)
|
61
|
+
return True
|
62
|
+
except Exception as e:
|
63
|
+
self.logger.error(f"Failed to connect client: {e}")
|
64
|
+
return False
|
65
|
+
|
66
|
+
def create_async_client(self, host: str, port: int, user: str, password: str, database: str) -> AsyncClient:
|
67
|
+
"""Create an asynchronous client"""
|
68
|
+
return AsyncClient()
|
69
|
+
|
70
|
+
async def connect_async_client(
|
71
|
+
self, client: AsyncClient, host: str, port: int, user: str, password: str, database: str
|
72
|
+
) -> bool:
|
73
|
+
"""Connect an async client and return success status"""
|
74
|
+
try:
|
75
|
+
await client.connect(host=host, port=port, user=user, password=password, database=database)
|
76
|
+
return True
|
77
|
+
except Exception as e:
|
78
|
+
self.logger.error(f"Failed to connect async client: {e}")
|
79
|
+
return False
|
80
|
+
|
81
|
+
def test_connection(self, host: str, port: int, user: str, password: str, database: str) -> bool:
|
82
|
+
"""Test database connection"""
|
83
|
+
try:
|
84
|
+
client = self.create_client(host, port, user, password, database)
|
85
|
+
return self.connect_client(client, host, port, user, password, database)
|
86
|
+
except Exception as e:
|
87
|
+
self.logger.error(f"Connection test failed: {e}")
|
88
|
+
return False
|
89
|
+
|
90
|
+
async def test_async_connection(self, host: str, port: int, user: str, password: str, database: str) -> bool:
|
91
|
+
"""Test async database connection"""
|
92
|
+
try:
|
93
|
+
client = self.create_async_client(host, port, user, password, database)
|
94
|
+
return await self.connect_async_client(client, host, port, user, password, database)
|
95
|
+
except Exception as e:
|
96
|
+
self.logger.error(f"Async connection test failed: {e}")
|
97
|
+
return False
|
98
|
+
|
99
|
+
|
100
|
+
@pytest.fixture(scope="session")
|
101
|
+
def db_config():
|
102
|
+
"""Provide database configuration"""
|
103
|
+
return online_config
|
104
|
+
|
105
|
+
|
106
|
+
@pytest.fixture(scope="session")
|
107
|
+
def connection_params():
|
108
|
+
"""Provide connection parameters"""
|
109
|
+
return online_config.get_connection_params()
|
110
|
+
|
111
|
+
|
112
|
+
@pytest.fixture(scope="session")
|
113
|
+
def test_database():
|
114
|
+
"""Provide test database name"""
|
115
|
+
return online_config.get_test_database()
|
116
|
+
|
117
|
+
|
118
|
+
@pytest.fixture(scope="session")
|
119
|
+
def sys_database():
|
120
|
+
"""Provide system database name"""
|
121
|
+
return online_config.get_sys_database()
|
122
|
+
|
123
|
+
|
124
|
+
@pytest.fixture(scope="session")
|
125
|
+
def test_account():
|
126
|
+
"""Provide test account name"""
|
127
|
+
return online_config.get_test_account()
|
128
|
+
|
129
|
+
|
130
|
+
@pytest.fixture(scope="session")
|
131
|
+
def table_prefix():
|
132
|
+
"""Provide table prefix for tests"""
|
133
|
+
return online_config.table_prefix
|
134
|
+
|
135
|
+
|
136
|
+
@pytest.fixture(scope="session")
|
137
|
+
def snapshot_prefix():
|
138
|
+
"""Provide snapshot prefix for tests"""
|
139
|
+
return online_config.snapshot_prefix
|
140
|
+
|
141
|
+
|
142
|
+
@pytest.fixture(scope="session")
|
143
|
+
def vector_dimensions():
|
144
|
+
"""Provide vector dimensions for tests"""
|
145
|
+
return online_config.get_vector_dimensions()
|
146
|
+
|
147
|
+
|
148
|
+
@pytest.fixture(scope="session")
|
149
|
+
def vector_test_data_size():
|
150
|
+
"""Provide vector test data size"""
|
151
|
+
return online_config.get_vector_test_data_size()
|
152
|
+
|
153
|
+
|
154
|
+
@pytest.fixture(scope="session")
|
155
|
+
def db_helper():
|
156
|
+
"""Provide database helper instance"""
|
157
|
+
return DatabaseTestHelper()
|
158
|
+
|
159
|
+
|
160
|
+
@pytest.fixture(scope="session")
|
161
|
+
def db_connection_test(db_helper):
|
162
|
+
"""Test database connection and provide result"""
|
163
|
+
host, port, user, password, database = online_config.get_connection_params()
|
164
|
+
success = db_helper.test_connection(host, port, user, password, database)
|
165
|
+
if not success:
|
166
|
+
pytest.skip("Database connection failed - skipping online tests")
|
167
|
+
return success
|
168
|
+
|
169
|
+
|
170
|
+
@pytest_asyncio.fixture(scope="session")
|
171
|
+
async def async_db_connection_test(db_helper):
|
172
|
+
"""Test async database connection and provide result"""
|
173
|
+
host, port, user, password, database = online_config.get_connection_params()
|
174
|
+
success = await db_helper.test_async_connection(host, port, user, password, database)
|
175
|
+
if not success:
|
176
|
+
pytest.skip("Async database connection failed - skipping online tests")
|
177
|
+
return success
|
178
|
+
|
179
|
+
|
180
|
+
@pytest.fixture
|
181
|
+
def test_client(db_helper, db_connection_test):
|
182
|
+
"""Provide a connected test client"""
|
183
|
+
host, port, user, password, database = online_config.get_connection_params()
|
184
|
+
client = db_helper.create_client(host, port, user, password, database)
|
185
|
+
db_helper.connect_client(client, host, port, user, password, database)
|
186
|
+
try:
|
187
|
+
yield client
|
188
|
+
finally:
|
189
|
+
try:
|
190
|
+
client.disconnect()
|
191
|
+
except Exception as e:
|
192
|
+
print(f"Warning: Failed to disconnect test client: {e}")
|
193
|
+
# Don't ignore - this could indicate a real problem
|
194
|
+
raise
|
195
|
+
|
196
|
+
|
197
|
+
@pytest_asyncio.fixture
|
198
|
+
async def test_async_client(db_helper, async_db_connection_test):
|
199
|
+
"""Provide a connected async test client"""
|
200
|
+
host, port, user, password, database = online_config.get_connection_params()
|
201
|
+
client = db_helper.create_async_client(host, port, user, password, database)
|
202
|
+
await db_helper.connect_async_client(client, host, port, user, password, database)
|
203
|
+
try:
|
204
|
+
yield client
|
205
|
+
finally:
|
206
|
+
# Clean disconnect - the improved disconnect method should handle cleanup properly
|
207
|
+
try:
|
208
|
+
await client.disconnect()
|
209
|
+
except Exception as e:
|
210
|
+
# If async disconnect fails, try sync cleanup as fallback
|
211
|
+
try:
|
212
|
+
client.disconnect_sync()
|
213
|
+
except Exception:
|
214
|
+
pass
|
215
|
+
# Log the error for debugging
|
216
|
+
print(f"Warning: Failed to disconnect async client: {e}")
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# Copyright 2021 - 2022 Matrix Origin
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""
|
16
|
+
Online tests for account management functionality
|
17
|
+
|
18
|
+
These tests are inspired by example_02_account_management.py
|
19
|
+
"""
|
20
|
+
|
21
|
+
import pytest
|
22
|
+
from matrixone import Client, AsyncClient
|
23
|
+
from matrixone.account import AccountManager, AccountError
|
24
|
+
|
25
|
+
|
26
|
+
@pytest.mark.online
|
27
|
+
class TestAccountManagement:
|
28
|
+
"""Test account management functionality"""
|
29
|
+
|
30
|
+
def test_create_and_drop_account(self, test_client):
|
31
|
+
"""Test creating and dropping an account"""
|
32
|
+
account_manager = AccountManager(test_client)
|
33
|
+
|
34
|
+
# Create account
|
35
|
+
account_name = "test_account_001"
|
36
|
+
admin_name = "test_admin_001"
|
37
|
+
password = "test_password_001"
|
38
|
+
|
39
|
+
account = account_manager.create_account(account_name, admin_name, password)
|
40
|
+
assert account is not None
|
41
|
+
assert account.name == account_name
|
42
|
+
|
43
|
+
# Drop account
|
44
|
+
account_manager.drop_account(account_name)
|
45
|
+
|
46
|
+
# Verify account is dropped (should raise error when trying to get it)
|
47
|
+
try:
|
48
|
+
account_manager.get_account(account_name)
|
49
|
+
assert False, "Account should have been dropped"
|
50
|
+
except AccountError:
|
51
|
+
pass # Expected
|
52
|
+
|
53
|
+
def test_create_and_drop_user(self, test_client):
|
54
|
+
"""Test creating and dropping a user"""
|
55
|
+
account_manager = AccountManager(test_client)
|
56
|
+
|
57
|
+
# Create user
|
58
|
+
username = "test_user_001"
|
59
|
+
password = "test_password_001"
|
60
|
+
|
61
|
+
user = account_manager.create_user(username, password)
|
62
|
+
assert user is not None
|
63
|
+
assert user.name == username
|
64
|
+
|
65
|
+
# List users (MatrixOne only returns current user)
|
66
|
+
users = account_manager.list_users()
|
67
|
+
assert isinstance(users, list)
|
68
|
+
|
69
|
+
# Drop user
|
70
|
+
account_manager.drop_user(username)
|
71
|
+
|
72
|
+
def test_alter_account(self, test_client):
|
73
|
+
"""Test altering an account"""
|
74
|
+
account_manager = AccountManager(test_client)
|
75
|
+
|
76
|
+
# Create account first
|
77
|
+
account_name = "test_account_002"
|
78
|
+
admin_name = "test_admin_002"
|
79
|
+
password = "test_password_002"
|
80
|
+
|
81
|
+
account = account_manager.create_account(account_name, admin_name, password)
|
82
|
+
assert account is not None
|
83
|
+
|
84
|
+
try:
|
85
|
+
# Alter account (add comment)
|
86
|
+
account_manager.alter_account(account_name, comment="Updated account")
|
87
|
+
|
88
|
+
# Verify account still exists
|
89
|
+
updated_account = account_manager.get_account(account_name)
|
90
|
+
assert updated_account is not None
|
91
|
+
assert updated_account.name == account_name
|
92
|
+
|
93
|
+
finally:
|
94
|
+
# Clean up
|
95
|
+
account_manager.drop_account(account_name)
|
96
|
+
|
97
|
+
def test_alter_user(self, test_client):
|
98
|
+
"""Test altering a user"""
|
99
|
+
account_manager = AccountManager(test_client)
|
100
|
+
|
101
|
+
# Create user first
|
102
|
+
username = "test_user_002"
|
103
|
+
password = "test_password_002"
|
104
|
+
|
105
|
+
user = account_manager.create_user(username, password)
|
106
|
+
assert user is not None
|
107
|
+
|
108
|
+
try:
|
109
|
+
# Alter user (change password)
|
110
|
+
new_password = "new_password_002"
|
111
|
+
account_manager.alter_user(username, password=new_password)
|
112
|
+
|
113
|
+
finally:
|
114
|
+
# Clean up
|
115
|
+
account_manager.drop_user(username)
|
116
|
+
|
117
|
+
def test_account_management_with_transaction(self, test_client):
|
118
|
+
"""Test account management with transaction (limited by MatrixOne)"""
|
119
|
+
account_manager = AccountManager(test_client)
|
120
|
+
|
121
|
+
# Create account outside transaction (MatrixOne limitation)
|
122
|
+
account_name = "test_account_003"
|
123
|
+
admin_name = "test_admin_003"
|
124
|
+
password = "test_password_003"
|
125
|
+
|
126
|
+
account = account_manager.create_account(account_name, admin_name, password)
|
127
|
+
assert account is not None
|
128
|
+
|
129
|
+
try:
|
130
|
+
# Create user outside transaction (MatrixOne limitation)
|
131
|
+
username = "test_user_003"
|
132
|
+
user_password = "test_password_003"
|
133
|
+
|
134
|
+
user = account_manager.create_user(username, user_password)
|
135
|
+
assert user is not None
|
136
|
+
|
137
|
+
# Test transaction with regular SQL operations only
|
138
|
+
with test_client.transaction():
|
139
|
+
# Only regular SQL operations are allowed in transactions
|
140
|
+
result = test_client.execute("SELECT 1 as test_value")
|
141
|
+
assert result is not None
|
142
|
+
assert len(result.rows) > 0
|
143
|
+
|
144
|
+
# Alter user outside transaction
|
145
|
+
account_manager.alter_user(username, password="new_password_003")
|
146
|
+
|
147
|
+
# Drop user outside transaction
|
148
|
+
account_manager.drop_user(username)
|
149
|
+
|
150
|
+
finally:
|
151
|
+
# Clean up account
|
152
|
+
account_manager.drop_account(account_name)
|
153
|
+
|
154
|
+
@pytest.mark.asyncio
|
155
|
+
async def test_async_account_management(self, test_async_client):
|
156
|
+
"""Test async account management"""
|
157
|
+
# Test async client with direct SQL operations instead of AccountManager
|
158
|
+
# since AccountManager is designed for sync clients only
|
159
|
+
|
160
|
+
# Test basic async operations
|
161
|
+
result = await test_async_client.execute("SELECT 1 as test_value, USER() as user_info")
|
162
|
+
assert result is not None
|
163
|
+
assert len(result.rows) > 0
|
164
|
+
assert result.rows[0][0] == 1 # test_value should be 1
|
165
|
+
|
166
|
+
# Test async transaction
|
167
|
+
async with test_async_client.transaction():
|
168
|
+
result = await test_async_client.execute("SELECT 2 as test_value")
|
169
|
+
assert result is not None
|
170
|
+
assert len(result.rows) > 0
|
171
|
+
assert result.rows[0][0] == 2
|
172
|
+
|
173
|
+
# Test async database info queries
|
174
|
+
result = await test_async_client.execute("SHOW DATABASES")
|
175
|
+
assert result is not None
|
176
|
+
assert len(result.rows) > 0
|
177
|
+
|
178
|
+
def test_account_error_handling(self, test_client):
|
179
|
+
"""Test account error handling"""
|
180
|
+
account_manager = AccountManager(test_client)
|
181
|
+
|
182
|
+
# Test creating account with invalid name
|
183
|
+
try:
|
184
|
+
account_manager.create_account("", "", "password")
|
185
|
+
assert False, "Should have failed with empty admin name"
|
186
|
+
except AccountError:
|
187
|
+
pass # Expected
|
188
|
+
|
189
|
+
# Test dropping non-existent account
|
190
|
+
try:
|
191
|
+
account_manager.drop_account("non_existent_account")
|
192
|
+
assert False, "Should have failed with non-existent account"
|
193
|
+
except AccountError:
|
194
|
+
pass # Expected
|