Skip to content

Commit 088b579

Browse files
committed
Add tests
1 parent d8ac36c commit 088b579

File tree

1 file changed

+89
-1
lines changed

1 file changed

+89
-1
lines changed

tests/core/state_sync/test_state_sync.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import re
44
import typing as t
5+
from types import ModuleType
56
from unittest.mock import call, patch
67

78
import duckdb # noqa: TID253
@@ -11,8 +12,16 @@
1112
from pytest_mock.plugin import MockerFixture
1213
from sqlglot import exp
1314

15+
from sqlmesh.cli.project_init import init_example_project
1416
from sqlmesh.core import constants as c
15-
from sqlmesh.core.config import EnvironmentSuffixTarget
17+
from sqlmesh.core.config import (
18+
Config,
19+
DuckDBConnectionConfig,
20+
EnvironmentSuffixTarget,
21+
GatewayConfig,
22+
ModelDefaultsConfig,
23+
)
24+
from sqlmesh.core.context import Context
1625
from sqlmesh.core.dialect import parse_one, schema_
1726
from sqlmesh.core.engine_adapter import create_engine_adapter
1827
from sqlmesh.core.environment import Environment, EnvironmentStatements
@@ -48,6 +57,7 @@
4857
)
4958
from sqlmesh.utils.date import now_timestamp, to_datetime, to_timestamp
5059
from sqlmesh.utils.errors import SQLMeshError
60+
from tests.utils.test_helpers import use_terminal_console
5161

5262
pytestmark = pytest.mark.slow
5363

@@ -3629,3 +3639,81 @@ def test_update_environment_statements(state_sync: EngineAdapterStateSync):
36293639
"@grant_schema_usage()",
36303640
"@grant_select_privileges()",
36313641
]
3642+
3643+
3644+
@use_terminal_console
3645+
def test_pre_checks(tmp_path, mocker):
3646+
init_example_project(tmp_path, engine_type="duckdb")
3647+
3648+
db_path = str(tmp_path / "db.db")
3649+
config = Config(
3650+
gateways={"main": GatewayConfig(connection=DuckDBConnectionConfig(database=db_path))},
3651+
model_defaults=ModelDefaultsConfig(dialect="duckdb"),
3652+
)
3653+
context = Context(paths=tmp_path, config=config)
3654+
context.plan(auto_apply=True, no_prompts=True)
3655+
3656+
def mock_migrate(state_sync, **kwargs):
3657+
pass
3658+
3659+
def mock_pre_check_with_warnings(state_sync):
3660+
return [
3661+
"Warning: This migration will break compatibility with older versions",
3662+
"Warning: You must update all model configurations before applying this migration",
3663+
"Warning: Existing snapshots will need to be rebuilt",
3664+
]
3665+
3666+
def mock_pre_check_without_warnings(state_sync):
3667+
return []
3668+
3669+
# Create a mock migration module with a pre_check function
3670+
mock_migration = ModuleType("v9999_test_pre_check")
3671+
3672+
setattr(mock_migration, "migrate", mock_migrate)
3673+
setattr(mock_migration, "pre_check", mock_pre_check_with_warnings)
3674+
3675+
versions_before_migrate = context.state_sync.get_versions()
3676+
3677+
import sqlmesh.core.state_sync as state_sync
3678+
3679+
test_migrations = state_sync.db.migrator.MIGRATIONS + [mock_migration]
3680+
3681+
# Test 1: Pre-check warnings are properly collected and displayed, user rejects migration
3682+
with (
3683+
patch.object(state_sync.db.migrator, "MIGRATIONS", test_migrations),
3684+
patch.object(context.console, "_confirm", return_value=False),
3685+
):
3686+
console = context.console
3687+
log_pre_check_warnings_spy = mocker.spy(console, "log_pre_check_warnings")
3688+
3689+
context.migrate(pre_check_only=False)
3690+
3691+
calls = log_pre_check_warnings_spy.mock_calls
3692+
assert len(calls) == 1
3693+
3694+
pre_check_warnings = calls[0].args[0]
3695+
assert len(pre_check_warnings) == 1
3696+
3697+
assert pre_check_warnings[0][0] == "v9999_test_pre_check"
3698+
assert len(pre_check_warnings[0][1]) == 3
3699+
assert all(warning.startswith("Warning:") for warning in pre_check_warnings[0][1])
3700+
3701+
assert context.state_sync.get_versions() == versions_before_migrate
3702+
3703+
update_versions_spy = mocker.spy(state_sync.db.version.VersionState, "update_versions")
3704+
3705+
# Test 2: User accepts migration after being notified about pre-check warnings
3706+
with (
3707+
patch.object(state_sync.db.migrator, "MIGRATIONS", test_migrations),
3708+
patch.object(context.console, "_confirm", return_value=True),
3709+
):
3710+
context.migrate(pre_check_only=False)
3711+
assert len(update_versions_spy.mock_calls) == 1
3712+
3713+
# Test 3: Pre-check without warning should automatically reuslt in a migration
3714+
setattr(mock_migration, "pre_check", mock_pre_check_without_warnings)
3715+
with patch.object(state_sync.db.migrator, "MIGRATIONS", test_migrations):
3716+
# Since the version module's SCHEMA_VERSION, etc, weren't patched, the old versions
3717+
# are still used, so the following should result in hitting the update_versions path
3718+
context.migrate(pre_check_only=False)
3719+
assert len(update_versions_spy.mock_calls) == 2

0 commit comments

Comments
 (0)