1
0
pretty/test/test_pretty.lua

604 lines
15 KiB
Lua

local SUITE = require('TestSuite').new('pretty')
SUITE:setEnviroment{
format = require('pretty')
}
local ASSERT_ERROR_APPROX = [[
Approximate strings not similar enough:
Should match: %s
Gotten: %s
]]
--------------------------------------------------------------------------------
-- Lua 5.1 compat:
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams
-- Lua 5.3 compat:
if not loadstring then
loadstring = load
end
local function format_test (t)
if t.longterm then return end
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
SUITE:addTest(t.expect, function ()
local input_value = t.input
local input_options = t.options
local expected_result = t.expect
local actual_result = format(input_value, input_options)
if not t.approx or type(actual_result) ~= 'string' then
assert_equal(actual_result, expected_result)
else
if not actual_result:match(expected_result) then
error(ASSERT_ERROR_APPROX:format(expected_result, actual_result))
end
end
end)
end
--------------------------------------------------------------------------------
-- Strings
format_test {
input = 'Hello World',
expect = '\'Hello World\'',
}
format_test {
input = 'Hello \'World\'',
expect = '\"Hello \'World\'\"',
}
format_test {
input = 'Hello \"World\"',
expect = '\'Hello \"World\"\'',
}
format_test {
input = 'Hello [[World]]',
expect = '\'Hello [[World]]\'',
}
format_test {
input = '\'Hello\' [[World]]',
expect = '\"\'Hello\' [[World]]\"',
}
format_test {
input = '\'Hello\' \"there\" [[World]]',
expect = '[=[\'Hello\' \"there\" [[World]]]=]',
}
format_test {
input = '\'Hello\' \"there\" [=[World]=]',
expect = '[[\'Hello\' \"there\" [=[World]=]]]',
}
format_test {
input = '\nHello World',
expect = '\'\\nHello World\'',
}
format_test {
input = '\'\"\n',
expect = '[[\n\'\"\n]]',
}
format_test {
input = '\n',
expect = '\'\\n\'',
}
format_test {
input = '\\',
expect = '\'\\\\\'',
}
format_test {
input = '\000',
expect = '\'\\000\'',
}
format_test {
input = '\a\b\v\r\f',
expect = '\'\\a\\b\\v\\r\\f\'',
}
format_test {
input = 'ø',
expect = '\'ø\'',
}
--------------------------------------------------------------------------------
-- Numbers
format_test {
input = 0,
expect = '0',
}
format_test {
input = 2000,
expect = '2000',
}
format_test {
input = -2000,
expect = '-2000',
}
format_test {
input = 1/0, -- Same as math.huge
expect = '1/0',
}
format_test {
input = -1/0, -- Same as -math.huge
expect = '-1/0',
}
format_test {
input = 0/0, -- Same as nan
expect = '0/0',
}
format_test {
input = 1/0, -- Same as math.huge
options = { math_shorthand = true },
expect = 'inf',
}
format_test {
input = -1/0, -- Same as -math.huge
options = { math_shorthand = true },
expect = '-inf',
}
format_test {
input = 0/0, -- Same as nan
options = { math_shorthand = true },
expect = 'nan',
}
--------------------------------------------------------------------------------
-- Primitive types
format_test {
input = nil,
expect = 'nil',
}
format_test {
input = true,
expect = 'true',
}
format_test {
input = false,
expect = 'false',
}
--------------------------------------------------------------------------------
-- Function printing
format_test {
adv_getlocal = true,
input = function () end,
expect = 'function () ... end',
}
format_test {
adv_getlocal = true,
input = function (a) end,
expect = 'function (a) ... end',
}
format_test {
adv_getlocal = true,
input = function (a, b) end,
expect = 'function (a, b) ... end',
}
format_test {
adv_getlocal = true,
input = function (...) end,
expect = 'function (...) ... end',
}
format_test {
adv_getlocal = true,
input = function (a, b, ...) end,
expect = 'function (a, b, ...) ... end',
}
do
local SOME_RANDOM_UPVALUE = false
format_test {
adv_getlocal = true,
input = function () l = SOME_RANDOM_UPVALUE end,
expect = 'function () ... end',
}
format_test {
adv_getlocal = true,
input = function () SOME_RANDOM_UPVALUE = true end,
expect = 'function () ... end',
}
format_test {
-- More function info is ignored if not at depth 0.
adv_getlocal = true,
input = { a = function () SOME_RANDOM_UPVALUE = true end },
options = { more_function_info = true },
expect = '{\n\ta = function () ... end\n}',
}
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function () l = SOME_RANDOM_UPVALUE end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
}
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function () SOME_RANDOM_UPVALUE = true end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
}
end
do
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function () end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend'
}
end
do
local index = 0
format_test {
input = function () index = index + 1; return index end,
adv_getlocal = true,
expect = 'function () ... end'
}
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function () index = index + 1; return index end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { index = 0 }\n\n\t...\nend'
}
end
format_test {
adv_getlocal = true,
input = loadstring('return function () end')(),
expect = 'function () end',
}
format_test {
adv_getlocal = true,
input = loadstring('return function () return function () end end')(),
expect = 'function () return function () end end',
}
format_test {
longterm = true,
adv_getlocal = true,
input = loadstring('return function () return function () end\nend')()(),
expect = 'function () end',
}
format_test {
-- NOTE: This is HARD to fix. It's thus longerterm
longterm = true,
adv_getlocal = true,
input = loadstring('return function () return function () end end')()(),
expect = 'function () end',
}
format_test {
-- More function info allows one to even get the function whole, if it was defined in a string.
input = loadstring('return function (a, b) return a + b end')(),
options = { more_function_info = true },
expect = 'function (a, b) return a + b end',
}
format_test {
-- More function info allows one to even get the function whole, if it was defined in a string.
input = loadstring('return function (a, b)\n\treturn a + b\nend')(),
options = { more_function_info = true },
expect = 'function (a, b)\n\treturn a + b\nend',
}
do
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function ()
-- NOTE: This function must cover 3 lines of code!
end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Lines: '..func_line..' - '..(func_line+2)..']\n\n\t...\nend',
}
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test {
input = function () --[[ NOTE: This function must cover a single line of code! ]] end,
adv_getlocal = true,
options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend',
}
end
format_test {
input = math.abs,
expect = 'builtin function (x) ... end',
}
format_test {
input = math.abs,
options = { more_function_info = true },
expect = 'builtin function (x)\n\t-- math.abs\n\t-- Returns the absolute value of x.\n\n\t...\nend',
}
format_test {
input = math.random,
expect = 'builtin function ([m [, n]) ... end',
}
format_test {
input = math.random,
options = { more_function_info = true },
expect = 'builtin function ([m [, n])\n\t-- math.random\n\t-- When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].\n\n\t...\nend',
}
format_test {
input = string.byte,
options = { more_function_info = true },
expect = 'builtin function (s [, i [, j]])\n\t-- string.byte\n\t-- Returns the internal numerical codes of the characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the default value for j is i.\n\t-- Note that numerical codes are not necessarily portable across platforms.\n\n\t...\nend',
}
-- Indent functions nicely
format_test {
-- The tail part should align, letting people focus on the important aspects.
input = { random = math.random, abs = math.abs },
expect = '{\n\tabs = builtin function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
}
format_test {
-- The function part should align, if some are builtin and some are not.
adv_getlocal = true,
input = { random = math.random, abs = function (x) return x < 0 and -x or x end },
expect = '{\n\tabs = function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
}
format_test {
-- No special indent if no special function modifier.
adv_getlocal = true,
input = { max = function(a, b) return a > b and a or b end,
abs = function (x) return x < 0 and -x or x end
},
expect = '{\n\tabs = function (x) ... end,\n\tmax = function (a, b) ... end\n}',
}
--------------------------------------------------------------------------------
-- Userdata printing
-- TODO. First off figure out a way to test this stuff.
-- Maybe look into using the one available debug.getupvalue(pairs, 1)
--------------------------------------------------------------------------------
-- Thread printing
do
local suspended_coroutine = coroutine.create(function () end)
format_test {
input = suspended_coroutine,
approx = true,
expect = 'suspended coroutine: 0x%x+',
}
end
do
local dead_coroutine = coroutine.create(function () end)
coroutine.resume(dead_coroutine)
format_test {
input = dead_coroutine,
approx = true,
expect = 'dead coroutine: 0x%x+',
}
end
--------------------------------------------------------------------------------
-- Single-line tables
format_test {
input = {},
expect = '{}',
}
format_test {
input = {1, 2, 3},
expect = '{ 1, 2, 3 }',
}
format_test {
input = { 'Hello', 'World' },
expect = '{ \'Hello\', \'World\' }',
}
format_test {
input = { a = 1, b = 2 },
expect = '{ a = 1, b = 2 }',
}
format_test {
input = { __hello = true },
expect = '{ __hello = true }',
}
format_test {
input = { [']]'] = true },
expect = '{ [\']]\'] = true }',
}
format_test {
input = { ['and'] = true },
expect = '{ [\'and\'] = true }',
}
format_test {
input = { [false] = false, [true] = true },
expect = '{ [false] = false, [true] = true }',
}
format_test {
input = { [100] = 'Hi', [300] = 'Hello' },
expect = '{ [100] = \'Hi\', [300] = \'Hello\' }',
}
format_test { -- Order does not matter
input = { b = 1, a = 2 },
expect = '{ a = 2, b = 1 }',
}
format_test { -- Can include empty tables
input = { {}, {}, {} },
expect = '{ {}, {}, {} }',
}
format_test { -- Can include very small tables
input = { {1}, {2}, {3} },
expect = '{ { 1 }, { 2 }, { 3 } }',
}
--------------------------------------------------------------------------------
-- Multi-line tables
format_test {
input = { {1, 2, 3}, {4, 5, 6} },
expect = '{\n\t{ 1, 2, 3 },\n\t{ 4, 5, 6 }\n}',
}
format_test {
input = { a = {1, 2, 3}, b = {4, 5, 6} },
expect = '{\n\ta = { 1, 2, 3 },\n\tb = { 4, 5, 6 }\n}',
}
format_test {
input = { 'Hi', [300] = 'Hello' },
expect = '{\n\t[1] = \'Hi\',\n\t[300] = \'Hello\'\n}',
}
format_test {
input = { { {} } },
expect = '{\n\t{ {} }\n}',
}
format_test {
input = { [{ 1, 2 }] = { 2, 1 } },
expect = '{\n\t[{ 1, 2 }] = { 2, 1 }\n}',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
expect = '{\n\t{\n\t\t{ 1, 2 },\n\t\t{ 3, 4 }\n\t},\n\t{ 5, 6 }\n}',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 0 },
expect = '{...}',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 1 },
expect = '{\n\t{...},\n\t{...}\n}',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 2 },
expect = '{\n\t{\n\t\t{...},\n\t\t{...}\n\t},\n\t{ 5, 6 }\n}',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 3 },
expect = '{\n\t{\n\t\t{ 1, 2 },\n\t\t{ 3, 4 }\n\t},\n\t{ 5, 6 }\n}',
}
format_test {
input = { [{ {1,2}, {3,4} }] = 'Hello World' },
expect = '{\n\t[{...}] = \'Hello World\'\n}',
}
format_test {
input = { a = {1,2}, bcdefg = {3,4} },
expect = '{\n\ta = { 1, 2 },\n\tbcdefg = { 3, 4 }\n}',
}
format_test {
input = { [true] = 1, [1] = false },
expect = '{\n\t[true] = 1,\n\t[1] = false\n}',
}
format_test {
-- Proper indent
input = { [1] = 1, ['whatever'] = false },
expect = '{\n\t[1] = 1,\n\t[\'whatever\'] = false\n}',
}
format_test {
-- Table view, with indent.
input = { { a = 'hello', b = 'hi' }, { a = 'hi', b = 'hello' } },
expect = '{\n\t{ a = \'hello\', b = \'hi\' },\n\t{ a = \'hi\', b = \'hello\' }\n}',
}
--------------------------------------------------------------------------------
-- CDATA
-- TODO: Add more advanced understanding of cdata.
if type(jit) == 'table' then
local ffi = require('ffi')
ffi.cdef[[
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
]]
format_test {
input = ffi.C.poll,
approx = true,
expect = 'cdata<.+>: 0x%x+',
}
format_test {
input = ffi.new('int[10]'),
approx = true,
expect = 'cdata<.+>: 0x%x+',
}
end
--------------------------------------------------------------------------------
return SUITE