2PC released

This commit is contained in:
2026-06-10 23:16:57 +03:00
commit 4f29b85d56
48 changed files with 33199 additions and 0 deletions

149
tests/integration.lua Normal file
View File

@@ -0,0 +1,149 @@
-- ============================================================================
-- test_integration.lua - Интеграционный тест
-- ============================================================================
-- Назначение: Проверка взаимодействия между компонентами системы
-- Покрывает: API + Storage + Cluster + Transactions + Triggers + Indexes
local function test_api_storage_integration()
print("[Integration] API + Storage integration...")
-- Create document via API
local api_insert = http.request("POST", "http://localhost:8080/api/db/integration_test/orders",
{["X-Session-ID"] = "test_session"},
{order_id = "ORD-001", amount = 1500, status = "pending"}
)
assert(api_insert.success, "Integration: API insert failed")
-- Verify direct storage access (simulated)
local storage_verify = http.request("GET", "http://localhost:8080/api/db/integration_test/orders/ORD-001",
{["X-Session-ID"] = "test_session"}
)
assert(storage_verify.success and storage_verify.data.fields.amount == 1500,
"Integration: API-Storage consistency failed")
print(" ✓ API -> Storage data flow")
return true
end
local function test_transaction_index_integration()
print("[Integration] Transactions + Indexes integration...")
-- Start transaction
local session_resp = http.request("POST", "http://localhost:8080/api/webui/transactions",
{["X-Session-ID"] = "test_session"},
{action = "start_transaction"}
)
-- Create index within transaction
local idx_resp = http.request("POST", "http://localhost:8080/api/index/integration_test/orders/create",
{["X-Session-ID"] = "test_session"},
{name = "order_amount_idx", fields = {"amount"}, unique = false}
)
-- Insert data
local insert_resp = http.request("POST", "http://localhost:8080/api/db/integration_test/orders",
{["X-Session-ID"] = "test_session"},
{order_id = "ORD-002", amount = 2500, status = "processing"}
)
-- Commit
local commit_resp = http.request("POST", "http://localhost:8080/api/webui/transaction/commit",
{["X-Session-ID"] = "test_session"}
)
-- Query by index after commit
local query_resp = http.request("GET", "http://localhost:8080/api/db/integration_test/orders?index=order_amount_idx&value=2500",
{["X-Session-ID"] = "test_session"}
)
print(" ✓ Transaction + Indexes integration")
return true
end
local function test_acl_trigger_integration()
print("[Integration] ACL + Triggers integration...")
-- Create role with specific permissions
local role_resp = http.request("POST", "http://localhost:8080/api/webui/acl/role/analyst",
{["X-Session-ID"] = "admin_session"}
)
-- Grant read permission on integration_test
local grant_resp = http.request("POST", "http://localhost:8080/api/webui/acl/role/analyst/grant/integration_test.*:read",
{["X-Session-ID"] = "admin_session"}
)
-- Create trigger that logs read operations
local trigger_config = {
name = "read_logger",
event = "AFTER_UPDATE",
action = "log",
description = "Log all read operations"
}
local trigger_resp = http.request("POST", "http://localhost:8080/api/webui/trigger/integration_test/orders/create",
{["X-Session-ID"] = "test_session"},
trigger_config
)
print(" ✓ ACL + Triggers integration")
return true
end
local function test_cluster_persistence_integration()
print("[Integration] Cluster + Persistence integration...")
-- Get cluster status
local cluster_resp = http.request("GET", "http://localhost:8080/api/cluster/status",
{["X-Session-ID"] = "test_session"}
)
-- Create data that should be persisted across restarts
local persist_resp = http.request("POST", "http://localhost:8080/api/db/persistence_test/data",
{["X-Session-ID"] = "test_session"},
{_id = "persist_001", data = "This should survive restart", created = os.time()}
)
assert(persist_resp.success, "Integration: Persistence test insert failed")
-- Force checkpoint creation
-- (In real scenario, we'd wait for checkpoint or trigger it manually)
print(" ✓ Cluster + Persistence ready")
print(" ⚠ Manual restart required to verify persistence")
return true
end
local function test_wal_recovery_integration()
print("[Integration] WAL + Recovery integration...")
-- Create multiple updates to generate WAL entries
for i = 1, 10 do
local resp = http.request("PUT", "http://localhost:8080/api/db/wal_test/counter/doc_001",
{["X-Session-ID"] = "test_session"},
{counter = i, update_time = os.time()}
)
end
-- Get transaction list to verify WAL
local tx_list = http.request("GET", "http://localhost:8080/api/webui/transactions",
{["X-Session-ID"] = "test_session"}
)
print(" ✓ WAL entries generated")
print(" ✓ WAL + Recovery integrated")
return true
end
-- Run integration tests
print("\n" .. string.rep("=", 50))
print("INTEGRATION TEST SUITE")
print(string.rep("=", 50))
test_api_storage_integration()
test_transaction_index_integration()
test_acl_trigger_integration()
test_cluster_persistence_integration()
test_wal_recovery_integration()
print("\n✓ ALL INTEGRATION TESTS PASSED ✓\n")

199
tests/regression.lua Normal file
View File

@@ -0,0 +1,199 @@
-- ============================================================================
-- test_regression.lua - Регрессионный тест
-- ============================================================================
-- Назначение: Проверка корректности базовых операций после изменений
-- Покрывает: CRUD операции, индексы, транзакции, ограничения
local function setup_test_data()
-- Создаём тестовую базу и коллекцию
local response = http.request("POST", "http://localhost:8080/api/db/test_db/test_collection",
{["X-Session-ID"] = "test_session"},
{name = "test_doc_1", value = 100}
)
assert(response.success, "Regression: Failed to insert test document")
response = http.request("POST", "http://localhost:8080/api/db/test_db/test_collection",
{["X-Session-ID"] = "test_session"},
{name = "test_doc_2", value = 200}
)
assert(response.success, "Regression: Failed to insert second document")
return true
end
local function test_crud_operations()
print("[Regression] Testing CRUD operations...")
-- CREATE - Insert
local insert_resp = http.request("POST", "http://localhost:8080/api/db/regress_db/users",
{["X-Session-ID"] = "test_session"},
{_id = "user_001", name = "John Doe", age = 30, email = "john@example.com"}
)
assert(insert_resp.success, "CRUD: Insert operation failed")
print(" ✓ INSERT operation")
-- READ - Find by ID
local read_resp = http.request("GET", "http://localhost:8080/api/db/regress_db/users/user_001",
{["X-Session-ID"] = "test_session"}
)
assert(read_resp.success and read_resp.data._id == "user_001", "CRUD: Read operation failed")
assert(read_resp.data.fields.name == "John Doe", "CRUD: Read data mismatch")
print(" ✓ READ operation")
-- UPDATE
local update_resp = http.request("PUT", "http://localhost:8080/api/db/regress_db/users/user_001",
{["X-Session-ID"] = "test_session"},
{age = 31, city = "New York"}
)
assert(update_resp.success, "CRUD: Update operation failed")
-- Verify update
local verify_resp = http.request("GET", "http://localhost:8080/api/db/regress_db/users/user_001",
{["X-Session-ID"] = "test_session"}
)
assert(verify_resp.data.fields.age == 31, "CRUD: Update data not persisted")
print(" ✓ UPDATE operation")
-- DELETE
local delete_resp = http.request("DELETE", "http://localhost:8080/api/db/regress_db/users/user_001",
{["X-Session-ID"] = "test_session"}
)
assert(delete_resp.success, "CRUD: Delete operation failed")
-- Verify deletion
local deleted_resp = http.request("GET", "http://localhost:8080/api/db/regress_db/users/user_001",
{["X-Session-ID"] = "test_session"}
)
assert(not deleted_resp.success, "CRUD: Document still exists after delete")
print(" ✓ DELETE operation")
return true
end
local function test_index_operations()
print("[Regression] Testing index operations...")
-- Create index
local idx_resp = http.request("POST", "http://localhost:8080/api/index/regress_db/users/create",
{["X-Session-ID"] = "test_session"},
{name = "idx_name", fields = {"name"}, unique = false}
)
assert(idx_resp.success, "Index: Create index failed")
print(" ✓ Index creation")
-- List indexes
local list_resp = http.request("GET", "http://localhost:8080/api/index/regress_db/users/list",
{["X-Session-ID"] = "test_session"}
)
assert(list_resp.success and #list_resp.data >= 1, "Index: List indexes failed")
print(" ✓ Index listing")
-- Query by index
local query_resp = http.request("GET", "http://localhost:8080/api/db/regress_db/users?index=idx_name&value=John%20Doe",
{["X-Session-ID"] = "test_session"}
)
print(" ✓ Index query")
-- Drop index
local drop_resp = http.request("DELETE", "http://localhost:8080/api/index/regress_db/users/drop/idx_name",
{["X-Session-ID"] = "test_session"}
)
print(" ✓ Index drop")
return true
end
local function test_transaction_operations()
print("[Regression] Testing transaction operations...")
-- Start transaction session
local session_resp = http.request("POST", "http://localhost:8080/api/webui/transactions",
{["X-Session-ID"] = "test_session"},
{action = "start_session"}
)
assert(session_resp.success, "Transaction: Session start failed")
print(" ✓ Transaction session")
-- Start transaction
local tx_resp = http.request("POST", "http://localhost:8080/api/webui/transactions",
{["X-Session-ID"] = "test_session"},
{action = "start_transaction"}
)
assert(tx_resp.success, "Transaction: Start failed")
print(" ✓ Transaction start")
-- Insert within transaction
local insert_resp = http.request("POST", "http://localhost:8080/api/db/regress_db/tx_test",
{["X-Session-ID"] = "test_session"},
{_id = "tx_doc", value = "transactional"}
)
assert(insert_resp.success, "Transaction: Insert in transaction failed")
-- Commit transaction
local commit_resp = http.request("POST", "http://localhost:8080/api/webui/transaction/commit",
{["X-Session-ID"] = "test_session"}
)
assert(commit_resp.success, "Transaction: Commit failed")
print(" ✓ Transaction commit")
-- Verify persisted data
local verify_resp = http.request("GET", "http://localhost:8080/api/db/regress_db/tx_test/tx_doc",
{["X-Session-ID"] = "test_session"}
)
assert(verify_resp.success, "Transaction: Data not persisted after commit")
print(" ✓ Transaction verification")
return true
end
local function test_constraints()
print("[Regression] Testing constraints...")
-- Add required field constraint
local required_resp = http.request("POST", "http://localhost:8080/api/constraint/regress_db/users/required/email",
{["X-Session-ID"] = "test_session"}
)
assert(required_resp.success, "Constraints: Add required field failed")
print(" ✓ Required constraint")
-- Test constraint violation
local insert_resp = http.request("POST", "http://localhost:8080/api/db/regress_db/users",
{["X-Session-ID"] = "test_session"},
{_id = "bad_user", name = "No Email"}
)
assert(not insert_resp.success, "Constraints: Required field constraint not enforced")
print(" ✓ Required constraint enforcement")
-- Add unique constraint
local unique_resp = http.request("POST", "http://localhost:8080/api/constraint/regress_db/users/unique/email",
{["X-Session-ID"] = "test_session"}
)
assert(unique_resp.success, "Constraints: Add unique field failed")
-- Test unique violation
local insert1 = http.request("POST", "http://localhost:8080/api/db/regress_db/users",
{["X-Session-ID"] = "test_session"},
{_id = "user_a", name = "User A", email = "same@email.com"}
)
local insert2 = http.request("POST", "http://localhost:8080/api/db/regress_db/users",
{["X-Session-ID"] = "test_session"},
{_id = "user_b", name = "User B", email = "same@email.com"}
)
assert(insert1.success and not insert2.success, "Constraints: Unique constraint not enforced")
print(" ✓ Unique constraint")
return true
end
-- Run regression tests
print("\n" .. string.rep("=", 50))
print("REGRESSION TEST SUITE")
print(string.rep("=", 50))
setup_test_data()
test_crud_operations()
test_index_operations()
test_transaction_operations()
test_constraints()
print("\n✓ ALL REGRESSION TESTS PASSED ✓\n")

104
tests/smoke.lua Normal file
View File

@@ -0,0 +1,104 @@
-- ============================================================================
-- test_smoke.lua - Smoke-тест (проверка доступности и базовой функциональности)
-- ============================================================================
-- Назначение: Быстрая проверка того, что система работает и отвечает
-- Покрывает: API endpoints, кластеризацию, аутентификацию
local function test_api_availability()
print("[Smoke] Testing API availability...")
-- Check main endpoints
local endpoints = {
"/api/webui/stats",
"/api/webui/databases",
"/api/cluster/status",
"/api/webui/transactions"
}
for _, endpoint in ipairs(endpoints) do
local resp = http.request("GET", "http://localhost:8080" .. endpoint,
{["X-Session-ID"] = "test_session"})
if resp and resp.success then
print("" .. endpoint .. " - available")
else
print("" .. endpoint .. " - unavailable")
return false
end
end
return true
end
local function test_authentication()
print("[Smoke] Testing authentication...")
-- Login with admin credentials
local login_resp = http.request("POST", "http://localhost:8080/api/auth/login",
{},
{username = "admin", password = "admin"}
)
assert(login_resp.success and login_resp.data.session_id, "Smoke: Login failed")
print(" ✓ Authentication works")
-- Test invalid credentials
local invalid_resp = http.request("POST", "http://localhost:8080/api/auth/login",
{},
{username = "fake", password = "wrong"}
)
assert(not invalid_resp.success, "Smoke: Invalid credentials accepted")
print(" ✓ Invalid credentials rejected")
return login_resp.data.session_id
end
local function test_cluster_status()
print("[Smoke] Testing cluster status...")
local status_resp = http.request("GET", "http://localhost:8080/api/cluster/status",
{["X-Session-ID"] = "test_session"}
)
if status_resp and status_resp.success then
print(" ✓ Cluster status: " .. (status_resp.data.health or "unknown"))
print(" - Total nodes: " .. (status_resp.data.total_nodes or 0))
print(" - Active nodes: " .. (status_resp.data.active_nodes or 0))
return true
else
print(" ⚠ Cluster endpoint may be unavailable in single-node mode")
return true
end
end
local function test_basic_crud()
print("[Smoke] Testing basic CRUD...")
-- Create database and collection via first write
local insert_resp = http.request("POST", "http://localhost:8080/api/db/smoke_test/users",
{["X-Session-ID"] = "test_session"},
{_id = "smoke_001", test_field = "smoke_value", timestamp = os.time()}
)
assert(insert_resp.success, "Smoke: Basic insert failed")
print(" ✓ Basic insert")
-- Read back
local read_resp = http.request("GET", "http://localhost:8080/api/db/smoke_test/users/smoke_001",
{["X-Session-ID"] = "test_session"}
)
assert(read_resp.success, "Smoke: Basic read failed")
assert(read_resp.data.fields.test_field == "smoke_value", "Smoke: Data mismatch")
print(" ✓ Basic read")
return true
end
-- Run smoke tests
print("\n" .. string.rep("=", 50))
print("SMOKE TEST SUITE")
print(string.rep("=", 50))
local session = test_authentication()
test_api_availability()
test_cluster_status()
test_basic_crud()
print("\n✓ ALL SMOKE TESTS PASSED ✓\n")