Files
futriix/tests/load_test.lua

244 lines
9.7 KiB
Lua
Raw 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/load_test.lua
-- Комплексное нагрузочное тестирование всех компонентов
local function run_load_test()
print("╔══════════════════════════════════════════════════════════════╗")
print("║ LOAD TEST SUITE ║")
print("╚══════════════════════════════════════════════════════════════╝")
local test_results = {}
-- Функция для замера производительности
local function measure_performance(name, fn, iterations)
print(string.format("\n📊 Measuring: %s (%d iterations)", name, iterations))
local times = {}
local errors = 0
for i = 1, iterations do
local start = os.clock()
local success, err = pcall(fn)
local duration = os.clock() - start
if success then
table.insert(times, duration)
else
errors = errors + 1
print(string.format(" Error #%d: %s", i, tostring(err)))
end
end
if #times == 0 then
print(string.format(" ❌ All %d iterations failed", iterations))
return nil
end
-- Вычисляем статистику
table.sort(times)
local min = times[1]
local max = times[#times]
local sum = 0
for _, t in ipairs(times) do sum = sum + t end
local avg = sum / #times
local p50 = times[math.floor(#times * 0.5)]
local p95 = times[math.floor(#times * 0.95)]
local p99 = times[math.floor(#times * 0.99)]
print(string.format([[
Results:
Success rate: %.1f%% (%d/%d)
Min: %.3f ms
Max: %.3f ms
Avg: %.3f ms
P50: %.3f ms
P95: %.3f ms
P99: %.3f ms
]], (iterations - errors) / iterations * 100, iterations - errors, iterations,
min * 1000, max * 1000, avg * 1000, p50 * 1000, p95 * 1000, p99 * 1000))
return {
success_rate = (iterations - errors) / iterations,
min_ms = min * 1000,
max_ms = max * 1000,
avg_ms = avg * 1000,
p50_ms = p50 * 1000,
p95_ms = p95 * 1000,
p99_ms = p99 * 1000
}
end
-- Подготовка
print("\n🔧 Preparing test environment...")
db.execute("CREATE DATABASE IF NOT EXISTS load_test")
db.execute("USE load_test")
db.execute([[
CREATE COLLECTION IF NOT EXISTS load_collection
WITH SETTINGS {
max_documents = 1000000,
auto_index_id = true
}
]])
-- Тест 1: Вставка документов
local insert_results = measure_performance("INSERT", function()
local doc = {
_id = string.format("doc_%d_%d", os.time(), math.random(1, 1000000)),
timestamp = os.time() * 1000,
value = math.random(1, 10000),
data = string.rep("x", 100)
}
db.execute(string.format(
"INSERT INTO load_collection VALUES (%s)",
db.json_encode(doc)
))
end, 1000)
-- Тест 2: Чтение по ID
local read_results = measure_performance("SELECT BY ID", function()
db.execute(string.format("SELECT * FROM load_collection WHERE _id = 'doc_%d'",
math.random(1, 1000)))
end, 1000)
-- Тест 3: Обновление
local update_results = measure_performance("UPDATE", function()
db.execute(string.format([[
UPDATE load_collection
SET value = %d, updated_at = %d
WHERE _id = 'doc_%d'
]], math.random(1, 10000), os.time() * 1000, math.random(1, 1000)))
end, 1000)
-- Тест 4: Удаление
local delete_results = measure_performance("DELETE", function()
db.execute(string.format("DELETE FROM load_collection WHERE _id = 'temp_%d'",
math.random(1, 100)))
end, 500)
-- Тест 5: Сложный запрос с фильтром
local query_results = measure_performance("COMPLEX QUERY", function()
db.execute([[
SELECT * FROM load_collection
WHERE value > 5000
AND value < 8000
LIMIT 50
]])
end, 500)
-- Тест 6: Агрегация
local agg_results = measure_performance("AGGREGATION", function()
db.execute([[
SELECT
COUNT(*) as total,
AVG(value) as avg_value,
MIN(value) as min_value,
MAX(value) as max_value
FROM load_collection
WHERE value > 1000
]])
end, 200)
-- Тест 7: Пакетная вставка
local batch_results = measure_performance("BATCH INSERT", function()
local docs = {}
for i = 1, 10 do
table.insert(docs, {
_id = string.format("batch_%d_%d", os.time(), i),
value = i
})
end
db.execute(string.format(
"INSERT INTO load_collection VALUES %s",
db.json_encode(docs)
))
end, 100)
-- Тест 8: Транзакция
local tx_results = measure_performance("TRANSACTION", function()
db.execute("BEGIN TRANSACTION")
db.execute("INSERT INTO load_collection VALUES {_id = 'tx1', value = 1}")
db.execute("INSERT INTO load_collection VALUES {_id = 'tx2', value = 2}")
db.execute("COMMIT")
end, 100)
-- Тест 9: Поиск по индексу
db.execute("CREATE INDEX idx_value ON load_collection(value)")
local index_results = measure_performance("INDEX SEARCH", function()
db.execute("SELECT * FROM load_collection WHERE value = 5000")
end, 500)
-- Тест 10: Сканирование с лимитом
local scan_results = measure_performance("SCAN WITH LIMIT", function()
db.execute("SELECT * FROM load_collection LIMIT 1000")
end, 100)
-- Сводка
print("\n╔══════════════════════════════════════════════════════════════╗")
print("║ PERFORMANCE SUMMARY ║")
print("╚══════════════════════════════════════════════════════════════╝")
local function print_summary(name, results)
if results then
local status = results.success_rate > 0.99 and "" or "⚠️"
print(string.format("%s %-15s: avg=%.2fms, p95=%.2fms, success=%.1f%%",
status, name, results.avg_ms, results.p95_ms, results.success_rate * 100))
else
print(string.format("❌ %-15s: FAILED", name))
end
end
print_summary("INSERT", insert_results)
print_summary("SELECT", read_results)
print_summary("UPDATE", update_results)
print_summary("DELETE", delete_results)
print_summary("QUERY", query_results)
print_summary("AGGREGATE", agg_results)
print_summary("BATCH", batch_results)
print_summary("TRANSACTION", tx_results)
print_summary("INDEX SEARCH", index_results)
print_summary("SCAN", scan_results)
-- Общий вердикт
local success_rate = (insert_results and insert_results.success_rate or 0) +
(read_results and read_results.success_rate or 0) +
(update_results and update_results.success_rate or 0) +
(delete_results and delete_results.success_rate or 0) +
(query_results and query_results.success_rate or 0) +
(agg_results and agg_results.success_rate or 0) +
(batch_results and batch_results.success_rate or 0) +
(tx_results and tx_results.success_rate or 0) +
(index_results and index_results.success_rate or 0) +
(scan_results and scan_results.success_rate or 0)
success_rate = success_rate / 10 * 100
print("\n╔══════════════════════════════════════════════════════════════╗")
print("║ FINAL VERDICT ║")
print("╚══════════════════════════════════════════════════════════════╝")
if success_rate > 99 then
print("✅ EXCELLENT: All operations performing optimally")
elseif success_rate > 95 then
print("✅ GOOD: Most operations performing well")
elseif success_rate > 90 then
print("⚠️ ACCEPTABLE: Some operations need optimization")
else
print("❌ POOR: Significant performance issues detected")
end
print(string.format("Overall success rate: %.1f%%", success_rate))
-- Очистка
print("\n🧹 Cleaning up...")
db.execute("DROP DATABASE IF EXISTS load_test")
return success_rate > 90
end
-- Запуск всех тестов
local function run_all_tests()
print("🚀 STARTING FULL TEST SUITE\n")