|
| 1 | +local ffi = require('ffi') |
| 2 | +local tap = require('tap') |
| 3 | + |
| 4 | +-- The test file to test various FFI C vararg calls. |
| 5 | +-- luacheck: push no max_comment_line_length |
| 6 | +-- Originated from: https://github.com/neovim/neovim/blob/a5aa62e37b82214a1d4d1e0a54d193b155fb340c/test/unit/strings_spec.lua |
| 7 | +-- luacheck: pop |
| 8 | +-- See also: https://github.com/LuaJIT/LuaJIT/issues/1455. |
| 9 | + |
| 10 | +local test = tap.test('lj-1455-macos-arm64-vararg-regression') |
| 11 | + |
| 12 | +test:plan(45) |
| 13 | + |
| 14 | +ffi.cdef('int sprintf(char *str, const char *format, ...);') |
| 15 | + |
| 16 | +local buf = ffi.new('char[64]') |
| 17 | + |
| 18 | +local function t(expected, fmt, ...) |
| 19 | + local args = {...} |
| 20 | + local ctx = string.format('sprintf(buf, "%s"', fmt) |
| 21 | + for _, x in ipairs(args) do |
| 22 | + ctx = ctx .. ', ' .. tostring(x) |
| 23 | + end |
| 24 | + ctx = ctx .. string.format(') = %s', expected) |
| 25 | + |
| 26 | + test:test(ctx, function(subtest, ...) |
| 27 | + subtest:plan(2) |
| 28 | + subtest:is(ffi.C.sprintf(buf, fmt, ...), #expected, |
| 29 | + ctx .. ' - return status') |
| 30 | + subtest:is(ffi.string(buf), expected, ctx .. ' - result string') |
| 31 | + end, ...) |
| 32 | +end |
| 33 | + |
| 34 | +local function i(n) |
| 35 | + return ffi.cast('int', n) |
| 36 | +end |
| 37 | + |
| 38 | +local function l(n) |
| 39 | + return ffi.cast('long', n) |
| 40 | +end |
| 41 | + |
| 42 | +local function ll(n) |
| 43 | + return ffi.cast('long long', n) |
| 44 | +end |
| 45 | + |
| 46 | +local function z(n) |
| 47 | + return ffi.cast('ptrdiff_t', n) |
| 48 | +end |
| 49 | + |
| 50 | +local function u(n) |
| 51 | + return ffi.cast('unsigned', n) |
| 52 | +end |
| 53 | + |
| 54 | +local function ul(n) |
| 55 | + return ffi.cast('unsigned long', n) |
| 56 | +end |
| 57 | + |
| 58 | +local function ull(n) |
| 59 | + return ffi.cast('unsigned long long', n) |
| 60 | +end |
| 61 | + |
| 62 | +local function uz(n) |
| 63 | + return ffi.cast('size_t', n) |
| 64 | +end |
| 65 | + |
| 66 | +t('1234567', '%d', i(1234567)) |
| 67 | +t('1234567', '%ld', l(1234567)) |
| 68 | +t(' 1234567', '%9ld', l(1234567)) |
| 69 | +t('1234567 ', '%-9ld', l(1234567)) |
| 70 | +t('deadbeef', '%x', u(0xdeadbeef)) |
| 71 | +t('one two', '%s %s', 'one', 'two') |
| 72 | +t('1.234000', '%f', 1.234) |
| 73 | +t('1.234000e+00', '%e', 1.234) |
| 74 | +t('inf', '%f', 1.0 / 0.0) |
| 75 | +t('-inf', '%f', -1.0 / 0.0) |
| 76 | +t('-0.000000', '%f', tonumber('-0.0')) |
| 77 | +t('%%%', '%%%%%%') |
| 78 | +t('0x87654321', '%p', ffi.cast('char *', 0x87654321)) |
| 79 | +t('0x0087654321', '%012p', ffi.cast('char *', 0x87654321)) |
| 80 | +t('1234567 ', '%1$*2$ld', l(1234567), i(-9)) |
| 81 | +t('1234567 ', '%1$*2$.*3$ld', l(1234567), i(-9), i(5)) |
| 82 | +t('1234567 ', '%1$*3$.*2$ld', l(1234567), i(5), i(-9)) |
| 83 | +t('1234567 ', '%3$*1$.*2$ld', i(-9), i(5), l(1234567)) |
| 84 | +t('1234567', '%1$ld', l(1234567)) |
| 85 | +t(' 1234567', '%1$*2$ld', l(1234567), i(9)) |
| 86 | +t('9 12345 7654321', '%2$ld %1$d %3$lu', i(12345), l(9), ul(7654321)) |
| 87 | +t('9 1234567 7654321', '%2$d %1$ld %3$lu', l(1234567), i(9), ul(7654321)) |
| 88 | +t('9 1234567 7654321', '%2$d %1$lld %3$lu', ll(1234567), i(9), ul(7654321)) |
| 89 | +t('9 12345 7654321', '%2$ld %1$u %3$lu', u(12345), l(9), ul(7654321)) |
| 90 | +t('9 1234567 7654321', '%2$d %1$lu %3$lu', ul(1234567), i(9), ul(7654321)) |
| 91 | +t('9 1234567 7654321', '%2$d %1$llu %3$lu', ull(1234567), i(9), ul(7654321)) |
| 92 | +t('9 deadbeef 7654321', '%2$d %1$x %3$lu', u(0xdeadbeef), i(9), ul(7654321)) |
| 93 | +t('9 c 7654321', '%2$ld %1$c %3$lu', i(('c'):byte()), l(9), ul(7654321)) |
| 94 | +t('9 hi 7654321', '%2$ld %1$s %3$lu', 'hi', l(9), ul(7654321)) |
| 95 | +t('9 0.000000e+00 7654321', '%2$ld %1$e %3$lu', 0.0, l(9), ul(7654321)) |
| 96 | +t('two one two', '%2$s %1$s %2$s', 'one', 'two', 'three') |
| 97 | +t('three one two', '%3$s %1$s %2$s', 'one', 'two', 'three') |
| 98 | +t('1234567', '%1$d', i(1234567)) |
| 99 | +t('deadbeef', '%1$x', u(0xdeadbeef)) |
| 100 | +t('one two', '%1$s %2$s', 'one', 'two') |
| 101 | +t('two one', '%2$s %1$s', 'one', 'two') |
| 102 | +t('1.234000', '%1$f', 1.234) |
| 103 | +t('1.234000e+00', '%1$e', 1.234) |
| 104 | +t('inf', '%1$f', 1.0 / 0.0) |
| 105 | +t('-inf', '%1$f', -1.0 / 0.0) |
| 106 | +t('-0.000000', '%1$f', tonumber('-0.0')) |
| 107 | +t('-1234567 -7654321', '%zd %zd', z(-1234567), z(-7654321)) |
| 108 | +t('-7654321 -1234567', '%2$zd %1$zd', z(-1234567), z(-7654321)) |
| 109 | +t('1234567 7654321', '%zu %zu', uz(1234567), uz(7654321)) |
| 110 | +t('7654321 1234567', '%2$zu %1$zu', uz(1234567), uz(7654321)) |
| 111 | + |
| 112 | +test:done(true) |
0 commit comments