435 lines
14 KiB
Lua
435 lines
14 KiB
Lua
-- Test suite for ErrorHandler module
|
|
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
|
|
|
require("testing.loveStub")
|
|
local luaunit = require("testing.luaunit")
|
|
local ErrorHandler = require("modules.ErrorHandler")
|
|
local ErrorCodes = require("modules.ErrorCodes")
|
|
|
|
TestErrorHandler = {}
|
|
|
|
function TestErrorHandler:setUp()
|
|
-- Reset debug mode and logging before each test
|
|
ErrorHandler.setDebugMode(false)
|
|
ErrorHandler.setLogTarget("none") -- Disable logging during tests
|
|
end
|
|
|
|
function TestErrorHandler:tearDown()
|
|
-- Clean up any test log files
|
|
os.remove("test-errors.log")
|
|
for i = 1, 5 do
|
|
os.remove("test-errors.log." .. i)
|
|
end
|
|
end
|
|
|
|
-- Test: error() throws with correct format (backward compatibility)
|
|
function TestErrorHandler:test_error_throws_with_format()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "Something went wrong")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "[FlexLove - TestModule] Error: Something went wrong")
|
|
end
|
|
|
|
-- Test: error() with error code
|
|
function TestErrorHandler:test_error_with_code()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Invalid property type")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "[FlexLove - TestModule] Error [FLEXLOVE_VAL_001]")
|
|
luaunit.assertStrContains(err, "Invalid property type")
|
|
end
|
|
|
|
-- Test: error() with error code and details
|
|
function TestErrorHandler:test_error_with_code_and_details()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Invalid property type", {
|
|
property = "width",
|
|
expected = "number",
|
|
got = "string",
|
|
})
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "[FLEXLOVE_VAL_001]")
|
|
luaunit.assertStrContains(err, "Details:")
|
|
luaunit.assertStrContains(err, "Property: width")
|
|
luaunit.assertStrContains(err, "Expected: number")
|
|
luaunit.assertStrContains(err, "Got: string")
|
|
end
|
|
|
|
-- Test: error() with error code, details, and custom suggestion
|
|
function TestErrorHandler:test_error_with_code_details_and_suggestion()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Invalid property type", {
|
|
property = "width",
|
|
expected = "number",
|
|
got = "string",
|
|
}, "Use a number like width = 100")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "Suggestion: Use a number like width = 100")
|
|
end
|
|
|
|
-- Test: error() with code uses automatic suggestion
|
|
function TestErrorHandler:test_error_with_code_uses_auto_suggestion()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Invalid property type", {
|
|
property = "width",
|
|
})
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "Suggestion:")
|
|
-- Should contain suggestion from ErrorCodes
|
|
local suggestion = ErrorCodes.getSuggestion("VAL_001")
|
|
luaunit.assertStrContains(err, suggestion)
|
|
end
|
|
|
|
-- Test: warn() prints with correct format (backward compatibility)
|
|
function TestErrorHandler:test_warn_prints_with_format()
|
|
-- Capture print output by mocking print
|
|
local captured = nil
|
|
local originalPrint = print
|
|
print = function(msg)
|
|
captured = msg
|
|
end
|
|
|
|
ErrorHandler.warn("TestModule", "This is a warning")
|
|
|
|
print = originalPrint
|
|
|
|
luaunit.assertNotNil(captured, "warn() should print")
|
|
luaunit.assertEquals(captured, "[FlexLove - TestModule] Warning: This is a warning")
|
|
end
|
|
|
|
-- Test: warn() with error code
|
|
function TestErrorHandler:test_warn_with_code()
|
|
local captured = nil
|
|
local originalPrint = print
|
|
print = function(msg)
|
|
captured = msg
|
|
end
|
|
|
|
ErrorHandler.warn("TestModule", "VAL_001", "Potentially invalid property")
|
|
|
|
print = originalPrint
|
|
|
|
luaunit.assertNotNil(captured, "warn() should print")
|
|
luaunit.assertStrContains(captured, "[FlexLove - TestModule] Warning [FLEXLOVE_VAL_001]")
|
|
luaunit.assertStrContains(captured, "Potentially invalid property")
|
|
end
|
|
|
|
-- Test: warn() with details
|
|
function TestErrorHandler:test_warn_with_details()
|
|
local captured = nil
|
|
local originalPrint = print
|
|
print = function(msg)
|
|
captured = msg
|
|
end
|
|
|
|
ErrorHandler.warn("TestModule", "VAL_001", "Check this property", {
|
|
property = "height",
|
|
value = "auto",
|
|
})
|
|
|
|
print = originalPrint
|
|
|
|
luaunit.assertNotNil(captured, "warn() should print")
|
|
luaunit.assertStrContains(captured, "Details:")
|
|
luaunit.assertStrContains(captured, "Property: height")
|
|
luaunit.assertStrContains(captured, "Value: auto")
|
|
end
|
|
|
|
-- Test: assertNotNil returns true for non-nil value
|
|
function TestErrorHandler:test_assertNotNil_returns_true_for_valid()
|
|
local result = ErrorHandler.assertNotNil("TestModule", "some value", "testParam")
|
|
luaunit.assertTrue(result, "assertNotNil should return true for non-nil value")
|
|
end
|
|
|
|
-- Test: assertNotNil throws for nil value (now uses error codes)
|
|
function TestErrorHandler:test_assertNotNil_throws_for_nil()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.assertNotNil("TestModule", nil, "testParam")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "assertNotNil should throw for nil")
|
|
luaunit.assertStrContains(err, "[FLEXLOVE_VAL_003]")
|
|
luaunit.assertStrContains(err, "Required parameter missing")
|
|
luaunit.assertStrContains(err, "testParam")
|
|
end
|
|
|
|
-- Test: assertType returns true for correct type
|
|
function TestErrorHandler:test_assertType_returns_true_for_valid()
|
|
local result = ErrorHandler.assertType("TestModule", "hello", "string", "testParam")
|
|
luaunit.assertTrue(result, "assertType should return true for correct type")
|
|
|
|
result = ErrorHandler.assertType("TestModule", 123, "number", "testParam")
|
|
luaunit.assertTrue(result, "assertType should return true for number")
|
|
|
|
result = ErrorHandler.assertType("TestModule", {}, "table", "testParam")
|
|
luaunit.assertTrue(result, "assertType should return true for table")
|
|
end
|
|
|
|
-- Test: assertType throws for wrong type (now uses error codes)
|
|
function TestErrorHandler:test_assertType_throws_for_wrong_type()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.assertType("TestModule", 123, "string", "testParam")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "assertType should throw for wrong type")
|
|
luaunit.assertStrContains(err, "[FLEXLOVE_VAL_001]")
|
|
luaunit.assertStrContains(err, "Invalid property type")
|
|
luaunit.assertStrContains(err, "testParam")
|
|
end
|
|
|
|
-- Test: assertRange returns true for value in range
|
|
function TestErrorHandler:test_assertRange_returns_true_for_valid()
|
|
local result = ErrorHandler.assertRange("TestModule", 5, 0, 10, "testParam")
|
|
luaunit.assertTrue(result, "assertRange should return true for value in range")
|
|
|
|
result = ErrorHandler.assertRange("TestModule", 0, 0, 10, "testParam")
|
|
luaunit.assertTrue(result, "assertRange should accept min boundary")
|
|
|
|
result = ErrorHandler.assertRange("TestModule", 10, 0, 10, "testParam")
|
|
luaunit.assertTrue(result, "assertRange should accept max boundary")
|
|
end
|
|
|
|
-- Test: assertRange throws for value below min (now uses error codes)
|
|
function TestErrorHandler:test_assertRange_throws_for_below_min()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.assertRange("TestModule", -1, 0, 10, "testParam")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "assertRange should throw for value below min")
|
|
luaunit.assertStrContains(err, "[FLEXLOVE_VAL_002]")
|
|
luaunit.assertStrContains(err, "Property value out of range")
|
|
luaunit.assertStrContains(err, "testParam")
|
|
end
|
|
|
|
-- Test: assertRange throws for value above max (now uses error codes)
|
|
function TestErrorHandler:test_assertRange_throws_for_above_max()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.assertRange("TestModule", 11, 0, 10, "testParam")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "assertRange should throw for value above max")
|
|
luaunit.assertStrContains(err, "[FLEXLOVE_VAL_002]")
|
|
luaunit.assertStrContains(err, "Property value out of range")
|
|
end
|
|
|
|
-- Test: warnDeprecated prints deprecation warning
|
|
function TestErrorHandler:test_warnDeprecated_prints_message()
|
|
local captured = nil
|
|
local originalPrint = print
|
|
print = function(msg)
|
|
captured = msg
|
|
end
|
|
|
|
ErrorHandler.warnDeprecated("TestModule", "oldFunction", "newFunction")
|
|
|
|
print = originalPrint
|
|
|
|
luaunit.assertNotNil(captured, "warnDeprecated should print")
|
|
luaunit.assertStrContains(captured, "'oldFunction' is deprecated. Use 'newFunction' instead")
|
|
end
|
|
|
|
-- Test: warnCommonMistake prints helpful message
|
|
function TestErrorHandler:test_warnCommonMistake_prints_message()
|
|
local captured = nil
|
|
local originalPrint = print
|
|
print = function(msg)
|
|
captured = msg
|
|
end
|
|
|
|
ErrorHandler.warnCommonMistake("TestModule", "Width is zero", "Set width to positive value")
|
|
|
|
print = originalPrint
|
|
|
|
luaunit.assertNotNil(captured, "warnCommonMistake should print")
|
|
luaunit.assertStrContains(captured, "Width is zero. Suggestion: Set width to positive value")
|
|
end
|
|
|
|
-- Test: debug mode enables stack traces
|
|
function TestErrorHandler:test_debug_mode_enables_stack_trace()
|
|
ErrorHandler.setDebugMode(true)
|
|
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test error")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "Stack trace:")
|
|
|
|
ErrorHandler.setDebugMode(false)
|
|
end
|
|
|
|
-- Test: setStackTrace independently
|
|
function TestErrorHandler:test_set_stack_trace()
|
|
ErrorHandler.setStackTrace(true)
|
|
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test error")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "Stack trace:")
|
|
|
|
ErrorHandler.setStackTrace(false)
|
|
end
|
|
|
|
-- Test: error code validation
|
|
function TestErrorHandler:test_invalid_error_code_fallback()
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "INVALID_CODE", "This is a message")
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
-- Should treat as message (backward compatibility)
|
|
luaunit.assertStrContains(err, "INVALID_CODE")
|
|
luaunit.assertStrContains(err, "This is a message")
|
|
end
|
|
|
|
-- Test: details formatting with long values
|
|
function TestErrorHandler:test_details_with_long_values()
|
|
local longValue = string.rep("x", 150)
|
|
local success, err = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test", {
|
|
shortValue = "short",
|
|
longValue = longValue,
|
|
})
|
|
end)
|
|
|
|
luaunit.assertFalse(success, "error() should throw")
|
|
luaunit.assertStrContains(err, "ShortValue: short")
|
|
-- Long value should be truncated
|
|
luaunit.assertStrContains(err, "...")
|
|
end
|
|
|
|
-- Test: file logging
|
|
function TestErrorHandler:test_file_logging()
|
|
ErrorHandler.setLogTarget("file")
|
|
ErrorHandler.setLogFile("test-errors.log")
|
|
|
|
-- Trigger an error (will be caught)
|
|
local success = pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test file logging")
|
|
end)
|
|
|
|
-- Check file was created and contains log
|
|
local file = io.open("test-errors.log", "r")
|
|
luaunit.assertNotNil(file, "Log file should be created")
|
|
|
|
if file then
|
|
local content = file:read("*all")
|
|
file:close()
|
|
|
|
luaunit.assertStrContains(content, "ERROR")
|
|
luaunit.assertStrContains(content, "TestModule")
|
|
luaunit.assertStrContains(content, "Test file logging")
|
|
end
|
|
|
|
-- Cleanup
|
|
ErrorHandler.setLogTarget("none")
|
|
os.remove("test-errors.log")
|
|
end
|
|
|
|
-- Test: log level filtering
|
|
function TestErrorHandler:test_log_level_filtering()
|
|
ErrorHandler.setLogTarget("file")
|
|
ErrorHandler.setLogFile("test-errors.log")
|
|
ErrorHandler.setLogLevel("ERROR") -- Only log errors, not warnings
|
|
|
|
-- Trigger a warning (should not be logged)
|
|
ErrorHandler.warn("TestModule", "VAL_001", "Test warning")
|
|
|
|
-- Trigger an error (should be logged)
|
|
pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test error")
|
|
end)
|
|
|
|
-- Check file
|
|
local file = io.open("test-errors.log", "r")
|
|
if file then
|
|
local content = file:read("*all")
|
|
file:close()
|
|
|
|
luaunit.assertStrContains(content, "Test error")
|
|
luaunit.assertFalse(content:find("Test warning") ~= nil, "Warning should not be logged")
|
|
end
|
|
|
|
-- Cleanup
|
|
ErrorHandler.setLogTarget("none")
|
|
ErrorHandler.setLogLevel("WARNING")
|
|
os.remove("test-errors.log")
|
|
end
|
|
|
|
-- Test: JSON format
|
|
function TestErrorHandler:test_json_format()
|
|
ErrorHandler.setLogTarget("file")
|
|
ErrorHandler.setLogFile("test-errors.log")
|
|
ErrorHandler.setLogFormat("json")
|
|
|
|
pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test JSON", {
|
|
property = "width",
|
|
})
|
|
end)
|
|
|
|
local file = io.open("test-errors.log", "r")
|
|
if file then
|
|
local content = file:read("*all")
|
|
file:close()
|
|
|
|
-- Should be valid JSON-like
|
|
luaunit.assertStrContains(content, '"level":"ERROR"')
|
|
luaunit.assertStrContains(content, '"module":"TestModule"')
|
|
luaunit.assertStrContains(content, '"message":"Test JSON"')
|
|
luaunit.assertStrContains(content, '"details":')
|
|
end
|
|
|
|
-- Cleanup
|
|
ErrorHandler.setLogTarget("none")
|
|
ErrorHandler.setLogFormat("human")
|
|
os.remove("test-errors.log")
|
|
end
|
|
|
|
-- Test: log rotation
|
|
function TestErrorHandler:test_log_rotation()
|
|
ErrorHandler.setLogTarget("file")
|
|
ErrorHandler.setLogFile("test-errors.log")
|
|
ErrorHandler.enableLogRotation({ maxSize = 100, maxFiles = 2 }) -- Very small for testing
|
|
|
|
-- Write multiple errors to trigger rotation
|
|
for i = 1, 10 do
|
|
pcall(function()
|
|
ErrorHandler.error("TestModule", "VAL_001", "Test rotation error number " .. i)
|
|
end)
|
|
end
|
|
|
|
-- Check that rotation occurred (main file should exist)
|
|
local file = io.open("test-errors.log", "r")
|
|
luaunit.assertNotNil(file, "Main log file should exist")
|
|
if file then
|
|
file:close()
|
|
end
|
|
|
|
-- Check that rotated files might exist (depending on log size)
|
|
-- We won't assert this as it depends on exact message size
|
|
|
|
-- Cleanup
|
|
ErrorHandler.setLogTarget("none")
|
|
ErrorHandler.enableLogRotation(true) -- Reset to defaults
|
|
os.remove("test-errors.log")
|
|
os.remove("test-errors.log.1")
|
|
os.remove("test-errors.log.2")
|
|
end
|
|
|
|
if not _G.RUNNING_ALL_TESTS then
|
|
os.exit(luaunit.LuaUnit.run())
|
|
end
|