319 lines
9.9 KiB
Lua
319 lines
9.9 KiB
Lua
-- tests/runtime_limits_test.lua
|
||
-- Тестирование runtime-ограничений на размер коллекции и документа
|
||
|
||
local function setup_limits_test()
|
||
print("=== Setup Runtime Limits Test ===")
|
||
|
||
db.execute("CREATE DATABASE IF NOT EXISTS limits_test")
|
||
db.execute("USE limits_test")
|
||
|
||
-- Устанавливаем тестовые ограничения
|
||
db.execute([[
|
||
SET RUNTIME_LIMITS {
|
||
global_max_doc_size_mb = 1,
|
||
global_max_coll_size_mb = 10,
|
||
global_max_docs_per_coll = 1000
|
||
}
|
||
]])
|
||
|
||
db.execute([[
|
||
CREATE COLLECTION IF NOT EXISTS test_collection
|
||
]])
|
||
|
||
return true
|
||
end
|
||
|
||
local function test_max_document_size()
|
||
print("\n=== Test 1: Max Document Size ===")
|
||
|
||
-- Создаём документ меньше лимита (0.5 MB)
|
||
local small_doc = {
|
||
_id = "small_doc",
|
||
data = string.rep("x", 500 * 1024) -- 500KB
|
||
}
|
||
|
||
local success, err = pcall(function()
|
||
return db.execute(string.format(
|
||
"INSERT INTO test_collection VALUES (%s)",
|
||
db.json_encode(small_doc)
|
||
))
|
||
end)
|
||
|
||
if success then
|
||
print("✅ Small document (500KB) inserted successfully")
|
||
else
|
||
print("❌ Small document rejected: " .. tostring(err))
|
||
return false
|
||
end
|
||
|
||
-- Создаём документ больше лимита (2 MB)
|
||
local large_doc = {
|
||
_id = "large_doc",
|
||
data = string.rep("x", 2 * 1024 * 1024) -- 2MB
|
||
}
|
||
|
||
success, err = pcall(function()
|
||
return db.execute(string.format(
|
||
"INSERT INTO test_collection VALUES (%s)",
|
||
db.json_encode(large_doc)
|
||
))
|
||
end)
|
||
|
||
if not success and string.find(err or "", "exceeds limit") then
|
||
print("✅ Large document (2MB) correctly rejected")
|
||
return true
|
||
else
|
||
print("❌ Large document should have been rejected: " .. tostring(err))
|
||
return false
|
||
end
|
||
end
|
||
|
||
local function test_max_collection_size()
|
||
print("\n=== Test 2: Max Collection Size ===")
|
||
|
||
local inserted = 0
|
||
local rejected = 0
|
||
|
||
for i = 1, 20 do
|
||
-- Каждый документ ~1MB
|
||
local doc = {
|
||
_id = string.format("doc_%d", i),
|
||
data = string.rep("x", 900 * 1024), -- 900KB
|
||
index = i
|
||
}
|
||
|
||
local success, err = pcall(function()
|
||
return db.execute(string.format(
|
||
"INSERT INTO test_collection VALUES (%s)",
|
||
db.json_encode(doc)
|
||
))
|
||
end)
|
||
|
||
if success then
|
||
inserted = inserted + 1
|
||
print(string.format(" Inserted doc %d, total inserted: %d", i, inserted))
|
||
else
|
||
rejected = rejected + 1
|
||
if string.find(err or "", "exceeds limit") then
|
||
print(string.format(" Doc %d rejected: collection size limit reached", i))
|
||
end
|
||
end
|
||
end
|
||
|
||
print(string.format("Final: %d inserted, %d rejected", inserted, rejected))
|
||
|
||
-- Должно быть вставлено не более 10 документов (~10MB)
|
||
if inserted <= 11 and inserted >= 8 then
|
||
print("✅ Collection size limit working correctly")
|
||
return true
|
||
else
|
||
print(string.format("❌ Unexpected number of inserts: %d", inserted))
|
||
return false
|
||
end
|
||
end
|
||
|
||
local function test_max_document_count()
|
||
print("\n=== Test 3: Max Document Count ===")
|
||
|
||
-- Создаём новую коллекцию для этого теста
|
||
db.execute("CREATE COLLECTION IF NOT EXISTS count_test")
|
||
|
||
-- Устанавливаем лимит в 50 документов
|
||
db.execute([[
|
||
ALTER COLLECTION count_test SET LIMITS {
|
||
max_documents = 50
|
||
}
|
||
]])
|
||
|
||
local inserted = 0
|
||
local rejected = 0
|
||
|
||
for i = 1, 60 do
|
||
local doc = {
|
||
_id = string.format("count_doc_%d", i),
|
||
value = i
|
||
}
|
||
|
||
local success, err = pcall(function()
|
||
return db.execute(string.format(
|
||
"INSERT INTO count_test VALUES (%s)",
|
||
db.json_encode(doc)
|
||
))
|
||
end)
|
||
|
||
if success then
|
||
inserted = inserted + 1
|
||
else
|
||
rejected = rejected + 1
|
||
end
|
||
end
|
||
|
||
print(string.format("Inserted: %d, Rejected: %d", inserted, rejected))
|
||
|
||
if inserted == 50 and rejected == 10 then
|
||
print("✅ Document count limit working correctly")
|
||
return true
|
||
else
|
||
print(string.format("❌ Expected 50 inserts, got %d", inserted))
|
||
return false
|
||
end
|
||
|
||
db.execute("DROP COLLECTION count_test")
|
||
end
|
||
|
||
local function test_collection_override_limits()
|
||
print("\n=== Test 4: Collection Override Limits ===")
|
||
|
||
-- Создаём коллекцию с собственными лимитами
|
||
db.execute([[
|
||
CREATE COLLECTION override_test
|
||
WITH LIMITS {
|
||
max_doc_size_mb = 5,
|
||
max_docs = 200
|
||
}
|
||
]])
|
||
|
||
-- Проверяем, что можно вставить 4MB документ
|
||
local large_doc = {
|
||
_id = "large_override",
|
||
data = string.rep("y", 4 * 1024 * 1024)
|
||
}
|
||
|
||
local success, err = pcall(function()
|
||
return db.execute(string.format(
|
||
"INSERT INTO override_test VALUES (%s)",
|
||
db.json_encode(large_doc)
|
||
))
|
||
end)
|
||
|
||
if not success then
|
||
print("❌ Failed to insert 4MB document with 5MB limit: " .. tostring(err))
|
||
return false
|
||
end
|
||
|
||
print("✅ Collection override limits working correctly")
|
||
|
||
db.execute("DROP COLLECTION override_test")
|
||
return true
|
||
end
|
||
|
||
local function test_runtime_limits_metrics()
|
||
print("\n=== Test 5: Runtime Limits Metrics ===")
|
||
|
||
local metrics = db.execute("SHOW RUNTIME_LIMITS METRICS")
|
||
local metrics_data = db.json_decode(metrics)
|
||
|
||
print("Runtime limits metrics:")
|
||
for key, value in pairs(metrics_data) do
|
||
print(string.format(" %s: %s", key, tostring(value)))
|
||
end
|
||
|
||
local required_fields = {
|
||
"rejected_by_size",
|
||
"rejected_by_doc_count",
|
||
"rejected_by_coll_size",
|
||
"global_max_doc_size_mb",
|
||
"global_max_coll_size_mb",
|
||
"global_max_docs_per_coll",
|
||
"enabled"
|
||
}
|
||
|
||
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 test_dynamic_limit_change()
|
||
print("\n=== Test 6: Dynamic Limit Change ===")
|
||
|
||
-- Создаём коллекцию
|
||
db.execute("CREATE COLLECTION dynamic_test")
|
||
|
||
-- Меняем лимиты динамически
|
||
db.execute("ALTER COLLECTION dynamic_test SET LIMITS { max_docs = 10 }")
|
||
|
||
-- Вставляем 10 документов
|
||
for i = 1, 10 do
|
||
db.execute(string.format(
|
||
"INSERT INTO dynamic_test VALUES {_id = 'dyn_%d'}", i
|
||
))
|
||
end
|
||
|
||
-- Пытаемся вставить 11-й
|
||
local success, err = pcall(function()
|
||
return db.execute("INSERT INTO dynamic_test VALUES {_id = 'dyn_11'}")
|
||
end)
|
||
|
||
if success then
|
||
print("❌ Should have rejected after dynamic limit change")
|
||
return false
|
||
end
|
||
|
||
-- Увеличиваем лимит
|
||
db.execute("ALTER COLLECTION dynamic_test SET LIMITS { max_docs = 20 }")
|
||
|
||
-- Теперь 11-й должен пройти
|
||
success, err = pcall(function()
|
||
return db.execute("INSERT INTO dynamic_test VALUES {_id = 'dyn_11'}")
|
||
end)
|
||
|
||
if not success then
|
||
print("❌ Should have accepted after limit increase")
|
||
return false
|
||
end
|
||
|
||
print("✅ Dynamic limit change working correctly")
|
||
|
||
db.execute("DROP COLLECTION dynamic_test")
|
||
return true
|
||
end
|
||
|
||
local function cleanup_limits()
|
||
print("\n=== Cleanup ===")
|
||
db.execute("DROP DATABASE IF EXISTS limits_test")
|
||
db.execute("SET RUNTIME_LIMITS DEFAULT")
|
||
print("Cleanup completed")
|
||
end
|
||
|
||
local function run_all_runtime_limits_tests()
|
||
print("╔══════════════════════════════════════════════════════════════╗")
|
||
print("║ RUNTIME LIMITS TESTS SUITE ║")
|
||
print("╚══════════════════════════════════════════════════════════════╝")
|
||
|
||
setup_limits_test()
|
||
|
||
local results = {
|
||
test_max_document_size(),
|
||
test_max_collection_size(),
|
||
test_max_document_count(),
|
||
test_collection_override_limits(),
|
||
test_runtime_limits_metrics(),
|
||
test_dynamic_limit_change()
|
||
}
|
||
|
||
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_limits()
|
||
|
||
return passed == #results
|
||
end
|
||
|
||
return run_all_runtime_limits_tests()
|