366 lines
14 KiB
Lua
366 lines
14 KiB
Lua
-- Load the helper script
|
|
dofile("luahelper.lua")
|
|
|
|
-- Test helper function
|
|
local function assert(condition, message)
|
|
if not condition then error("ASSERTION FAILED: " .. (message or "unknown error")) end
|
|
end
|
|
|
|
local function test(name, fn)
|
|
local ok, err = pcall(fn)
|
|
if ok then
|
|
print("PASS: " .. name)
|
|
else
|
|
print("FAIL: " .. name .. " - " .. tostring(err))
|
|
end
|
|
end
|
|
|
|
-- Test fromCSV basic parsing
|
|
test("fromCSV basic", function()
|
|
local csv = "a,b,c\n1,2,3\n4,5,6"
|
|
local rows = fromCSV(csv)
|
|
assert(#rows == 3, "Should have 3 rows")
|
|
assert(rows[1][1] == "a", "First row first field should be 'a'")
|
|
assert(rows[2][2] == "2", "Second row second field should be '2'")
|
|
end)
|
|
|
|
-- Test fromCSV with headers
|
|
test("fromCSV with headers", function()
|
|
local csv = "foo,bar,baz\n1,2,3\n4,5,6"
|
|
local rows = fromCSV(csv, { hasHeaders = true })
|
|
assert(#rows == 2, "Should have 2 data rows")
|
|
assert(rows[1][1] == "1", "First row first field should be '1'")
|
|
assert(rows[1].foo == "1", "First row foo should be '1'")
|
|
assert(rows[1].bar == "2", "First row bar should be '2'")
|
|
assert(rows[1].baz == "3", "First row baz should be '3'")
|
|
end)
|
|
|
|
-- Test fromCSV with custom delimiter
|
|
test("fromCSV with tab delimiter", function()
|
|
local csv = "a\tb\tc\n1\t2\t3"
|
|
local rows = fromCSV(csv, { delimiter = "\t" })
|
|
assert(#rows == 2, "Should have 2 rows")
|
|
assert(rows[1][1] == "a", "First row first field should be 'a'")
|
|
assert(rows[2][2] == "2", "Second row second field should be '2'")
|
|
end)
|
|
|
|
-- Test fromCSV with quoted fields
|
|
test("fromCSV with quoted fields", function()
|
|
local csv = '"hello,world","test"\n"foo","bar"'
|
|
local rows = fromCSV(csv)
|
|
assert(#rows == 2, "Should have 2 rows")
|
|
assert(rows[1][1] == "hello,world", "Quoted field with comma should be preserved")
|
|
assert(rows[1][2] == "test", "Second field should be 'test'")
|
|
end)
|
|
|
|
-- Test toCSV basic
|
|
test("toCSV basic", function()
|
|
local rows = { { "a", "b", "c" }, { "1", "2", "3" } }
|
|
local csv = toCSV(rows)
|
|
assert(csv == "a,b,c\n1,2,3", "CSV output should match expected")
|
|
end)
|
|
|
|
-- Test toCSV with custom delimiter
|
|
test("toCSV with tab delimiter", function()
|
|
local rows = { { "a", "b", "c" }, { "1", "2", "3" } }
|
|
local csv = toCSV(rows, "\t")
|
|
assert(csv == "a\tb\tc\n1\t2\t3", "TSV output should match expected")
|
|
end)
|
|
|
|
-- Test toCSV with fields needing quoting
|
|
test("toCSV with quoted fields", function()
|
|
local rows = { { "hello,world", "test" }, { "foo", "bar" } }
|
|
local csv = toCSV(rows)
|
|
assert(csv == '"hello,world",test\nfoo,bar', "Fields with commas should be quoted")
|
|
end)
|
|
|
|
-- Test round trip
|
|
test("fromCSV toCSV round trip", function()
|
|
local original = "a,b,c\n1,2,3\n4,5,6"
|
|
local rows = fromCSV(original)
|
|
local csv = toCSV(rows)
|
|
assert(csv == original, "Round trip should preserve original")
|
|
end)
|
|
|
|
-- Test round trip with headers
|
|
test("fromCSV toCSV round trip with headers", function()
|
|
local original = "foo,bar,baz\n1,2,3\n4,5,6"
|
|
local rows = fromCSV(original, { hasHeaders = true })
|
|
local csv = toCSV(rows)
|
|
local expected = "1,2,3\n4,5,6"
|
|
assert(csv == expected, "Round trip with headers should preserve data rows")
|
|
end)
|
|
|
|
-- Test fromCSV with comments
|
|
test("fromCSV with comments", function()
|
|
local csv = "# This is a comment\nfoo,bar,baz\n1,2,3\n# Another comment\n4,5,6"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 3, "Should have 3 rows (comments filtered, header + 2 data rows)")
|
|
assert(rows[1][1] == "foo", "First row should be header row")
|
|
assert(rows[2][1] == "1", "Second row first field should be '1'")
|
|
assert(rows[3][1] == "4", "Third row first field should be '4'")
|
|
end)
|
|
|
|
-- Test fromCSV with comments and headers
|
|
test("fromCSV with comments and headers", function()
|
|
local csv = "#mercenary_profiles\nId,Name,Value\n1,Test,100\n# End of data\n2,Test2,200"
|
|
local rows = fromCSV(csv, { hasHeaders = true, hasComments = true })
|
|
assert(#rows == 2, "Should have 2 data rows")
|
|
assert(rows[1].Id == "1", "First row Id should be '1'")
|
|
assert(rows[1].Name == "Test", "First row Name should be 'Test'")
|
|
assert(rows[1].Value == "100", "First row Value should be '100'")
|
|
assert(rows[2].Id == "2", "Second row Id should be '2'")
|
|
end)
|
|
|
|
-- Test fromCSV with comments disabled
|
|
test("fromCSV without comments", function()
|
|
local csv = "# This should not be filtered\nfoo,bar\n1,2"
|
|
local rows = fromCSV(csv, { hasComments = false })
|
|
assert(#rows == 3, "Should have 3 rows (including comment)")
|
|
assert(rows[1][1] == "# This should not be filtered", "Comment line should be preserved")
|
|
end)
|
|
|
|
-- Test fromCSV with comment at start
|
|
test("fromCSV comment at start", function()
|
|
local csv = "# Header comment\nId,Name\n1,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (comment filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
end)
|
|
|
|
-- Test fromCSV with comment with leading whitespace
|
|
test("fromCSV comment with whitespace", function()
|
|
local csv = " # Comment with spaces\nId,Name\n1,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (comment with spaces filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
end)
|
|
|
|
-- Test fromCSV with comment with tabs
|
|
test("fromCSV comment with tabs", function()
|
|
local csv = "\t# Comment with tab\nId,Name\n1,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (comment with tab filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
end)
|
|
|
|
-- Test fromCSV with multiple consecutive comments
|
|
test("fromCSV multiple consecutive comments", function()
|
|
local csv = "# First comment\n# Second comment\n# Third comment\nId,Name\n1,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (all comments filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
end)
|
|
|
|
-- Test fromCSV with comment in middle of data
|
|
test("fromCSV comment in middle", function()
|
|
local csv = "Id,Name\n1,Test\n# Middle comment\n2,Test2"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 3, "Should have 3 rows (comment filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
assert(rows[2][1] == "1", "Second row should be first data")
|
|
assert(rows[3][1] == "2", "Third row should be second data")
|
|
end)
|
|
|
|
-- Test fromCSV with comment at end
|
|
test("fromCSV comment at end", function()
|
|
local csv = "Id,Name\n1,Test\n# End comment"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (end comment filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
assert(rows[2][1] == "1", "Second row should be data")
|
|
end)
|
|
|
|
-- Test fromCSV with empty comment line
|
|
test("fromCSV empty comment", function()
|
|
local csv = "#\nId,Name\n1,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows (empty comment filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
end)
|
|
|
|
-- Test fromCSV with comment and headers
|
|
test("fromCSV comment with headers enabled", function()
|
|
local csv = "#mercenary_profiles\nId,Name,Value\n1,Test,100\n2,Test2,200"
|
|
local rows = fromCSV(csv, { hasHeaders = true, hasComments = true })
|
|
assert(#rows == 2, "Should have 2 data rows")
|
|
assert(rows[1].Id == "1", "First row Id should be '1'")
|
|
assert(rows[1].Name == "Test", "First row Name should be 'Test'")
|
|
assert(rows[2].Id == "2", "Second row Id should be '2'")
|
|
end)
|
|
|
|
-- Test fromCSV with comment and TSV delimiter
|
|
test("fromCSV comment with tab delimiter", function()
|
|
local csv = "# Comment\nId\tName\n1\tTest"
|
|
local rows = fromCSV(csv, { delimiter = "\t", hasComments = true })
|
|
assert(#rows == 2, "Should have 2 rows")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
assert(rows[2][1] == "1", "Second row first field should be '1'")
|
|
end)
|
|
|
|
-- Test fromCSV with comment and headers and TSV
|
|
test("fromCSV comment with headers and TSV", function()
|
|
local csv = "#mercenary_profiles\nId\tName\tValue\n1\tTest\t100"
|
|
local rows = fromCSV(csv, { delimiter = "\t", hasHeaders = true, hasComments = true })
|
|
assert(#rows == 1, "Should have 1 data row")
|
|
assert(rows[1].Id == "1", "Row Id should be '1'")
|
|
assert(rows[1].Name == "Test", "Row Name should be 'Test'")
|
|
assert(rows[1].Value == "100", "Row Value should be '100'")
|
|
end)
|
|
|
|
-- Test fromCSV with data field starting with # (not a comment)
|
|
test("fromCSV data field starting with hash", function()
|
|
local csv = "Id,Name\n1,#NotAComment\n2,Test"
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 3, "Should have 3 rows (data with # not filtered)")
|
|
assert(rows[1][1] == "Id", "First row should be header")
|
|
assert(rows[2][2] == "#NotAComment", "Second row should have #NotAComment as data")
|
|
end)
|
|
|
|
-- Test fromCSV with quoted field starting with #
|
|
test("fromCSV quoted field with hash", function()
|
|
local csv = 'Id,Name\n1,"#NotAComment"\n2,Test'
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 3, "Should have 3 rows (quoted # not filtered)")
|
|
assert(rows[2][2] == "#NotAComment", "Quoted field with # should be preserved")
|
|
end)
|
|
|
|
-- Test fromCSV with comment after quoted field
|
|
test("fromCSV comment after quoted field", function()
|
|
local csv = 'Id,Name\n1,"Test"\n# This is a comment\n2,Test2'
|
|
local rows = fromCSV(csv, { hasComments = true })
|
|
assert(#rows == 3, "Should have 3 rows (comment filtered)")
|
|
assert(rows[2][2] == "Test", "Quoted field should be preserved")
|
|
assert(rows[3][1] == "2", "Third row should be second data row")
|
|
end)
|
|
|
|
-- Math function tests
|
|
test("min function", function()
|
|
assert(min(5, 3) == 3, "min(5, 3) should be 3")
|
|
assert(min(-1, 0) == -1, "min(-1, 0) should be -1")
|
|
assert(min(10, 10) == 10, "min(10, 10) should be 10")
|
|
end)
|
|
|
|
test("max function", function()
|
|
assert(max(5, 3) == 5, "max(5, 3) should be 5")
|
|
assert(max(-1, 0) == 0, "max(-1, 0) should be 0")
|
|
assert(max(10, 10) == 10, "max(10, 10) should be 10")
|
|
end)
|
|
|
|
test("round function", function()
|
|
assert(round(3.14159) == 3, "round(3.14159) should be 3")
|
|
assert(round(3.14159, 2) == 3.14, "round(3.14159, 2) should be 3.14")
|
|
assert(round(3.5) == 4, "round(3.5) should be 4")
|
|
assert(round(3.4) == 3, "round(3.4) should be 3")
|
|
assert(round(123.456, 1) == 123.5, "round(123.456, 1) should be 123.5")
|
|
end)
|
|
|
|
test("floor function", function()
|
|
assert(floor(3.7) == 3, "floor(3.7) should be 3")
|
|
assert(floor(-3.7) == -4, "floor(-3.7) should be -4")
|
|
assert(floor(5) == 5, "floor(5) should be 5")
|
|
end)
|
|
|
|
test("ceil function", function()
|
|
assert(ceil(3.2) == 4, "ceil(3.2) should be 4")
|
|
assert(ceil(-3.2) == -3, "ceil(-3.2) should be -3")
|
|
assert(ceil(5) == 5, "ceil(5) should be 5")
|
|
end)
|
|
|
|
-- String function tests
|
|
test("upper function", function()
|
|
assert(upper("hello") == "HELLO", "upper('hello') should be 'HELLO'")
|
|
assert(upper("Hello World") == "HELLO WORLD", "upper('Hello World') should be 'HELLO WORLD'")
|
|
assert(upper("123abc") == "123ABC", "upper('123abc') should be '123ABC'")
|
|
end)
|
|
|
|
test("lower function", function()
|
|
assert(lower("HELLO") == "hello", "lower('HELLO') should be 'hello'")
|
|
assert(lower("Hello World") == "hello world", "lower('Hello World') should be 'hello world'")
|
|
assert(lower("123ABC") == "123abc", "lower('123ABC') should be '123abc'")
|
|
end)
|
|
|
|
test("format function", function()
|
|
assert(format("Hello %s", "World") == "Hello World", "format should work")
|
|
assert(format("Number: %d", 42) == "Number: 42", "format with number should work")
|
|
assert(format("%.2f", 3.14159) == "3.14", "format with float should work")
|
|
end)
|
|
|
|
test("trim function", function()
|
|
assert(trim(" hello ") == "hello", "trim should remove leading and trailing spaces")
|
|
assert(trim(" hello world ") == "hello world", "trim should preserve internal spaces")
|
|
assert(trim("hello") == "hello", "trim should not affect strings without spaces")
|
|
assert(trim(" ") == "", "trim should handle all spaces")
|
|
end)
|
|
|
|
test("strsplit function", function()
|
|
local result = strsplit("a,b,c", ",")
|
|
assert(#result == 3, "strsplit should return 3 elements")
|
|
assert(result[1] == "a", "First element should be 'a'")
|
|
assert(result[2] == "b", "Second element should be 'b'")
|
|
assert(result[3] == "c", "Third element should be 'c'")
|
|
end)
|
|
|
|
test("strsplit with default separator", function()
|
|
local result = strsplit("a b c")
|
|
assert(#result == 3, "strsplit with default should return 3 elements")
|
|
assert(result[1] == "a", "First element should be 'a'")
|
|
assert(result[2] == "b", "Second element should be 'b'")
|
|
assert(result[3] == "c", "Third element should be 'c'")
|
|
end)
|
|
|
|
test("strsplit with custom separator", function()
|
|
local result = strsplit("a|b|c", "|")
|
|
assert(#result == 3, "strsplit with pipe should return 3 elements")
|
|
assert(result[1] == "a", "First element should be 'a'")
|
|
assert(result[2] == "b", "Second element should be 'b'")
|
|
assert(result[3] == "c", "Third element should be 'c'")
|
|
end)
|
|
|
|
-- Conversion function tests
|
|
test("num function", function()
|
|
assert(num("123") == 123, "num('123') should be 123")
|
|
assert(num("45.67") == 45.67, "num('45.67') should be 45.67")
|
|
assert(num("invalid") == 0, "num('invalid') should be 0")
|
|
assert(num("") == 0, "num('') should be 0")
|
|
end)
|
|
|
|
test("str function", function()
|
|
assert(str(123) == "123", "str(123) should be '123'")
|
|
assert(str(45.67) == "45.67", "str(45.67) should be '45.67'")
|
|
assert(str(0) == "0", "str(0) should be '0'")
|
|
end)
|
|
|
|
test("is_number function", function()
|
|
assert(is_number("123") == true, "is_number('123') should be true")
|
|
assert(is_number("45.67") == true, "is_number('45.67') should be true")
|
|
assert(is_number("invalid") == false, "is_number('invalid') should be false")
|
|
assert(is_number("") == false, "is_number('') should be false")
|
|
assert(is_number("123abc") == false, "is_number('123abc') should be false")
|
|
end)
|
|
|
|
-- Table function tests
|
|
test("isArray function", function()
|
|
assert(isArray({ 1, 2, 3 }) == true, "isArray should return true for sequential array")
|
|
assert(isArray({ "a", "b", "c" }) == true, "isArray should return true for string array")
|
|
assert(isArray({}) == true, "isArray should return true for empty array")
|
|
assert(isArray({ a = 1, b = 2 }) == false, "isArray should return false for map")
|
|
assert(isArray({ 1, 2, [4] = 4 }) == false, "isArray should return false for sparse array")
|
|
assert(
|
|
isArray({ [1] = 1, [2] = 2, [3] = 3 }) == true,
|
|
"isArray should return true for 1-indexed array"
|
|
)
|
|
assert(
|
|
isArray({ [0] = 1, [1] = 2 }) == false,
|
|
"isArray should return false for 0-indexed array"
|
|
)
|
|
assert(
|
|
isArray({ [1] = 1, [2] = 2, [4] = 4 }) == false,
|
|
"isArray should return false for non-sequential array"
|
|
)
|
|
assert(isArray("not a table") == false, "isArray should return false for non-table")
|
|
assert(isArray(123) == false, "isArray should return false for number")
|
|
end)
|
|
|
|
print("\nAll tests completed!")
|