Files
futriix/tests/schema_migration_test.lua

338 lines
11 KiB
Lua
Raw Permalink Normal View History

2026-06-12 18:08:10 +00:00
-- tests/schema_migration_test.lua
-- Тестирование миграции схемы данных
local function setup_schema_test()
print("=== Setup Schema Migration Test ===")
db.execute("CREATE DATABASE IF NOT EXISTS schema_test")
db.execute("USE schema_test")
-- Создаём коллекцию со старой схемой
db.execute([[
CREATE COLLECTION IF NOT EXISTS products
WITH SCHEMA {
version = "1.0.0",
fields = {
_id = {type = "string", required = true},
name = {type = "string", required = true},
price = {type = "float"}
}
}
]])
-- Вставляем тестовые данные
for i = 1, 50 do
db.execute(string.format([[
INSERT INTO products VALUES {
_id = "prod_%d",
name = "Product %d",
price = %.2f
}
]], i, i, math.random(100, 1000) / 100))
end
print("Inserted 50 test products")
return true
end
local function test_schema_version()
print("\n=== Test 1: Schema Version ===")
local version = db.execute("SHOW SCHEMA VERSION")
print(string.format("Current schema version: %s", version))
if version and version ~= "" then
print("✅ Schema version retrieved")
return true
else
print("❌ Failed to get schema version")
return false
end
end
local function test_add_field_migration()
print("\n=== Test 2: Add Field Migration ===")
-- Миграция: добавляем поле description
local migration = [[
MIGRATE SCHEMA products
ADD FIELD description {
type = "string",
default = "No description",
required = false
}
]]
local result = db.execute(migration)
print("Migration result: " .. tostring(result))
-- Проверяем, что у старых документов появилось поле description
local sample = db.execute("SELECT * FROM products LIMIT 1")
local sample_data = db.json_decode(sample)
if sample_data[1].description == "No description" then
print("✅ Field added and default value applied")
return true
else
print("❌ Field migration failed")
return false
end
end
local function test_change_field_type_migration()
print("\n=== Test 3: Change Field Type Migration ===")
-- Миграция: меняем тип price на string с префиксом "$"
local migration = [[
MIGRATE SCHEMA products
MODIFY FIELD price
TYPE string
TRANSFORM value -> "$" .. tostring(value)
]]
local result = db.execute(migration)
print("Migration result: " .. tostring(result))
-- Проверяем преобразование
local sample = db.execute("SELECT price FROM products LIMIT 1")
local sample_data = db.json_decode(sample)
if string.sub(sample_data[1].price, 1, 1) == "$" then
print("✅ Field type conversion successful")
return true
else
print("❌ Field type conversion failed")
return false
end
end
local function test_rename_field_migration()
print("\n=== Test 4: Rename Field Migration ===")
-- Миграция: переименовываем name в title
local migration = [[
MIGRATE SCHEMA products
RENAME FIELD name TO title
]]
local result = db.execute(migration)
print("Migration result: " .. tostring(result))
-- Проверяем, что поле переименовано
local sample = db.execute("SELECT title FROM products LIMIT 1")
local sample_data = db.json_decode(sample)
local check_name = db.execute("SELECT name FROM products LIMIT 1")
if sample_data[1].title and check_name == "null" then
print("✅ Field renamed successfully")
return true
else
print("❌ Field rename failed")
return false
end
end
local function test_remove_field_migration()
print("\n=== Test 5: Remove Field Migration ===")
-- Миграция: удаляем поле description
local migration = [[
MIGRATE SCHEMA products
REMOVE FIELD description
]]
local result = db.execute(migration)
print("Migration result: " .. tostring(result))
-- Проверяем, что поле удалено
local sample = db.execute("SELECT * FROM products LIMIT 1")
local sample_data = db.json_decode(sample)
if sample_data[1].description == nil then
print("✅ Field removed successfully")
return true
else
print("❌ Field removal failed")
return false
end
end
local function test_add_validation_migration()
print("\n=== Test 6: Add Validation Migration ===")
-- Добавляем валидацию для поля price
local migration = [[
MIGRATE SCHEMA products
ADD VALIDATION price {
min = 0,
max = 10000,
type = "float"
}
]]
local result = db.execute(migration)
print("Migration result: " .. tostring(result))
-- Проверяем валидацию
local success, err = pcall(function()
return db.execute("INSERT INTO products VALUES {_id = 'invalid', title = 'Invalid', price = 20000}")
end)
if not success and string.find(err or "", "validation") then
print("✅ Validation added and working")
return true
else
print("❌ Validation not working correctly")
return false
end
end
local function test_rollback_migration()
print("\n=== Test 7: Rollback Migration ===")
-- Сохраняем текущее состояние
local before_state = db.execute("SHOW SCHEMA STATUS")
-- Откатываем последнюю миграцию
local result = db.execute("ROLLBACK SCHEMA MIGRATION")
print("Rollback result: " .. tostring(result))
-- Проверяем, что validation убрана
local success, err = pcall(function()
return db.execute("INSERT INTO products VALUES {_id = 'rollback_test', title = 'Rollback Test', price = 20000}")
end)
if success then
print("✅ Rollback successful - validation removed")
return true
else
print("❌ Rollback failed")
return false
end
end
local function test_schema_migration_history()
print("\n=== Test 8: Schema Migration History ===")
local history = db.execute("SHOW SCHEMA MIGRATION HISTORY")
local history_data = db.json_decode(history)
print("Migration history:")
for i, migration in ipairs(history_data) do
print(string.format(" %d: %s - %s (applied: %s)",
i, migration.id, migration.description,
os.date("%Y-%m-%d %H:%M:%S", migration.applied_at / 1000)))
end
if #history_data >= 5 then
print("✅ Migration history contains multiple entries")
return true
else
print("⚠️ Migration history shorter than expected")
return false
end
end
local function test_lazy_schema_migration()
print("\n=== Test 9: Lazy Schema Migration ===")
-- Включаем ленивую миграцию
db.execute("SET SCHEMA MIGRATION STRATEGY lazy")
-- Меняем схему
db.execute([[
MIGRATE SCHEMA products
ADD FIELD tags {
type = "array",
default = {}
}
]])
-- Существующие документы не должны иметь tags сразу
local sample = db.execute("SELECT tags FROM products LIMIT 1")
local sample_data = db.json_decode(sample)
-- При первом чтении tags может отсутствовать
-- При следующем чтении (после миграции) должно появиться
print("✅ Lazy migration configured")
return true
end
local function test_schema_migration_metrics()
print("\n=== Test 10: Schema Migration Metrics ===")
local metrics = db.execute("SHOW SCHEMA MIGRATION METRICS")
local metrics_data = db.json_decode(metrics)
print("Migration metrics:")
for key, value in pairs(metrics_data) do
print(string.format(" %s: %s", key, tostring(value)))
end
local required_fields = {
"total_migrations",
"applied_migrations",
"pending_migrations",
"current_version"
}
for _, field in ipairs(required_fields) do
if metrics_data[field] == nil then
print("❌ Missing metric: " .. field)
return false
end
end
print("✅ All required metrics present")
return true
end
local function cleanup_schema()
print("\n=== Cleanup ===")
db.execute("DROP DATABASE IF EXISTS schema_test")
print("Cleanup completed")
end
local function run_all_schema_migration_tests()
print("╔══════════════════════════════════════════════════════════════╗")
print("║ SCHEMA MIGRATION TESTS SUITE ║")
print("╚══════════════════════════════════════════════════════════════╝")
setup_schema_test()
local results = {
test_schema_version(),
test_add_field_migration(),
test_change_field_type_migration(),
test_rename_field_migration(),
test_remove_field_migration(),
test_add_validation_migration(),
test_rollback_migration(),
test_schema_migration_history(),
test_lazy_schema_migration(),
test_schema_migration_metrics()
}
print("\n╔══════════════════════════════════════════════════════════════╗")
print("║ TEST RESULTS ║")
print("╚══════════════════════════════════════════════════════════════╝")
local passed = 0
for i, result in ipairs(results) do
local status = result and "✅ PASSED" or "⚠️ SKIPPED/FAILED"
print(string.format("Test %d: %s", i, status))
if result then passed = passed + 1 end
end
print(string.format("\nTotal: %d/%d tests passed", passed, #results))
cleanup_schema()
return passed == #results
end
return run_all_schema_migration_tests()