app-store-connect-mcp-server
- tests
"""
Test suite for the DuckDB-based MCP server module.
Uses pytest for running the tests.
"""
import tempfile
from pathlib import Path
import duckdb
import pytest
from mcp_server_duckdb.config import Config
from mcp_server_duckdb.server import DuckDBDatabase
def test_create_database_in_nonexistent_directory():
"""
Ensure that when running in non-readonly mode, a missing directory
can be created, and the database file is also created.
"""
with tempfile.TemporaryDirectory() as tmpdir:
db_path = Path(tmpdir) / "subdir" / "test.db"
config = Config(db_path=db_path, readonly=False)
db = DuckDBDatabase(config)
assert db_path.exists(), "Database file should be created automatically in non-readonly mode."
# Optionally verify basic queries:
db.execute_query("CREATE TABLE test (id INTEGER)")
db.execute_query("INSERT INTO test VALUES (1)")
result = db.execute_query("SELECT * FROM test")
assert result == [(1,)], "Should be able to insert data when readonly=False."
def test_readonly_mode_missing_directory():
"""
If the target directory does not exist and readonly=True,
an exception should be raised.
"""
with tempfile.TemporaryDirectory() as tmpdir:
db_path = Path(tmpdir) / "subdir" / "test.db"
config = Config(db_path=db_path, readonly=True)
# The directory 'subdir' does not exist, so it should raise an error.
with pytest.raises(ValueError, match="Database directory does not exist"):
DuckDBDatabase(config)
def test_readonly_mode_missing_db_file():
"""
If the directory exists but the DB file itself does not exist and readonly=True,
an exception should be raised.
"""
with tempfile.TemporaryDirectory() as tmpdir:
subdir = Path(tmpdir) / "subdir"
subdir.mkdir(exist_ok=True)
db_path = subdir / "test.db"
config = Config(db_path=db_path, readonly=True)
with pytest.raises(ValueError, match="Database file does not exist"):
DuckDBDatabase(config)
def test_normal_mode_create_and_write():
"""
In non-readonly mode, we should be able to create a table and perform write operations.
"""
with tempfile.TemporaryDirectory() as tmpdir:
db_path = Path(tmpdir) / "test.db"
config = Config(db_path=db_path, readonly=False)
db = DuckDBDatabase(config)
db.execute_query("CREATE TABLE users (id INTEGER, name VARCHAR)")
db.execute_query("INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')")
result = db.execute_query("SELECT * FROM users ORDER BY id")
assert result == [(1, "Alice"), (2, "Bob")], "Data insertion in non-readonly mode should succeed."
def test_readonly_mode_write_query_error():
"""
In readonly mode, attempting a write operation (INSERT) should raise a duckdb.Error.
"""
with tempfile.TemporaryDirectory() as tmpdir:
# First, create the database in writable mode
db_path = Path(tmpdir) / "test.db"
config_writable = Config(db_path=db_path, readonly=False)
db_writable = DuckDBDatabase(config_writable)
db_writable.execute_query("CREATE TABLE test (val INTEGER)")
# Now open the same DB in readonly mode
config_readonly = Config(db_path=db_path, readonly=True)
db_readonly = DuckDBDatabase(config_readonly)
# Attempting to write should fail
with pytest.raises(duckdb.Error):
db_readonly.execute_query("INSERT INTO test VALUES (42)")
def test_readonly_flag_behavior():
"""
Tests behavior for readonly=True vs. readonly=False.
1) readonly=False: should allow table creation and data insertion.
2) readonly=True: should raise an error when attempting to insert data.
"""
with tempfile.TemporaryDirectory() as tmpdir:
# 1) Writable configuration
db_path_writable = Path(tmpdir) / "writable.db"
config_writable = Config(db_path=db_path_writable, readonly=False)
db_writable = DuckDBDatabase(config_writable)
db_writable.execute_query("CREATE TABLE items (id INTEGER)")
db_writable.execute_query("INSERT INTO items VALUES (100)")
result = db_writable.execute_query("SELECT * FROM items")
assert result == [(100,)], "Should successfully write when readonly=False"
# 2) Readonly configuration
db_path_readonly = Path(tmpdir) / "readonly.db"
# Create the DB file in non-readonly mode first
config_init = Config(db_path=db_path_readonly, readonly=False)
DuckDBDatabase(config_init).execute_query("CREATE TABLE ro_test (val INTEGER)")
# Reopen in readonly mode
config_ro = Config(db_path=db_path_readonly, readonly=True)
db_ro = DuckDBDatabase(config_ro)
# Attempt to write should fail
with pytest.raises(duckdb.Error):
db_ro.execute_query("INSERT INTO ro_test VALUES (999)")