Performance and reporting improvements
This commit is contained in:
@@ -517,6 +517,103 @@ function TestEventHandler:test_processTouchEvents_no_onEvent()
|
||||
handler:processTouchEvents()
|
||||
end
|
||||
|
||||
-- Test: onEventDeferred flag defers callback execution
|
||||
function TestEventHandler:test_onEventDeferred()
|
||||
-- Mock FlexLove module
|
||||
local deferredCallbacks = {}
|
||||
local MockFlexLove = {
|
||||
deferCallback = function(callback)
|
||||
table.insert(deferredCallbacks, callback)
|
||||
end
|
||||
}
|
||||
package.loaded["FlexLove"] = MockFlexLove
|
||||
|
||||
local eventsReceived = {}
|
||||
local handler = createEventHandler({
|
||||
onEventDeferred = true,
|
||||
onEvent = function(el, event)
|
||||
table.insert(eventsReceived, event)
|
||||
end
|
||||
})
|
||||
local element = createMockElement()
|
||||
handler:initialize(element)
|
||||
|
||||
local originalIsDown = love.mouse.isDown
|
||||
love.mouse.isDown = function(button)
|
||||
return button == 1
|
||||
end
|
||||
|
||||
-- Press and release mouse button
|
||||
handler:processMouseEvents(50, 50, true, true)
|
||||
love.mouse.isDown = function() return false end
|
||||
handler:processMouseEvents(50, 50, true, true)
|
||||
|
||||
-- Events should not be immediately executed
|
||||
luaunit.assertEquals(#eventsReceived, 0)
|
||||
|
||||
-- Should have deferred callbacks queued
|
||||
luaunit.assertTrue(#deferredCallbacks > 0)
|
||||
|
||||
-- Execute deferred callbacks
|
||||
for _, callback in ipairs(deferredCallbacks) do
|
||||
callback()
|
||||
end
|
||||
|
||||
-- Now events should be received
|
||||
luaunit.assertTrue(#eventsReceived > 0)
|
||||
|
||||
-- Check that we got a click event
|
||||
local hasClick = false
|
||||
for _, event in ipairs(eventsReceived) do
|
||||
if event.type == "click" then
|
||||
hasClick = true
|
||||
break
|
||||
end
|
||||
end
|
||||
luaunit.assertTrue(hasClick, "Should have received click event")
|
||||
|
||||
love.mouse.isDown = originalIsDown
|
||||
package.loaded["FlexLove"] = nil
|
||||
end
|
||||
|
||||
-- Test: onEventDeferred = false executes immediately
|
||||
function TestEventHandler:test_onEventDeferred_false()
|
||||
local eventsReceived = {}
|
||||
local handler = createEventHandler({
|
||||
onEventDeferred = false,
|
||||
onEvent = function(el, event)
|
||||
table.insert(eventsReceived, event)
|
||||
end
|
||||
})
|
||||
local element = createMockElement()
|
||||
handler:initialize(element)
|
||||
|
||||
local originalIsDown = love.mouse.isDown
|
||||
love.mouse.isDown = function(button)
|
||||
return button == 1
|
||||
end
|
||||
|
||||
-- Press and release mouse button
|
||||
handler:processMouseEvents(50, 50, true, true)
|
||||
love.mouse.isDown = function() return false end
|
||||
handler:processMouseEvents(50, 50, true, true)
|
||||
|
||||
-- Events should be immediately executed
|
||||
luaunit.assertTrue(#eventsReceived > 0)
|
||||
|
||||
-- Check that we got a click event
|
||||
local hasClick = false
|
||||
for _, event in ipairs(eventsReceived) do
|
||||
if event.type == "click" then
|
||||
hasClick = true
|
||||
break
|
||||
end
|
||||
end
|
||||
luaunit.assertTrue(hasClick, "Should have received click event")
|
||||
|
||||
love.mouse.isDown = originalIsDown
|
||||
end
|
||||
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
@@ -639,6 +639,99 @@ function TestFlexLove:testGetElementAtPositionOutside()
|
||||
luaunit.assertNil(found)
|
||||
end
|
||||
|
||||
-- Test: deferCallback() queues callback
|
||||
function TestFlexLove:testDeferCallbackQueuesCallback()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local called = false
|
||||
FlexLove.deferCallback(function()
|
||||
called = true
|
||||
end)
|
||||
|
||||
-- Callback should not be called immediately
|
||||
luaunit.assertFalse(called)
|
||||
|
||||
-- Callback should be called after executeDeferredCallbacks
|
||||
FlexLove.draw()
|
||||
luaunit.assertFalse(called) -- Still not called
|
||||
|
||||
FlexLove.executeDeferredCallbacks()
|
||||
luaunit.assertTrue(called) -- Now called
|
||||
end
|
||||
|
||||
-- Test: deferCallback() with multiple callbacks
|
||||
function TestFlexLove:testDeferCallbackMultiple()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local order = {}
|
||||
FlexLove.deferCallback(function()
|
||||
table.insert(order, 1)
|
||||
end)
|
||||
FlexLove.deferCallback(function()
|
||||
table.insert(order, 2)
|
||||
end)
|
||||
FlexLove.deferCallback(function()
|
||||
table.insert(order, 3)
|
||||
end)
|
||||
|
||||
FlexLove.draw()
|
||||
FlexLove.executeDeferredCallbacks()
|
||||
|
||||
luaunit.assertEquals(#order, 3)
|
||||
luaunit.assertEquals(order[1], 1)
|
||||
luaunit.assertEquals(order[2], 2)
|
||||
luaunit.assertEquals(order[3], 3)
|
||||
end
|
||||
|
||||
-- Test: deferCallback() with non-function argument
|
||||
function TestFlexLove:testDeferCallbackInvalidArgument()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
-- Should warn but not crash
|
||||
FlexLove.deferCallback("not a function")
|
||||
FlexLove.deferCallback(123)
|
||||
FlexLove.deferCallback(nil)
|
||||
|
||||
FlexLove.draw()
|
||||
luaunit.assertTrue(true)
|
||||
end
|
||||
|
||||
-- Test: deferCallback() clears queue after execution
|
||||
function TestFlexLove:testDeferCallbackClearsQueue()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local callCount = 0
|
||||
FlexLove.deferCallback(function()
|
||||
callCount = callCount + 1
|
||||
end)
|
||||
|
||||
FlexLove.draw()
|
||||
FlexLove.executeDeferredCallbacks() -- First execution
|
||||
luaunit.assertEquals(callCount, 1)
|
||||
|
||||
FlexLove.draw()
|
||||
FlexLove.executeDeferredCallbacks() -- Second execution should not call again
|
||||
luaunit.assertEquals(callCount, 1)
|
||||
end
|
||||
|
||||
-- Test: deferCallback() handles callback errors gracefully
|
||||
function TestFlexLove:testDeferCallbackWithError()
|
||||
FlexLove.setMode("retained")
|
||||
|
||||
local called = false
|
||||
FlexLove.deferCallback(function()
|
||||
error("Intentional error")
|
||||
end)
|
||||
FlexLove.deferCallback(function()
|
||||
called = true
|
||||
end)
|
||||
|
||||
-- Should not crash, second callback should still execute
|
||||
FlexLove.draw()
|
||||
FlexLove.executeDeferredCallbacks()
|
||||
luaunit.assertTrue(called)
|
||||
end
|
||||
|
||||
-- Test: External modules are exposed
|
||||
function TestFlexLove:testExternalModulesExposed()
|
||||
luaunit.assertNotNil(FlexLove.Animation)
|
||||
|
||||
199
testing/__tests__/font_cache_test.lua
Normal file
199
testing/__tests__/font_cache_test.lua
Normal file
@@ -0,0 +1,199 @@
|
||||
-- Test font cache optimizations
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local loveStub = require("testing.loveStub")
|
||||
|
||||
-- Set up stub before requiring modules
|
||||
_G.love = loveStub
|
||||
|
||||
local utils = require("modules.utils")
|
||||
|
||||
TestFontCache = {}
|
||||
|
||||
function TestFontCache:setUp()
|
||||
utils.clearFontCache()
|
||||
utils.resetFontCacheStats()
|
||||
love.timer.setTime(0) -- Reset timer for consistent timestamps
|
||||
end
|
||||
|
||||
function TestFontCache:tearDown()
|
||||
utils.clearFontCache()
|
||||
utils.resetFontCacheStats()
|
||||
utils.setFontCacheSize(50) -- Reset to default
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheHitOnRepeatedAccess()
|
||||
-- First access should be a miss
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.misses, 1)
|
||||
luaunit.assertEquals(stats1.hits, 0)
|
||||
|
||||
-- Second access should be a hit
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.hits, 1)
|
||||
luaunit.assertEquals(stats2.misses, 1)
|
||||
|
||||
-- Third access should also be a hit
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
local stats3 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats3.hits, 2)
|
||||
luaunit.assertEquals(stats3.misses, 1)
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheMissOnFirstAccess()
|
||||
utils.clearFontCache()
|
||||
utils.resetFontCacheStats()
|
||||
|
||||
utils.FONT_CACHE.get(24, nil)
|
||||
local stats = utils.getFontCacheStats()
|
||||
|
||||
luaunit.assertEquals(stats.misses, 1)
|
||||
luaunit.assertEquals(stats.hits, 0)
|
||||
end
|
||||
|
||||
function TestFontCache:testLRUEviction()
|
||||
utils.setFontCacheSize(3)
|
||||
|
||||
-- Load 3 fonts (fills cache) with time steps to ensure different timestamps
|
||||
utils.FONT_CACHE.get(10, nil)
|
||||
love.timer.step(0.001)
|
||||
utils.FONT_CACHE.get(12, nil)
|
||||
love.timer.step(0.001)
|
||||
utils.FONT_CACHE.get(14, nil)
|
||||
love.timer.step(0.001)
|
||||
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.size, 3)
|
||||
luaunit.assertEquals(stats1.evictions, 0)
|
||||
|
||||
-- Load 4th font (triggers eviction of font 10 - the oldest)
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.size, 3)
|
||||
luaunit.assertEquals(stats2.evictions, 1)
|
||||
|
||||
-- Access first font again - it should have been evicted (miss)
|
||||
local initialMisses = stats2.misses
|
||||
utils.FONT_CACHE.get(10, nil)
|
||||
|
||||
local stats3 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats3.misses, initialMisses + 1) -- Should be a miss
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheSizeLimitEnforced()
|
||||
utils.setFontCacheSize(5)
|
||||
|
||||
-- Load 10 fonts
|
||||
for i = 1, 10 do
|
||||
utils.FONT_CACHE.get(10 + i, nil)
|
||||
end
|
||||
|
||||
local stats = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats.size, 5)
|
||||
luaunit.assertTrue(stats.evictions >= 5)
|
||||
end
|
||||
|
||||
function TestFontCache:testFontRounding()
|
||||
-- Sizes should be rounded: 14.5 and 14.7 should map to same cache entry (15)
|
||||
utils.FONT_CACHE.get(14.5, nil)
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.misses, 1)
|
||||
|
||||
utils.FONT_CACHE.get(14.7, nil)
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.hits, 1) -- Should be a hit because both round to 15
|
||||
luaunit.assertEquals(stats2.misses, 1)
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheClear()
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
utils.FONT_CACHE.get(18, nil)
|
||||
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.size, 2)
|
||||
|
||||
utils.clearFontCache()
|
||||
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.size, 0)
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheKeyWithPath()
|
||||
-- Different cache keys for same size, different paths
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
utils.FONT_CACHE.get(16, "fonts/custom.ttf")
|
||||
|
||||
local stats = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats.misses, 2) -- Both should be misses
|
||||
luaunit.assertEquals(stats.size, 2)
|
||||
end
|
||||
|
||||
function TestFontCache:testPreloadFont()
|
||||
utils.clearFontCache()
|
||||
utils.resetFontCacheStats()
|
||||
|
||||
-- Preload multiple sizes
|
||||
utils.preloadFont(nil, {12, 14, 16, 18})
|
||||
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.size, 4)
|
||||
luaunit.assertEquals(stats1.misses, 4) -- All preloads are misses
|
||||
|
||||
-- Now access one - should be a hit
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.hits, 1)
|
||||
end
|
||||
|
||||
function TestFontCache:testCacheHitRate()
|
||||
utils.clearFontCache()
|
||||
utils.resetFontCacheStats()
|
||||
|
||||
-- 1 miss, 9 hits = 90% hit rate
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
for i = 1, 9 do
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
end
|
||||
|
||||
local stats = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats.hitRate, 0.9)
|
||||
end
|
||||
|
||||
function TestFontCache:testSetCacheSizeEvictsExcess()
|
||||
utils.setFontCacheSize(10)
|
||||
|
||||
-- Load 10 fonts
|
||||
for i = 1, 10 do
|
||||
utils.FONT_CACHE.get(10 + i, nil)
|
||||
end
|
||||
|
||||
local stats1 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats1.size, 10)
|
||||
|
||||
-- Reduce cache size - should trigger evictions
|
||||
utils.setFontCacheSize(5)
|
||||
|
||||
local stats2 = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats2.size, 5)
|
||||
luaunit.assertTrue(stats2.evictions >= 5)
|
||||
end
|
||||
|
||||
function TestFontCache:testMinimalCacheSize()
|
||||
-- Minimum cache size is 1
|
||||
utils.setFontCacheSize(0)
|
||||
utils.FONT_CACHE.get(16, nil)
|
||||
|
||||
local stats = utils.getFontCacheStats()
|
||||
luaunit.assertEquals(stats.size, 1)
|
||||
end
|
||||
|
||||
-- Run tests if executed directly
|
||||
if arg and arg[0]:find("font_cache_test%.lua$") then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
return TestFontCache
|
||||
167
testing/__tests__/performance_instrumentation_test.lua
Normal file
167
testing/__tests__/performance_instrumentation_test.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
-- Test Performance Instrumentation
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local loveStub = require("testing.loveStub")
|
||||
|
||||
-- Set up stub before requiring modules
|
||||
_G.love = loveStub
|
||||
|
||||
local Performance = require("modules.Performance")
|
||||
|
||||
TestPerformanceInstrumentation = {}
|
||||
|
||||
function TestPerformanceInstrumentation:setUp()
|
||||
Performance.reset()
|
||||
Performance.enable()
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:tearDown()
|
||||
Performance.disable()
|
||||
Performance.reset()
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testTimerStartStop()
|
||||
Performance.startTimer("test_operation")
|
||||
|
||||
-- Simulate some work
|
||||
local sum = 0
|
||||
for i = 1, 1000 do
|
||||
sum = sum + i
|
||||
end
|
||||
|
||||
local elapsed = Performance.stopTimer("test_operation")
|
||||
|
||||
luaunit.assertNotNil(elapsed)
|
||||
luaunit.assertTrue(elapsed >= 0)
|
||||
|
||||
local metrics = Performance.getMetrics()
|
||||
luaunit.assertNotNil(metrics.timings["test_operation"])
|
||||
luaunit.assertEquals(metrics.timings["test_operation"].count, 1)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testMultipleTimers()
|
||||
-- Start multiple timers
|
||||
Performance.startTimer("layout")
|
||||
Performance.startTimer("render")
|
||||
|
||||
local sum = 0
|
||||
for i = 1, 100 do sum = sum + i end
|
||||
|
||||
Performance.stopTimer("layout")
|
||||
Performance.stopTimer("render")
|
||||
|
||||
local metrics = Performance.getMetrics()
|
||||
luaunit.assertNotNil(metrics.timings["layout"])
|
||||
luaunit.assertNotNil(metrics.timings["render"])
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testFrameTiming()
|
||||
Performance.startFrame()
|
||||
|
||||
-- Simulate frame work
|
||||
local sum = 0
|
||||
for i = 1, 1000 do
|
||||
sum = sum + i
|
||||
end
|
||||
|
||||
Performance.endFrame()
|
||||
|
||||
local frameMetrics = Performance.getFrameMetrics()
|
||||
luaunit.assertNotNil(frameMetrics)
|
||||
luaunit.assertEquals(frameMetrics.frameCount, 1)
|
||||
luaunit.assertTrue(frameMetrics.lastFrameTime >= 0)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testDrawCallCounting()
|
||||
Performance.incrementCounter("draw_calls", 1)
|
||||
Performance.incrementCounter("draw_calls", 1)
|
||||
Performance.incrementCounter("draw_calls", 1)
|
||||
|
||||
local counter = Performance.getFrameCounter("draw_calls")
|
||||
luaunit.assertEquals(counter, 3)
|
||||
|
||||
-- Reset and check
|
||||
Performance.resetFrameCounters()
|
||||
counter = Performance.getFrameCounter("draw_calls")
|
||||
luaunit.assertEquals(counter, 0)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testHUDToggle()
|
||||
luaunit.assertFalse(Performance.getConfig().hudEnabled)
|
||||
|
||||
Performance.toggleHUD()
|
||||
luaunit.assertTrue(Performance.getConfig().hudEnabled)
|
||||
|
||||
Performance.toggleHUD()
|
||||
luaunit.assertFalse(Performance.getConfig().hudEnabled)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testEnableDisable()
|
||||
Performance.enable()
|
||||
luaunit.assertTrue(Performance.isEnabled())
|
||||
|
||||
Performance.disable()
|
||||
luaunit.assertFalse(Performance.isEnabled())
|
||||
|
||||
-- Timers should not record when disabled
|
||||
Performance.startTimer("disabled_test")
|
||||
local elapsed = Performance.stopTimer("disabled_test")
|
||||
luaunit.assertNil(elapsed)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testMeasureFunction()
|
||||
local function expensiveOperation(n)
|
||||
local sum = 0
|
||||
for i = 1, n do
|
||||
sum = sum + i
|
||||
end
|
||||
return sum
|
||||
end
|
||||
|
||||
local wrapped = Performance.measure("expensive_op", expensiveOperation)
|
||||
local result = wrapped(1000)
|
||||
|
||||
luaunit.assertEquals(result, 500500) -- sum of 1 to 1000
|
||||
|
||||
local metrics = Performance.getMetrics()
|
||||
luaunit.assertNotNil(metrics.timings["expensive_op"])
|
||||
luaunit.assertEquals(metrics.timings["expensive_op"].count, 1)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testMemoryTracking()
|
||||
Performance.updateMemory()
|
||||
|
||||
local memMetrics = Performance.getMemoryMetrics()
|
||||
luaunit.assertNotNil(memMetrics)
|
||||
luaunit.assertTrue(memMetrics.currentKb > 0)
|
||||
luaunit.assertTrue(memMetrics.currentMb > 0)
|
||||
luaunit.assertTrue(memMetrics.peakKb >= memMetrics.currentKb)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testExportJSON()
|
||||
Performance.startTimer("test_op")
|
||||
Performance.stopTimer("test_op")
|
||||
|
||||
local json = Performance.exportJSON()
|
||||
luaunit.assertNotNil(json)
|
||||
luaunit.assertTrue(string.find(json, "fps") ~= nil)
|
||||
luaunit.assertTrue(string.find(json, "test_op") ~= nil)
|
||||
end
|
||||
|
||||
function TestPerformanceInstrumentation:testExportCSV()
|
||||
Performance.startTimer("test_op")
|
||||
Performance.stopTimer("test_op")
|
||||
|
||||
local csv = Performance.exportCSV()
|
||||
luaunit.assertNotNil(csv)
|
||||
luaunit.assertTrue(string.find(csv, "Name,Average") ~= nil)
|
||||
luaunit.assertTrue(string.find(csv, "test_op") ~= nil)
|
||||
end
|
||||
|
||||
-- Run tests if executed directly
|
||||
if arg and arg[0]:find("performance_instrumentation_test%.lua$") then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
|
||||
return TestPerformanceInstrumentation
|
||||
156
testing/__tests__/performance_warnings_test.lua
Normal file
156
testing/__tests__/performance_warnings_test.lua
Normal file
@@ -0,0 +1,156 @@
|
||||
local luaunit = require("testing.luaunit")
|
||||
require("testing.loveStub")
|
||||
|
||||
local FlexLove = require("FlexLove")
|
||||
local Performance = require("modules.Performance")
|
||||
local Element = FlexLove.Element
|
||||
|
||||
TestPerformanceWarnings = {}
|
||||
|
||||
function TestPerformanceWarnings:setUp()
|
||||
-- Enable performance warnings
|
||||
Performance.setConfig("warningsEnabled", true)
|
||||
Performance.resetShownWarnings()
|
||||
end
|
||||
|
||||
function TestPerformanceWarnings:tearDown()
|
||||
-- Reset warnings
|
||||
Performance.resetShownWarnings()
|
||||
end
|
||||
|
||||
-- Test hierarchy depth warning
|
||||
function TestPerformanceWarnings:testHierarchyDepthWarning()
|
||||
-- Create a deep hierarchy (20 levels)
|
||||
local root = Element.new({
|
||||
id = "root",
|
||||
width = 100,
|
||||
height = 100,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
local current = root
|
||||
for i = 1, 20 do
|
||||
local child = Element.new({
|
||||
id = "child_" .. i,
|
||||
width = 50,
|
||||
height = 50,
|
||||
parent = current,
|
||||
}, Element.defaultDependencies)
|
||||
table.insert(current.children, child)
|
||||
current = child
|
||||
end
|
||||
|
||||
-- This should trigger a hierarchy depth warning
|
||||
root:layoutChildren()
|
||||
|
||||
-- Check that element was created successfully despite warning
|
||||
luaunit.assertNotNil(current)
|
||||
luaunit.assertEquals(current:getHierarchyDepth(), 20)
|
||||
end
|
||||
|
||||
-- Test element count warning
|
||||
function TestPerformanceWarnings:testElementCountWarning()
|
||||
-- Create a container with many children (simulating 1000+ elements)
|
||||
local root = Element.new({
|
||||
id = "root",
|
||||
width = 1000,
|
||||
height = 1000,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
-- Add many child elements
|
||||
for i = 1, 50 do -- Keep test fast, just verify the counting logic works
|
||||
local child = Element.new({
|
||||
id = "child_" .. i,
|
||||
width = 20,
|
||||
height = 20,
|
||||
parent = root,
|
||||
}, Element.defaultDependencies)
|
||||
table.insert(root.children, child)
|
||||
end
|
||||
|
||||
local count = root:countElements()
|
||||
luaunit.assertEquals(count, 51) -- root + 50 children
|
||||
end
|
||||
|
||||
-- Test animation count warning
|
||||
function TestPerformanceWarnings:testAnimationTracking()
|
||||
local root = Element.new({
|
||||
id = "root",
|
||||
width = 100,
|
||||
height = 100,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
-- Add some animated children
|
||||
for i = 1, 3 do
|
||||
local child = Element.new({
|
||||
id = "animated_child_" .. i,
|
||||
width = 20,
|
||||
height = 20,
|
||||
parent = root,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
-- Add mock animation
|
||||
child.animation = {
|
||||
update = function()
|
||||
return false
|
||||
end,
|
||||
interpolate = function()
|
||||
return { width = 20, height = 20 }
|
||||
end,
|
||||
}
|
||||
|
||||
table.insert(root.children, child)
|
||||
end
|
||||
|
||||
local animCount = root:_countActiveAnimations()
|
||||
luaunit.assertEquals(animCount, 3)
|
||||
end
|
||||
|
||||
-- Test warnings can be disabled
|
||||
function TestPerformanceWarnings:testWarningsCanBeDisabled()
|
||||
Performance.setConfig("warningsEnabled", false)
|
||||
|
||||
-- Create deep hierarchy
|
||||
local root = Element.new({
|
||||
id = "root",
|
||||
width = 100,
|
||||
height = 100,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
local current = root
|
||||
for i = 1, 20 do
|
||||
local child = Element.new({
|
||||
id = "child_" .. i,
|
||||
width = 50,
|
||||
height = 50,
|
||||
parent = current,
|
||||
}, Element.defaultDependencies)
|
||||
table.insert(current.children, child)
|
||||
current = child
|
||||
end
|
||||
|
||||
-- Should not trigger warning (but should still create elements)
|
||||
root:layoutChildren()
|
||||
luaunit.assertEquals(current:getHierarchyDepth(), 20)
|
||||
|
||||
-- Re-enable for other tests
|
||||
Performance.setConfig("warningsEnabled", true)
|
||||
end
|
||||
|
||||
-- Test layout recalculation tracking
|
||||
function TestPerformanceWarnings:testLayoutRecalculationTracking()
|
||||
local root = Element.new({
|
||||
id = "root",
|
||||
width = 100,
|
||||
height = 100,
|
||||
}, Element.defaultDependencies)
|
||||
|
||||
-- Layout multiple times (simulating layout thrashing)
|
||||
for i = 1, 5 do
|
||||
root:layoutChildren()
|
||||
end
|
||||
|
||||
-- Should complete without crashing
|
||||
luaunit.assertNotNil(root)
|
||||
end
|
||||
|
||||
return TestPerformanceWarnings
|
||||
Reference in New Issue
Block a user