1
0
pretty/test/test_pretty.lua
Jon Michael Aanes 93beb4bd1e Finally implemented column alignment
It's currently a bit limited in scope, but looks great when active.
2017-07-20 12:01:46 +02:00

420 lines
9.8 KiB
Lua

local SUITE = require 'TestSuite' 'pretty'
SUITE:setEnviroment{
format = require('pretty')
}
local ASSERT_ERROR_APPROX = [[
Approximate strings not similar enough:
Should match: %s
Gotten: %s
]]
--------------------------------------------------------------------------------
-- Compat
if not loadstring then loadstring = load end -- Lua 5.3 compat
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams -- Lua 5.1 compat
local HAS_UNICODE_IDEN = not not loadstring 'local ϕ = 1; return ϕ' -- Lua 5.1 compat
local HAS_JIT_LIBRARY = type(rawget(_G, 'jit')) == 'table' -- Non-LuaJIT compat
--
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.name or t.expect, function ()
local actual_result = format(t.input, t.options)
if not t.approx or type(actual_result) ~= 'string' then
assert_equal(t.expect, actual_result)
else
if not actual_result:match(t.expect) then
error(ASSERT_ERROR_APPROX:format(t.expect, actual_result))
end
end
end, { line = debug.getinfo(2).currentline })
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 = '\'ø\'',
}
--------------------------------------------------------------------------------
-- Primitive types
format_test {
input = nil,
expect = 'nil',
}
format_test {
input = true,
expect = 'true',
}
format_test {
input = false,
expect = 'false',
}
--------------------------------------------------------------------------------
-- Userdata printing
-- TODO: Figure out a way to print userdata.
-- 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 { -- 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 = '{ { 1, 2, 3 }, { 4, 5, 6 } }',
}
format_test {
input = { a = {1, 2, 3}, b = {4, 5, 6} },
expect = '{ a = { 1, 2, 3 }, b = { 4, 5, 6 } }',
}
format_test {
name = 'Unicode characters can be used as string keys in tables',
input = { ['a'] = 1, ['ψ'] = 2 },
expect = '{ a = 1, ψ = 2 }',
}
format_test {
input = { [100] = 'Hi', [300] = 'Hello' },
expect = '{ [100] = \'Hi\', [300] = \'Hello\' }',
}
format_test {
input = { 'Hi', [300] = 'Hello' },
expect = '{ [1] = \'Hi\', [300] = \'Hello\' }',
}
format_test {
input = { { {} } },
expect = '{ { {} } }',
}
format_test {
input = { [{ 1, 2 }] = { 2, 1 } },
expect = '{ [{ 1, 2 }] = { 2, 1 } }',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
expect = '{ { { 1, 2 }, { 3, 4 } }, { 5, 6 } }',
}
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 = '{ {...}, {...} }',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 2 },
expect = '{ { {...}, {...} }, { 5, 6 } }',
}
format_test {
input = { { {1, 2}, {3, 4} }, {5, 6} },
options = { max_depth = 3 },
expect = '{ { { 1, 2 }, { 3, 4 } }, { 5, 6 } }',
}
format_test {
input = { [{ {1,2}, {3,4} }] = 'Hello World' },
expect = '{ [{...}] = \'Hello World\' }',
}
format_test {
input = { a = {1,2}, bcdefg = {3,4} },
expect = '{ a = { 1, 2 }, bcdefg = { 3, 4 } }',
}
format_test {
input = { [true] = 1, [1] = false },
expect = '{ [1] = false, [true] = 1 }',
}
format_test {
-- Proper indent
input = { [1] = 1, ['whatever'] = false },
expect = '{ [1] = 1, [\'whatever\'] = false }',
}
format_test {
-- Table view, with indent.
input = { { a = 'hello', b = 'hi' }, { a = 'hi', b = 'hello' } },
expect = '{\n { a = \'hello\', b = \'hi\' },\n { a = \'hi\', b = \'hello\' }\n}',
}
format_test {
name = 'Proper alignment when using unicode characters as keys',
input = {
['djævle'] = 'dyr?',
['europa'] = 'måne',
['øå'] = 'en å på en ø?',
},
expect = '{\n djævle = \'dyr?\',\n europa = \'måne\',\n øå = \'en å på en ø?\'\n}',
}
format_test {
name = 'Format table into columns, if leaf node',
input = {
'hello', 'world', 'how',
'is', 'it', 'going?',
'Im', 'doing great', 'thanks',
'that', 'was', 'what',
'I', 'were', 'expecting'
},
expect = '{\n \'hello\', \'world\', \'how\',\n \'is\', \'it\', \'going?\',\n \'Im\', \'doing great\', \'thanks\',\n \'that\', \'was\', \'what\',\n \'I\', \'were\', \'expecting\'\n}',
}
--------------------------------------------------------------------------------
-- Table recursion
do
local recursive = {}
recursive[1] = recursive
format_test {
input = recursive,
options = { max_depth = 5 },
expect = '{ {...} }',
}
format_test {
input = recursive,
options = { max_depth = 5, recursion = 'ignore' },
expect = '{ {...} }',
}
format_test {
input = recursive,
options = { max_depth = 5, recursion = 'marked' },
expect = '<1>{ <1>{...} }',
}
end
do
local a = {}
local b = { a }
a[1] = b
local rec = { a = a, b = b }
format_test {
name = 'Top layers should be expanded, rather than lower layers.',
input = rec,
options = { max_depth = 5 },
expect = '{\n a = { {...} },\n b = { {...} }\n}',
}
end
--------------------------------------------------------------------------------
-- CDATA
-- TODO: Add more advanced understanding of cdata.
if HAS_JIT_LIBRARY 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
--------------------------------------------------------------------------------
-- General
SUITE:addTest('UseCase: Can print _G with max_depth = 1', function ()
format(_G, {max_depth = 1})
assert(true)
end)
SUITE:addTest('UseCase: Can load function from file that is shortly deleted', function ()
local module_name = 'tmp_'..os.time()
-- Create module
local file = io.open('./'..module_name..'.lua', 'w')
file:write '\nlocal function yo ()\n -- Hello World\n return math.random()\nend\n\nreturn yo\n'
file:close()
-- Load module
local yo = require(module_name)
-- Remove module
os.remove('./'..module_name..'.lua')
package.loaded[module_name] = nil
-- Format the function, even though the module it came from is gone.
format(yo)
assert(true)
end)
--------------------------------------------------------------------------------
return SUITE