Files
futriix/tests/schema_migration_test.lua

338 lines
11 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 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()