662 lines
23 KiB
Lua
662 lines
23 KiB
Lua
---@diagnostic disable: undefined-global, undefined-field
|
|
local lu = require("testing.luaunit")
|
|
|
|
-- Mock love globals for testing environment
|
|
_G.love = _G.love or {}
|
|
_G.love.graphics = _G.love.graphics or {}
|
|
_G.love.graphics.getDimensions = function()
|
|
return 1920, 1080
|
|
end
|
|
_G.love.window = _G.love.window or {}
|
|
_G.love.window.getMode = function()
|
|
return 1920, 1080
|
|
end
|
|
|
|
-- Load Calc module directly
|
|
local Calc = require("modules.Calc")
|
|
local ErrorHandler = require("modules.ErrorHandler")
|
|
|
|
-- Initialize with error handler
|
|
ErrorHandler.init({})
|
|
Calc.init({ ErrorHandler = ErrorHandler })
|
|
|
|
---@class TestCalc
|
|
TestCalc = {}
|
|
|
|
function TestCalc:setUp()
|
|
-- Fresh initialization for each test
|
|
end
|
|
|
|
function TestCalc:tearDown()
|
|
-- Cleanup after each test
|
|
end
|
|
|
|
--- Test basic arithmetic: addition
|
|
function TestCalc:testBasicAddition()
|
|
local calcObj = Calc.new("100px + 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 150)
|
|
end
|
|
|
|
--- Test basic arithmetic: subtraction
|
|
function TestCalc:testBasicSubtraction()
|
|
local calcObj = Calc.new("100px - 30px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 70)
|
|
end
|
|
|
|
--- Test basic arithmetic: multiplication
|
|
function TestCalc:testBasicMultiplication()
|
|
local calcObj = Calc.new("10px * 5")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 50)
|
|
end
|
|
|
|
--- Test basic arithmetic: division
|
|
function TestCalc:testBasicDivision()
|
|
local calcObj = Calc.new("100px / 4")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 25)
|
|
end
|
|
|
|
--- Test negative numbers
|
|
function TestCalc:testNegativeNumbers()
|
|
local calcObj = Calc.new("-50px + 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 50)
|
|
end
|
|
|
|
--- Test decimal numbers
|
|
function TestCalc:testDecimalNumbers()
|
|
local calcObj = Calc.new("10.5px + 5.5px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 16)
|
|
end
|
|
|
|
--- Test percentage units
|
|
function TestCalc:testPercentageUnits()
|
|
local calcObj = Calc.new("50% + 25%")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil) -- parent size = 1000
|
|
lu.assertEquals(result, 750) -- 50% of 1000 + 25% of 1000 = 500 + 250
|
|
end
|
|
|
|
--- Test viewport width units (vw)
|
|
function TestCalc:testViewportWidthUnits()
|
|
local calcObj = Calc.new("50vw - 10vw")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 768) -- 40% of 1920 = 768
|
|
end
|
|
|
|
--- Test viewport height units (vh)
|
|
function TestCalc:testViewportHeightUnits()
|
|
local calcObj = Calc.new("50vh + 10vh")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 648) -- 60% of 1080 = 648
|
|
end
|
|
|
|
--- Test mixed units
|
|
function TestCalc:testMixedUnits()
|
|
local calcObj = Calc.new("50% - 10vw")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
|
|
lu.assertEquals(result, 308) -- 50% of 1000 - 10% of 1920 = 500 - 192 = 308
|
|
end
|
|
|
|
--- Test complex expression with multiple operations
|
|
function TestCalc:testComplexExpression()
|
|
local calcObj = Calc.new("100px + 50px - 20px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 130)
|
|
end
|
|
|
|
--- Test parentheses for precedence
|
|
function TestCalc:testParentheses()
|
|
local calcObj = Calc.new("(100px + 50px) * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 300)
|
|
end
|
|
|
|
--- Test nested parentheses
|
|
function TestCalc:testNestedParentheses()
|
|
local calcObj = Calc.new("((100px + 50px) / 3) * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 100) -- (150 / 3) * 2 = 50 * 2 = 100
|
|
end
|
|
|
|
--- Test operator precedence (multiplication before addition)
|
|
function TestCalc:testOperatorPrecedence()
|
|
local calcObj = Calc.new("100px + 50px * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 200) -- 100 + (50 * 2) = 100 + 100 = 200
|
|
end
|
|
|
|
--- Test centering use case (50% - 10vw)
|
|
function TestCalc:testCenteringUseCase()
|
|
local calcObj = Calc.new("50% - 10vw")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Assuming element width is 20vw (384px) and parent width is 1920px
|
|
-- 50% of parent - 10vw should center it
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1920, nil, nil)
|
|
lu.assertEquals(result, 768) -- 50% of 1920 - 10% of 1920 = 960 - 192 = 768
|
|
end
|
|
|
|
--- Test element width units (ew)
|
|
function TestCalc:testElementWidthUnits()
|
|
local calcObj = Calc.new("100ew - 20ew")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, 500, nil) -- element width = 500
|
|
lu.assertEquals(result, 400) -- 80% of 500 = 400
|
|
end
|
|
|
|
--- Test element height units (eh)
|
|
function TestCalc:testElementHeightUnits()
|
|
local calcObj = Calc.new("50eh + 25eh")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, 300) -- element height = 300
|
|
lu.assertEquals(result, 225) -- 75% of 300 = 225
|
|
end
|
|
|
|
--- Test whitespace handling
|
|
function TestCalc:testWhitespaceHandling()
|
|
local calcObj = Calc.new(" 100px + 50px ")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 150)
|
|
end
|
|
|
|
--- Test zero value
|
|
function TestCalc:testZeroValue()
|
|
local calcObj = Calc.new("100px - 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test single value (no operation)
|
|
function TestCalc:testSingleValue()
|
|
local calcObj = Calc.new("100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 100)
|
|
end
|
|
|
|
--- Test isCalc function with non-calc values
|
|
function TestCalc:testIsCalcWithNonCalcValues()
|
|
lu.assertFalse(Calc.isCalc("100px"))
|
|
lu.assertFalse(Calc.isCalc(100))
|
|
lu.assertFalse(Calc.isCalc(nil))
|
|
lu.assertFalse(Calc.isCalc({}))
|
|
end
|
|
|
|
--- Test division by zero error handling
|
|
function TestCalc:testDivisionByZeroHandling()
|
|
local calcObj = Calc.new("100px / 0")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0) -- Should return 0 on division by zero error
|
|
end
|
|
|
|
--- Test invalid expression error handling
|
|
function TestCalc:testInvalidExpressionHandling()
|
|
local calcObj = Calc.new("100px +") -- Incomplete expression
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should return 0 for invalid expressions
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test complex real-world centering scenario
|
|
function TestCalc:testRealWorldCentering()
|
|
-- Button with 20vw width, centered at 50% - 10vw
|
|
local xCalc = Calc.new("50% - 10vw")
|
|
local result = Calc.resolve(xCalc, 1920, 1080, 1920, nil, nil)
|
|
-- Expected: 50% of 1920 - 10% of 1920 = 960 - 192 = 768
|
|
lu.assertEquals(result, 768)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- STRESS TESTS - Complex calculations and deeply nested structures
|
|
-- ============================================================================
|
|
|
|
--- Test deeply nested parentheses (3 levels)
|
|
function TestCalc:testDeeplyNested3Levels()
|
|
local calcObj = Calc.new("(((100px + 50px) * 2) - 100px) / 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (((150) * 2) - 100) / 2 = (300 - 100) / 2 = 200 / 2 = 100
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 100)
|
|
end
|
|
|
|
--- Test deeply nested parentheses (5 levels)
|
|
function TestCalc:testDeeplyNested5Levels()
|
|
local calcObj = Calc.new("(((((10px + 5px) * 2) + 10px) * 2) - 20px) / 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (((((15) * 2) + 10) * 2) - 20) / 2
|
|
-- ((((30) + 10) * 2) - 20) / 2
|
|
-- (((40) * 2) - 20) / 2
|
|
-- ((80) - 20) / 2
|
|
-- (60) / 2 = 30
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 30)
|
|
end
|
|
|
|
--- Test deeply nested parentheses (10 levels)
|
|
function TestCalc:testDeeplyNested10Levels()
|
|
local calcObj = Calc.new("((((((((((2px * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2) * 2)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 2 * 2^10 = 2 * 1024 = 2048
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 2048)
|
|
end
|
|
|
|
--- Test complex multi-operation expression with all operators
|
|
function TestCalc:testComplexMultiOperationAllOperators()
|
|
local calcObj = Calc.new("100px + 50px - 20px * 2 / 4 + 30px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Precedence: 20 * 2 = 40, 40 / 4 = 10
|
|
-- Then: 100 + 50 - 10 + 30 = 170
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 170)
|
|
end
|
|
|
|
--- Test complex expression with mixed units and all operators
|
|
function TestCalc:testComplexMixedUnitsAllOperators()
|
|
local calcObj = Calc.new("50% + 10vw - 5vh * 2 / 4")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 50% = 500 (parent 1000), 10vw = 192, 5vh = 54, 54 * 2 = 108, 108 / 4 = 27
|
|
-- 500 + 192 - 27 = 665
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
|
|
lu.assertEquals(result, 665)
|
|
end
|
|
|
|
--- Test nested parentheses with mixed operations
|
|
function TestCalc:testNestedParenthesesMixedOperations()
|
|
local calcObj = Calc.new("((100px + 50px) * (200px - 100px)) / 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (150 * 100) / 50 = 15000 / 50 = 300
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 300)
|
|
end
|
|
|
|
--- Test extremely long expression with many operations
|
|
function TestCalc:testExtremelyLongExpression()
|
|
local calcObj = Calc.new("10px + 20px + 30px + 40px + 50px - 5px - 10px - 15px * 2 / 3 + 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 15 * 2 / 3 = 30 / 3 = 10
|
|
-- 10 + 20 + 30 + 40 + 50 - 5 - 10 - 10 + 100 = 225
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 225)
|
|
end
|
|
|
|
--- Test alternating operations with parentheses
|
|
function TestCalc:testAlternatingOperationsWithParentheses()
|
|
local calcObj = Calc.new("(50px + 50px) * (100px - 50px) / (25px + 25px)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (100) * (50) / (50) = 5000 / 50 = 100
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 100)
|
|
end
|
|
|
|
--- Test very large numbers
|
|
function TestCalc:testVeryLargeNumbers()
|
|
local calcObj = Calc.new("10000px + 50000px * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 50000 * 2 = 100000, 10000 + 100000 = 110000
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 110000)
|
|
end
|
|
|
|
--- Test very small decimal numbers
|
|
function TestCalc:testVerySmallDecimals()
|
|
local calcObj = Calc.new("0.1px + 0.2px + 0.3px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertAlmostEquals(result, 0.6, 0.0001)
|
|
end
|
|
|
|
--- Test negative numbers in complex expression
|
|
function TestCalc:testNegativeNumbersInComplexExpression()
|
|
local calcObj = Calc.new("(-50px + 100px) * (-2px + 5px)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (50) * (3) = 150
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 150)
|
|
end
|
|
|
|
--- Test multiple negative numbers
|
|
function TestCalc:testMultipleNegativeNumbers()
|
|
local calcObj = Calc.new("-50px - 30px - 20px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- -50 - 30 - 20 = -100
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, -100)
|
|
end
|
|
|
|
--- Test negative result from subtraction
|
|
function TestCalc:testNegativeResultFromSubtraction()
|
|
local calcObj = Calc.new("50px - 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, -50)
|
|
end
|
|
|
|
--- Test all unit types in single expression
|
|
function TestCalc:testAllUnitTypesInSingleExpression()
|
|
local calcObj = Calc.new("100px + 10% + 5vw + 5vh + 10ew + 10eh")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 100 + 100 (10% of 1000) + 96 (5% of 1920) + 54 (5% of 1080) + 50 (10% of 500) + 30 (10% of 300)
|
|
-- = 100 + 100 + 96 + 54 + 50 + 30 = 430
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, 500, 300)
|
|
lu.assertEquals(result, 430)
|
|
end
|
|
|
|
--- Test precedence with multiple levels
|
|
function TestCalc:testPrecedenceWithMultipleLevels()
|
|
local calcObj = Calc.new("100px + 50px * 2 - 30px / 3")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 50 * 2 = 100, 30 / 3 = 10
|
|
-- 100 + 100 - 10 = 190
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 190)
|
|
end
|
|
|
|
--- Test parentheses overriding precedence in complex way
|
|
function TestCalc:testParenthesesOverridingPrecedenceComplex()
|
|
local calcObj = Calc.new("(100px + 50px) * (2px + 3px) - (30px + 20px) / (5px - 3px)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (150) * (5) - (50) / (2) = 750 - 25 = 725
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 725)
|
|
end
|
|
|
|
--- Test percentage calculations with zero parent
|
|
function TestCalc:testPercentageWithZeroParent()
|
|
local calcObj = Calc.new("50% + 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 50% of 0 = 0, 0 + 100 = 100
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 0, nil, nil)
|
|
lu.assertEquals(result, 100)
|
|
end
|
|
|
|
--- Test element units without element dimensions
|
|
function TestCalc:testElementUnitsWithoutDimensions()
|
|
local calcObj = Calc.new("100ew + 50eh")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should return 0 + 0 = 0 due to missing dimensions
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test mixed parentheses and operations at different levels
|
|
function TestCalc:testMixedParenthesesDifferentLevels()
|
|
local calcObj = Calc.new("((100px + 50px) * 2) + (200px / (10px + 10px))")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- ((150) * 2) + (200 / (20)) = 300 + 10 = 310
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 310)
|
|
end
|
|
|
|
--- Test chain multiplication
|
|
function TestCalc:testChainMultiplication()
|
|
local calcObj = Calc.new("2px * 3 * 4 * 5")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 2 * 3 * 4 * 5 = 120
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 120)
|
|
end
|
|
|
|
--- Test chain division
|
|
function TestCalc:testChainDivision()
|
|
local calcObj = Calc.new("1000px / 2 / 5 / 10")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 1000 / 2 / 5 / 10 = 500 / 5 / 10 = 100 / 10 = 10
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 10)
|
|
end
|
|
|
|
--- Test fractional results
|
|
function TestCalc:testFractionalResults()
|
|
local calcObj = Calc.new("100px / 3")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertAlmostEquals(result, 33.333333333, 0.0001)
|
|
end
|
|
|
|
--- Test complex viewport-based layout calculation
|
|
function TestCalc:testComplexViewportBasedLayout()
|
|
-- Simulate: margin-left = (100vw - element_width) / 2, where element is 30vw
|
|
local calcObj = Calc.new("(100vw - 30vw) / 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (1920 - 576) / 2 = 1344 / 2 = 672
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 672)
|
|
end
|
|
|
|
--- Test complex responsive sizing calculation
|
|
function TestCalc:testComplexResponsiveSizing()
|
|
-- Simulate: width = 100% - 20px padding on each side - 10vw margin
|
|
local calcObj = Calc.new("100% - 40px - 10vw")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 100% of 1000 - 40 - 10% of 1920 = 1000 - 40 - 192 = 768
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
|
|
lu.assertEquals(result, 768)
|
|
end
|
|
|
|
--- Test expression with leading negative in parentheses
|
|
function TestCalc:testLeadingNegativeInParentheses()
|
|
local calcObj = Calc.new("100px + (-50px * 2)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 100 + (-100) = 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test multiple parentheses groups at same level
|
|
function TestCalc:testMultipleParenthesesGroupsSameLevel()
|
|
local calcObj = Calc.new("(100px + 50px) + (200px - 100px) + (300px / 3)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 150 + 100 + 100 = 350
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 350)
|
|
end
|
|
|
|
--- Test near-zero division result
|
|
function TestCalc:testNearZeroDivisionResult()
|
|
local calcObj = Calc.new("1px / 1000")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertAlmostEquals(result, 0.001, 0.0001)
|
|
end
|
|
|
|
--- Test expression with only multiplication and division
|
|
function TestCalc:testOnlyMultiplicationAndDivision()
|
|
local calcObj = Calc.new("100px * 2 / 4 * 3 / 5")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 100 * 2 / 4 * 3 / 5 = 200 / 4 * 3 / 5 = 50 * 3 / 5 = 150 / 5 = 30
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 30)
|
|
end
|
|
|
|
--- Test expression with decimal percentages
|
|
function TestCalc:testDecimalPercentages()
|
|
local calcObj = Calc.new("12.5% + 37.5%")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 12.5% + 37.5% = 50% of 1000 = 500
|
|
local result = Calc.resolve(calcObj, 1920, 1080, 1000, nil, nil)
|
|
lu.assertEquals(result, 500)
|
|
end
|
|
|
|
--- Test unitless numbers in multiplication/division
|
|
function TestCalc:testUnitlessNumbersInMultDiv()
|
|
local calcObj = Calc.new("100px * 2.5 / 0.5")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- 100 * 2.5 / 0.5 = 250 / 0.5 = 500
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 500)
|
|
end
|
|
|
|
--- Test deeply nested with negative numbers
|
|
function TestCalc:testDeeplyNestedWithNegatives()
|
|
local calcObj = Calc.new("((-100px + 200px) * (-2px + 5px)) / (10px - 5px)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- ((100) * (3)) / (5) = 300 / 5 = 60
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 60)
|
|
end
|
|
|
|
--- Test asymmetric nested parentheses
|
|
function TestCalc:testAsymmetricNestedParentheses()
|
|
local calcObj = Calc.new("((100px + 50px) * 2) + 200px / 4")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (150 * 2) + (200 / 4) = 300 + 50 = 350
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 350)
|
|
end
|
|
|
|
--- Test maximum nesting with all operations
|
|
function TestCalc:testMaximumNestingAllOperations()
|
|
local calcObj = Calc.new("((((100px + 50px) - 30px) * 2) / 4)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- ((((150) - 30) * 2) / 4) = (((120) * 2) / 4) = ((240) / 4) = 60
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 60)
|
|
end
|
|
|
|
--- Test whitespace in complex expressions
|
|
function TestCalc:testWhitespaceInComplexExpression()
|
|
local calcObj = Calc.new(" ( 100px + 50px ) * ( 2px + 3px ) ")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- (150) * (5) = 750
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 750)
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- ERROR CONDITION STRESS TESTS
|
|
-- ============================================================================
|
|
|
|
--- Test mismatched parentheses (missing closing)
|
|
function TestCalc:testMismatchedParenthesesMissingClosing()
|
|
local calcObj = Calc.new("((100px + 50px) * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test mismatched parentheses (missing opening)
|
|
function TestCalc:testMismatchedParenthesesMissingOpening()
|
|
local calcObj = Calc.new("100px + 50px) * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test empty parentheses
|
|
function TestCalc:testEmptyParentheses()
|
|
local calcObj = Calc.new("100px + ()")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test consecutive operators
|
|
function TestCalc:testConsecutiveOperators()
|
|
local calcObj = Calc.new("100px ++ 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test trailing operator
|
|
function TestCalc:testTrailingOperator()
|
|
local calcObj = Calc.new("100px + 50px *")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test leading operator (non-negative)
|
|
function TestCalc:testLeadingOperatorNonNegative()
|
|
local calcObj = Calc.new("+ 100px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test invalid unit
|
|
function TestCalc:testInvalidUnit()
|
|
local calcObj = Calc.new("100xyz + 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test mixed invalid syntax
|
|
function TestCalc:testMixedInvalidSyntax()
|
|
local calcObj = Calc.new("100px + * 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test special characters
|
|
function TestCalc:testSpecialCharacters()
|
|
local calcObj = Calc.new("100px + 50px @ 20px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test extremely long invalid expression
|
|
function TestCalc:testExtremelyLongInvalidExpression()
|
|
local calcObj = Calc.new("100px + + + + + + + + + + 50px")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle gracefully and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test division by calculated zero
|
|
function TestCalc:testDivisionByCalculatedZero()
|
|
local calcObj = Calc.new("100px / (50px - 50px)")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle division by zero and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
--- Test nested division by zero
|
|
function TestCalc:testNestedDivisionByZero()
|
|
local calcObj = Calc.new("((100px + 50px) / 0) * 2")
|
|
lu.assertTrue(Calc.isCalc(calcObj))
|
|
-- Should handle division by zero and return 0
|
|
local result = Calc.resolve(calcObj, 1920, 1080, nil, nil, nil)
|
|
lu.assertEquals(result, 0)
|
|
end
|
|
|
|
if not _G.RUNNING_ALL_TESTS then
|
|
os.exit(lu.LuaUnit.run())
|
|
end
|