504 lines
19 KiB
Lua
504 lines
19 KiB
Lua
local function assertEquals(actual, expected, message)
|
|
if actual ~= expected then
|
|
error('Assertion failed: ' .. message
|
|
.. '\n actual: ' .. tostring(actual)
|
|
.. '\n expected: ' .. tostring(expected), 2)
|
|
end
|
|
end
|
|
|
|
local function assertThrows(msg_substr, fn)
|
|
local ok, err = pcall(fn)
|
|
if ok then
|
|
error('Assertion failed: expected error containing "'
|
|
.. msg_substr .. '"', 2)
|
|
end
|
|
if type(err) ~= 'string' then
|
|
err = tostring(err)
|
|
end
|
|
if not string.find(err, msg_substr, 1, true) then
|
|
error('Assertion failed: expected error message to contain "'
|
|
.. msg_substr .. '", got: "' .. err .. '"', 2)
|
|
end
|
|
end
|
|
|
|
-- %%: literal percent
|
|
assertEquals(string.format("%%"), "%", "%%: literal")
|
|
assertEquals(string.format("100%%"), "100%", "%%: 100%%")
|
|
assertEquals(string.format("%%%%"), "%%", "%%: %%%%")
|
|
assertEquals(string.format("a%%b%%c"), "a%b%c", "%%: a%%b%%c")
|
|
|
|
-- %d: basic integers
|
|
assertEquals(string.format("%d", 0), "0", "%d: 0")
|
|
assertEquals(string.format("%d", 1), "1", "%d: 1")
|
|
assertEquals(string.format("%d", -1), "-1", "%d: -1")
|
|
assertEquals(string.format("%d", 42), "42", "%d: 42")
|
|
assertEquals(string.format("%d", -42), "-42", "%d: -42")
|
|
assertEquals(string.format("%d", 2147483647), "2147483647", "%d: INT_MAX")
|
|
assertEquals(string.format("%d", -2147483648), "-2147483648", "%d: INT_MIN")
|
|
|
|
-- %i: alias for %d
|
|
assertEquals(string.format("%i", 42), "42", "%i: 42")
|
|
assertEquals(string.format("%i", -7), "-7", "%i: -7")
|
|
|
|
-- %d: width
|
|
assertEquals(string.format("%5d", 42), " 42", "%d: width 5")
|
|
assertEquals(string.format("%5d", -42), " -42", "%d: width 5 neg")
|
|
assertEquals(string.format("%1d", 42), "42", "%d: width 1 no pad")
|
|
|
|
-- %d: left-justify
|
|
assertEquals(string.format("%-5d", 42), "42 ", "%d: left 42")
|
|
assertEquals(string.format("%-5d", -42), "-42 ", "%d: left -42")
|
|
|
|
-- %d: zero-pad
|
|
assertEquals(string.format("%05d", 42), "00042", "%d: zero-pad 42")
|
|
assertEquals(string.format("%05d", -42), "-0042", "%d: zero-pad -42")
|
|
assertEquals(string.format("%05d", 0), "00000", "%d: zero-pad 0")
|
|
|
|
-- %d: plus flag
|
|
assertEquals(string.format("%+d", 42), "+42", "%d: +42")
|
|
assertEquals(string.format("%+d", -42), "-42", "%d: + -42")
|
|
assertEquals(string.format("%+d", 0), "+0", "%d: +0")
|
|
|
|
-- %d: space flag
|
|
assertEquals(string.format("% d", 42), " 42", "%d: space 42")
|
|
assertEquals(string.format("% d", -42), "-42", "%d: space -42")
|
|
assertEquals(string.format("% d", 0), " 0", "%d: space 0")
|
|
|
|
-- %d: precision
|
|
assertEquals(string.format("%.5d", 42), "00042", "%d: prec5 42")
|
|
assertEquals(string.format("%.5d", -42), "-00042", "%d: prec5 -42")
|
|
assertEquals(string.format("%.0d", 0), "", "%d: prec0 0")
|
|
assertEquals(string.format("%.0d", 1), "1", "%d: prec0 1")
|
|
assertEquals(string.format("%.1d", 0), "0", "%d: prec1 0")
|
|
|
|
-- %d: width and precision
|
|
assertEquals(string.format("%8.5d", 42), " 00042", "%d: w8 p5 42")
|
|
assertEquals(string.format("%-8.5d", 42), "00042 ", "%d: left w8 p5 42")
|
|
|
|
-- %u: unsigned integers
|
|
assertEquals(string.format("%u", 0), "0", "%u: 0")
|
|
assertEquals(string.format("%u", 42), "42", "%u: 42")
|
|
assertEquals(string.format("%u", -1), "18446744073709551615", "%u: -1")
|
|
assertEquals(string.format("%u", -42), "18446744073709551574", "%u: -42")
|
|
|
|
-- %o: octal
|
|
assertEquals(string.format("%o", 0), "0", "%o: 0")
|
|
assertEquals(string.format("%o", 8), "10", "%o: 8")
|
|
assertEquals(string.format("%o", 255), "377", "%o: 255")
|
|
assertEquals(string.format("%o", -1), "1777777777777777777777", "%o: -1")
|
|
|
|
-- %o: alt flag
|
|
assertEquals(string.format("%#o", 0), "0", "%#o: 0")
|
|
assertEquals(string.format("%#o", 8), "010", "%#o: 8")
|
|
assertEquals(string.format("%#o", 255), "0377", "%#o: 255")
|
|
|
|
-- %x: hex lowercase
|
|
assertEquals(string.format("%x", 0), "0", "%x: 0")
|
|
assertEquals(string.format("%x", 255), "ff", "%x: 255")
|
|
assertEquals(string.format("%x", 4095), "fff", "%x: 4095")
|
|
assertEquals(string.format("%x", -1), "ffffffffffffffff", "%x: -1")
|
|
|
|
-- %X: hex uppercase
|
|
assertEquals(string.format("%X", 255), "FF", "%X: 255")
|
|
assertEquals(string.format("%X", -1), "FFFFFFFFFFFFFFFF", "%X: -1")
|
|
|
|
-- %x: alt flag
|
|
assertEquals(string.format("%#x", 0), "0", "%#x: 0")
|
|
assertEquals(string.format("%#x", 255), "0xff", "%#x: 255")
|
|
assertEquals(string.format("%#X", 255), "0XFF", "%#X: 255")
|
|
|
|
-- %x: width and zero-pad
|
|
assertEquals(string.format("%08x", 255), "000000ff", "%x: zero-pad 255")
|
|
assertEquals(string.format("%#08x", 255), "0x0000ff", "%#x: zero-pad 255")
|
|
|
|
-- %c: character
|
|
assertEquals(string.format("%c", 65), "A", "%c: 65")
|
|
assertEquals(string.format("%c", 97), "a", "%c: 97")
|
|
assertEquals(string.format("%c", 48), "0", "%c: 48")
|
|
|
|
-- %c: width
|
|
assertEquals(string.format("%3c", 65), " A", "%c: width 3")
|
|
assertEquals(string.format("%-3c", 65), "A ", "%c: left width 3")
|
|
|
|
-- %s: strings
|
|
assertEquals(string.format("%s", "hello"), "hello", "%s: hello")
|
|
assertEquals(string.format("%s", ""), "", "%s: empty")
|
|
assertEquals(string.format("%s %s", "hello", "world"), "hello world", "%s: two")
|
|
|
|
-- %s: width
|
|
assertEquals(string.format("%10s", "hello"), " hello", "%s: width 10")
|
|
assertEquals(string.format("%-10s", "hello"), "hello ", "%s: left width 10")
|
|
|
|
-- %s: precision truncates
|
|
assertEquals(string.format("%.3s", "hello"), "hel", "%s: prec3")
|
|
assertEquals(string.format("%.10s", "hello"), "hello", "%s: prec10")
|
|
assertEquals(string.format("%.0s", "hello"), "", "%s: prec0")
|
|
|
|
-- %s: width and precision
|
|
assertEquals(string.format("%10.3s", "hello"), " hel", "%s: w10 p3")
|
|
assertEquals(string.format("%-10.3s", "hello"), "hel ", "%s: left w10 p3")
|
|
|
|
-- %f: basic floats
|
|
assertEquals(string.format("%f", 0), "0.000000", "%f: 0")
|
|
assertEquals(string.format("%f", 1), "1.000000", "%f: 1")
|
|
assertEquals(string.format("%f", -1), "-1.000000", "%f: -1")
|
|
assertEquals(string.format("%f", 3.14), "3.140000", "%f: 3.14")
|
|
assertEquals(string.format("%f", 0.1), "0.100000", "%f: 0.1")
|
|
|
|
-- %f: precision
|
|
assertEquals(string.format("%.2f", 3.14159), "3.14", "%f: prec2")
|
|
assertEquals(string.format("%.0f", 3.14159), "3", "%f: prec0")
|
|
assertEquals(string.format("%.10f", 1.0), "1.0000000000", "%f: prec10")
|
|
|
|
-- %f: width and precision
|
|
assertEquals(string.format("%10.2f", 3.14), " 3.14", "%f: w10 p2")
|
|
assertEquals(string.format("%-10.2f", 3.14), "3.14 ", "%f: left w10 p2")
|
|
assertEquals(string.format("%010.2f", 3.14), "0000003.14", "%f: zero-pad w10 p2")
|
|
|
|
-- %f: sign flags
|
|
assertEquals(string.format("%+f", 3.14), "+3.140000", "%f: +3.14")
|
|
assertEquals(string.format("%+f", -3.14), "-3.140000", "%f: + -3.14")
|
|
assertEquals(string.format("% f", 3.14), " 3.140000", "%f: space 3.14")
|
|
assertEquals(string.format("% f", -3.14), "-3.140000", "%f: space -3.14")
|
|
|
|
-- %f: non-finite
|
|
assertEquals(string.format("%f", 1/0), "inf", "%f: inf")
|
|
assertEquals(string.format("%f", -1/0), "-inf", "%f: -inf")
|
|
assertEquals(string.format("%f", 0/0), "-nan", "%f: nan")
|
|
assertEquals(string.format("%+f", 1/0), "+inf", "%f: +inf")
|
|
|
|
-- %f: width with non-finite
|
|
assertEquals(string.format("%10f", 1/0), " inf", "%f: w10 inf")
|
|
assertEquals(string.format("%-10f", 1/0), "inf ", "%f: left w10 inf")
|
|
|
|
-- %e: basic
|
|
assertEquals(string.format("%e", 0), "0.000000e+00", "%e: 0")
|
|
assertEquals(string.format("%e", 1), "1.000000e+00", "%e: 1")
|
|
assertEquals(string.format("%e", 100), "1.000000e+02", "%e: 100")
|
|
assertEquals(string.format("%e", 0.001), "1.000000e-03", "%e: 0.001")
|
|
assertEquals(string.format("%e", -42), "-4.200000e+01", "%e: -42")
|
|
|
|
-- %E: uppercase
|
|
assertEquals(string.format("%E", 100), "1.000000E+02", "%E: 100")
|
|
|
|
-- %e: precision
|
|
assertEquals(string.format("%.2e", 100), "1.00e+02", "%e: prec2")
|
|
assertEquals(string.format("%.0e", 100), "1e+02", "%e: prec0")
|
|
assertEquals(string.format("%.14e", 1), "1.00000000000000e+00", "%e: prec14")
|
|
|
|
-- %e: non-finite
|
|
assertEquals(string.format("%e", 1/0), "inf", "%e: inf")
|
|
assertEquals(string.format("%e", -1/0), "-inf", "%e: -inf")
|
|
assertEquals(string.format("%e", 0/0), "-nan", "%e: nan")
|
|
|
|
-- %e: width and flags
|
|
assertEquals(string.format("%15e", 100), " 1.000000e+02", "%e: w15")
|
|
assertEquals(string.format("%-15e", 100), "1.000000e+02 ", "%e: left w15")
|
|
assertEquals(string.format("%+e", 100), "+1.000000e+02", "%e: +100")
|
|
|
|
-- %g: basic
|
|
assertEquals(string.format("%g", 0), "0", "%g: 0")
|
|
assertEquals(string.format("%g", 1), "1", "%g: 1")
|
|
assertEquals(string.format("%g", 100), "100", "%g: 100")
|
|
assertEquals(string.format("%g", 100000), "100000", "%g: 100000")
|
|
assertEquals(string.format("%g", 1000000), "1e+06", "%g: 1000000")
|
|
assertEquals(string.format("%g", 0.0001), "0.0001", "%g: 0.0001")
|
|
assertEquals(string.format("%g", 0.00001), "1e-05", "%g: 0.00001")
|
|
assertEquals(string.format("%g", -42), "-42", "%g: -42")
|
|
|
|
-- %G: uppercase
|
|
assertEquals(string.format("%G", 1e6), "1E+06", "%G: 1e6")
|
|
assertEquals(string.format("%G", 1e-5), "1E-05", "%G: 1e-5")
|
|
|
|
-- %g: precision
|
|
assertEquals(string.format("%.1g", 3.14), "3", "%g: prec1")
|
|
assertEquals(string.format("%.2g", 3.14), "3.1", "%g: prec2")
|
|
assertEquals(string.format("%.4g", 3.14159), "3.142", "%g: prec4")
|
|
assertEquals(string.format("%.0g", 3.14), "3", "%g: prec0")
|
|
assertEquals(string.format("%.10g", 1), "1", "%g: prec10 int")
|
|
|
|
-- %g: strips trailing zeros
|
|
assertEquals(string.format("%.6g", 1.0), "1", "%g: strip 1.0")
|
|
assertEquals(string.format("%.6g", 1.5), "1.5", "%g: strip 1.5")
|
|
assertEquals(string.format("%.6g", 1.50), "1.5", "%g: strip 1.50")
|
|
assertEquals(string.format("%.14g", 1.0), "1", "%g: strip prec14 1.0")
|
|
assertEquals(string.format("%.14g", 1.5), "1.5", "%g: strip prec14 1.5")
|
|
|
|
-- %g: alt flag keeps trailing zeros and dot
|
|
assertEquals(string.format("%#g", 1.0), "1.00000", "%#g: 1.0")
|
|
assertEquals(string.format("%#.2g", 1.0), "1.0", "%#g: prec2 1.0")
|
|
assertEquals(string.format("%#.4g", 100), "100.0", "%#g: prec4 100")
|
|
|
|
-- %g: non-finite
|
|
assertEquals(string.format("%g", 1/0), "inf", "%g: inf")
|
|
assertEquals(string.format("%g", -1/0), "-inf", "%g: -inf")
|
|
assertEquals(string.format("%g", 0/0), "-nan", "%g: nan")
|
|
assertEquals(string.format("%+g", 1/0), "+inf", "%g: +inf")
|
|
|
|
-- %g: width and flags
|
|
assertEquals(string.format("%10g", 42), " 42", "%g: w10 42")
|
|
assertEquals(string.format("%-10g", 42), "42 ", "%g: left w10 42")
|
|
assertEquals(string.format("%010g", 42), "0000000042", "%g: zero-pad w10 42")
|
|
assertEquals(string.format("%+g", 42), "+42", "%g: +42")
|
|
assertEquals(string.format("% g", 42), " 42", "%g: space 42")
|
|
|
|
-- %g: Lua 5.4 %.14g reference values
|
|
assertEquals(string.format("%.14g", 0.0), "0", "%.14g: 0.0")
|
|
assertEquals(string.format("%.14g", 1.0), "1", "%.14g: 1.0")
|
|
assertEquals(string.format("%.14g", 1/3), "0.33333333333333", "%.14g: 1/3")
|
|
assertEquals(string.format("%.14g", math.pi), "3.1415926535898", "%.14g: pi")
|
|
assertEquals(string.format("%.14g", 1e-10), "1e-10", "%.14g: 1e-10")
|
|
assertEquals(string.format("%.14g", 1e18), "1e+18", "%.14g: 1e18")
|
|
assertEquals(string.format("%.14g", 2^63), "9.2233720368548e+18", "%.14g: 2^63")
|
|
assertEquals(string.format("%.14g", 2^53), "9.007199254741e+15", "%.14g: 2^53")
|
|
assertEquals(string.format("%.14g", 1.7976931348623e+308), "1.7976931348623e+308", "%.14g: max")
|
|
assertEquals(string.format("%.14g", 5e-324), "4.9406564584125e-324", "%.14g: min subnormal")
|
|
assertEquals(string.format("%.14g", 0/0), "-nan", "%.14g: nan")
|
|
assertEquals(string.format("%.14g", 1/0), "inf", "%.14g: inf")
|
|
assertEquals(string.format("%.14g", -1/0), "-inf", "%.14g: -inf")
|
|
|
|
-- mixed: multiple specifiers
|
|
assertEquals(string.format("%d + %d = %d", 1, 2, 3), "1 + 2 = 3", "mixed: d+d=d")
|
|
assertEquals(string.format("%s is %d", "age", 42), "age is 42", "mixed: s is d")
|
|
assertEquals(string.format("[%05d] %s (%.2f)", 7, "test", 3.14), "[00007] test (3.14)", "mixed: complex")
|
|
|
|
-- mixed: no specifiers
|
|
assertEquals(string.format("hello world"), "hello world", "mixed: no spec")
|
|
assertEquals(string.format(""), "", "mixed: empty")
|
|
|
|
-- error: invalid specifier (Lua 5.4 says "invalid conversion", 5.5 may differ)
|
|
do
|
|
local ok = pcall(string.format, "%z", 1)
|
|
assertEquals(ok, false, "%z: should error")
|
|
end
|
|
|
|
-- error: trailing percent
|
|
do
|
|
local ok = pcall(string.format, "abc%")
|
|
assertEquals(ok, false, "trailing %%: should error")
|
|
end
|
|
|
|
-- %f: negative zero
|
|
assertEquals(string.format("%f", -0.0), "-0.000000", "%f: -0.0")
|
|
assertEquals(string.format("%e", -0.0), "-0.000000e+00", "%e: -0.0")
|
|
assertEquals(string.format("%g", -0.0), "-0", "%g: -0.0")
|
|
|
|
-- %f: large precision
|
|
do
|
|
local s = string.format("%.20f", 1.0)
|
|
assertEquals(string.find(s, "%.") ~= nil, true, "%f: large prec has dot")
|
|
assertEquals(#s, 22, "%f: large prec length")
|
|
end
|
|
|
|
-- zero width is no-op
|
|
assertEquals(string.format("%0d", 42), "42", "%0d: no-op")
|
|
|
|
-- %a: basic hex floats
|
|
assertEquals(string.format("%a", 0), "0x0p+0", "%a: 0")
|
|
assertEquals(string.format("%a", 1), "0x1p+0", "%a: 1")
|
|
assertEquals(string.format("%a", -1), "-0x1p+0", "%a: -1")
|
|
assertEquals(string.format("%a", 2), "0x1p+1", "%a: 2")
|
|
assertEquals(string.format("%a", 0.5), "0x1p-1", "%a: 0.5")
|
|
assertEquals(string.format("%a", 1.5), "0x1.8p+0", "%a: 1.5")
|
|
assertEquals(string.format("%a", -0.0), "-0x0p+0", "%a: -0.0")
|
|
|
|
-- %A: uppercase
|
|
assertEquals(string.format("%A", 1.5), "0X1.8P+0", "%A: 1.5")
|
|
assertEquals(string.format("%A", 255), "0X1.FEP+7", "%A: 255")
|
|
|
|
-- %a: precision
|
|
assertEquals(string.format("%.0a", 1.5), "0x2p+0", "%a: prec0 1.5")
|
|
assertEquals(string.format("%.1a", 1.5), "0x1.8p+0", "%a: prec1 1.5")
|
|
assertEquals(string.format("%.4a", 1.5), "0x1.8000p+0", "%a: prec4 1.5")
|
|
assertEquals(string.format("%.4a", 1), "0x1.0000p+0", "%a: prec4 1")
|
|
|
|
-- %a: width and flags
|
|
assertEquals(string.format("%20a", 1.5), " 0x1.8p+0", "%a: w20 1.5")
|
|
assertEquals(string.format("%-20a", 1.5), "0x1.8p+0 ", "%a: left w20 1.5")
|
|
assertEquals(string.format("%+a", 1.5), "+0x1.8p+0", "%a: +1.5")
|
|
assertEquals(string.format("% a", 1.5), " 0x1.8p+0", "%a: space 1.5")
|
|
|
|
-- %a: non-finite
|
|
assertEquals(string.format("%a", 1/0), "inf", "%a: inf")
|
|
assertEquals(string.format("%a", -1/0), "-inf", "%a: -inf")
|
|
assertEquals(string.format("%a", 0/0), "-nan", "%a: nan")
|
|
assertEquals(string.format("%A", 1/0), "INF", "%A: inf")
|
|
|
|
-- %a: Math.PI
|
|
assertEquals(string.format("%a", math.pi), "0x1.921fb54442d18p+1", "%a: pi")
|
|
|
|
-- %a: 0.1
|
|
assertEquals(string.format("%a", 0.1), "0x1.999999999999ap-4", "%a: 0.1")
|
|
|
|
-- %q: nil and booleans
|
|
assertEquals(string.format("%q", nil), "nil", "%q: nil")
|
|
assertEquals(string.format("%q", true), "true", "%q: true")
|
|
assertEquals(string.format("%q", false), "false", "%q: false")
|
|
|
|
-- %q: integers
|
|
assertEquals(string.format("%q", 0), "0", "%q: 0")
|
|
assertEquals(string.format("%q", 1), "1", "%q: 1")
|
|
assertEquals(string.format("%q", -1), "-1", "%q: -1")
|
|
assertEquals(string.format("%q", 42), "42", "%q: 42")
|
|
assertEquals(string.format("%q", -42), "-42", "%q: -42")
|
|
|
|
-- %q: floats as hex
|
|
assertEquals(string.format("%q", 1.5), "0x1.8p+0", "%q: 1.5")
|
|
assertEquals(string.format("%q", 0.1), "0x1.999999999999ap-4", "%q: 0.1")
|
|
assertEquals(string.format("%q", math.pi), "0x1.921fb54442d18p+1", "%q: pi")
|
|
assertEquals(string.format("%q", -0.5), "-0x1p-1", "%q: -0.5")
|
|
assertEquals(string.format("%q", -0.0), "-0x0p+0", "%q: -0.0")
|
|
|
|
-- %q: non-finite numbers
|
|
assertEquals(string.format("%q", 0/0), "(0/0)", "%q: nan")
|
|
assertEquals(string.format("%q", 1/0), "1e9999", "%q: inf")
|
|
assertEquals(string.format("%q", -1/0), "-1e9999", "%q: -inf")
|
|
|
|
-- %q: simple strings
|
|
assertEquals(string.format("%q", "hello"), '"hello"', "%q: hello")
|
|
assertEquals(string.format("%q", ""), '""', "%q: empty")
|
|
|
|
-- %q: strings with special characters
|
|
assertEquals(string.format("%q", 'say "hi"'), '"say \\"hi\\""', '%q: quotes')
|
|
assertEquals(string.format("%q", "back\\slash"), '"back\\\\slash"', "%q: backslash")
|
|
assertEquals(string.format("%q", "line\nbreak"), '"line\\\nbreak"', "%q: newline")
|
|
assertEquals(string.format("%q", "cr\rreturn"), '"cr\\13return"', "%q: cr")
|
|
assertEquals(string.format("%q", "tab\there"), '"tab\\9here"', "%q: tab")
|
|
|
|
-- %q: Lua reference example
|
|
do
|
|
local result = string.format("%q", 'a string with "quotes" and \n new line')
|
|
assertEquals(result, '"a string with \\"quotes\\" and \\\n new line"', "%q: reference")
|
|
end
|
|
|
|
-- %q: mixed with other specifiers
|
|
assertEquals(
|
|
string.format("name=%q age=%d", "Alice", 30),
|
|
'name="Alice" age=30',
|
|
"%q: mixed"
|
|
)
|
|
|
|
-- %p: pointer-like identity for tables
|
|
do
|
|
local t1 = {}
|
|
local t2 = {}
|
|
local s1 = string.format("%p", t1)
|
|
local s2 = string.format("%p", t2)
|
|
-- starts with 0x
|
|
assertEquals(s1:sub(1, 2), "0x", "%p: table prefix")
|
|
-- same object gives same result
|
|
assertEquals(string.format("%p", t1), s1, "%p: stable identity")
|
|
-- different objects give different results
|
|
assertEquals(s1 ~= s2, true, "%p: distinct tables differ")
|
|
end
|
|
|
|
-- %p: functions get an identity too
|
|
do
|
|
local f1 = function() end
|
|
local f2 = function() end
|
|
local s1 = string.format("%p", f1)
|
|
local s2 = string.format("%p", f2)
|
|
assertEquals(s1:sub(1, 2), "0x", "%p: function prefix")
|
|
assertEquals(s1 ~= s2, true, "%p: distinct functions differ")
|
|
end
|
|
|
|
-- %p: nil and primitives yield (null)
|
|
assertEquals(string.format("%p", nil), "(null)", "%p: nil")
|
|
assertEquals(string.format("%p", true), "(null)", "%p: boolean")
|
|
assertEquals(string.format("%p", 42), "(null)", "%p: number")
|
|
|
|
-- %p: strings get an identity (they are GC objects in Lua)
|
|
do
|
|
local s = string.format("%p", "hello")
|
|
assertEquals(s:sub(1, 2), "0x", "%p: string prefix")
|
|
end
|
|
|
|
-- %p: width
|
|
do
|
|
local t = {}
|
|
local s = string.format("%20p", t)
|
|
assertEquals(#s >= 20, true, "%p: width pads")
|
|
end
|
|
|
|
-- %p: left-justify
|
|
do
|
|
local t = {}
|
|
local s = string.format("%-20p", t)
|
|
assertEquals(#s >= 20, true, "%p: left width pads")
|
|
-- trailing spaces
|
|
assertEquals(s:sub(#s, #s), " ", "%p: left-justify trailing space")
|
|
end
|
|
|
|
-- %p: pointer-like identity for tables
|
|
do
|
|
local t1 = {}
|
|
local t2 = {}
|
|
local s1 = string.format("%p", t1)
|
|
local s2 = string.format("%p", t2)
|
|
assertEquals(s1:sub(1, 2), "0x", "%p: table prefix")
|
|
assertEquals(string.format("%p", t1), s1, "%p: table stable identity")
|
|
assertEquals(s1 ~= s2, true, "%p: distinct tables differ")
|
|
end
|
|
|
|
-- %p: functions get an identity too
|
|
do
|
|
local f1 = function() end
|
|
local f2 = function() end
|
|
local s1 = string.format("%p", f1)
|
|
local s2 = string.format("%p", f2)
|
|
assertEquals(s1:sub(1, 2), "0x", "%p: function prefix")
|
|
assertEquals(string.format("%p", f1), s1, "%p: function stable identity")
|
|
assertEquals(s1 ~= s2, true, "%p: distinct functions differ")
|
|
end
|
|
|
|
-- %p: strings get an identity (interned: same content = same id)
|
|
do
|
|
local s1 = string.format("%p", "hello")
|
|
local s2 = string.format("%p", "hello")
|
|
local s3 = string.format("%p", "world")
|
|
assertEquals(s1:sub(1, 2), "0x", "%p: string prefix")
|
|
assertEquals(s1, s2, "%p: same string content = same id")
|
|
assertEquals(s1 ~= s3, true, "%p: different string content differs")
|
|
end
|
|
|
|
-- %p: nil and primitives yield (null)
|
|
assertEquals(string.format("%p", nil), "(null)", "%p: nil")
|
|
assertEquals(string.format("%p", true), "(null)", "%p: boolean")
|
|
assertEquals(string.format("%p", 42), "(null)", "%p: number")
|
|
|
|
-- %p: repeated calls on same table are stable
|
|
do
|
|
local t = {}
|
|
local ids = {}
|
|
for i = 1, 5 do
|
|
ids[i] = string.format("%p", t)
|
|
end
|
|
for i = 2, 5 do
|
|
assertEquals(ids[i], ids[1], "%p: repeated call #" .. i .. " stable")
|
|
end
|
|
end
|
|
|
|
-- %p: table stored in another table keeps identity
|
|
do
|
|
local inner = {}
|
|
local outer = { ref = inner }
|
|
local s1 = string.format("%p", inner)
|
|
local s2 = string.format("%p", outer.ref)
|
|
assertEquals(s1, s2, "%p: table via reference stable")
|
|
end
|
|
|
|
-- %p: width
|
|
do
|
|
local t = {}
|
|
local s = string.format("%20p", t)
|
|
assertEquals(#s >= 20, true, "%p: width pads")
|
|
end
|
|
|
|
-- %p: left-justify
|
|
do
|
|
local t = {}
|
|
local s = string.format("%-20p", t)
|
|
assertEquals(#s >= 20, true, "%p: left width pads")
|
|
assertEquals(s:sub(#s, #s), " ", "%p: left-justify trailing space")
|
|
end
|