diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
| commit | 1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch) | |
| tree | cd08258054db80bb9a11b1061bb091c70b76926a /test/unit | |
| parent | eaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff) | |
| parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
| download | rneovim-aucmd_textputpost.tar.gz rneovim-aucmd_textputpost.tar.bz2 rneovim-aucmd_textputpost.zip | |
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'test/unit')
27 files changed, 1483 insertions, 1237 deletions
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua index a54ea8c656..6e08a09295 100644 --- a/test/unit/buffer_spec.lua +++ b/test/unit/buffer_spec.lua @@ -1,15 +1,11 @@ - local helpers = require("test.unit.helpers")(after_each) local itp = helpers.gen_itp(it) local to_cstr = helpers.to_cstr -local get_str = helpers.ffi.string local eq = helpers.eq local NULL = helpers.NULL -local globals = helpers.cimport("./src/nvim/globals.h") local buffer = helpers.cimport("./src/nvim/buffer.h") -local stl = helpers.cimport("./src/nvim/statusline.h") describe('buffer functions', function() @@ -210,276 +206,4 @@ describe('buffer functions', function() close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0) end) end) - - describe('build_stl_str_hl', function() - local buffer_byte_size = 100 - local STL_INITIAL_ITEMS = 20 - local output_buffer = '' - - -- This function builds the statusline - -- - -- @param arg Optional arguments are: - -- .pat The statusline format string - -- .fillchar The fill character used in the statusline - -- .maximum_cell_count The number of cells available in the statusline - local function build_stl_str_hl(arg) - output_buffer = to_cstr(string.rep(" ", buffer_byte_size)) - - local pat = arg.pat or '' - local fillchar = arg.fillchar or (' '):byte() - local maximum_cell_count = arg.maximum_cell_count or buffer_byte_size - - return stl.build_stl_str_hl(globals.curwin, - output_buffer, - buffer_byte_size, - to_cstr(pat), - NULL, - 0, - fillchar, - maximum_cell_count, - NULL, - NULL, - NULL) - end - - -- Use this function to simplify testing the comparison between - -- the format string and the resulting statusline. - -- - -- @param description The description of what the test should be doing - -- @param statusline_cell_count The number of cells available in the statusline - -- @param input_stl The format string for the statusline - -- @param expected_stl The expected result string for the statusline - -- - -- @param arg Options can be placed in an optional dictionary as the last parameter - -- .expected_cell_count The expected number of cells build_stl_str_hl will return - -- .expected_byte_length The expected byte length of the string (defaults to byte length of expected_stl) - -- .file_name The name of the file to be tested (useful in %f type tests) - -- .fillchar The character that will be used to fill any 'extra' space in the stl - local function statusline_test (description, - statusline_cell_count, - input_stl, - expected_stl, - arg) - - -- arg is the optional parameter - -- so we either fill in option with arg or an empty dictionary - local option = arg or {} - - local fillchar = option.fillchar or (' '):byte() - local expected_cell_count = option.expected_cell_count or statusline_cell_count - local expected_byte_length = option.expected_byte_length or #expected_stl - - itp(description, function() - if option.file_name then - buffer.setfname(globals.curbuf, to_cstr(option.file_name), NULL, 1) - else - buffer.setfname(globals.curbuf, nil, NULL, 1) - end - - local result_cell_count = build_stl_str_hl{pat=input_stl, - maximum_cell_count=statusline_cell_count, - fillchar=fillchar} - - eq(expected_stl, get_str(output_buffer, expected_byte_length)) - eq(expected_cell_count, result_cell_count) - end) - end - - -- expression testing - statusline_test('Should expand expression', 2, - '%!expand(20+1)', '21') - statusline_test('Should expand broken expression to itself', 11, - '%!expand(20+1', 'expand(20+1') - - -- file name testing - statusline_test('should print no file name', 10, - '%f', '[No Name]', - {expected_cell_count=9}) - statusline_test('should print the relative file name', 30, - '%f', 'test/unit/buffer_spec.lua', - {file_name='test/unit/buffer_spec.lua', expected_cell_count=25}) - statusline_test('should print the full file name', 40, - '%F', '/test/unit/buffer_spec.lua', - {file_name='/test/unit/buffer_spec.lua', expected_cell_count=26}) - - -- fillchar testing - statusline_test('should handle `!` as a fillchar', 10, - 'abcde%=', 'abcde!!!!!', - {fillchar=('!'):byte()}) - statusline_test('should handle `~` as a fillchar', 10, - '%=abcde', '~~~~~abcde', - {fillchar=('~'):byte()}) - statusline_test('should put fillchar `!` in between text', 10, - 'abc%=def', 'abc!!!!def', - {fillchar=('!'):byte()}) - statusline_test('should put fillchar `~` in between text', 10, - 'abc%=def', 'abc~~~~def', - {fillchar=('~'):byte()}) - statusline_test('should put fillchar `━` in between text', 10, - 'abc%=def', 'abc━━━━def', - {fillchar=0x2501}) - statusline_test('should handle zero-fillchar as a space', 10, - 'abcde%=', 'abcde ', - {fillchar=0}) - statusline_test('should print the tail file name', 80, - '%t', 'buffer_spec.lua', - {file_name='test/unit/buffer_spec.lua', expected_cell_count=15}) - - -- standard text testing - statusline_test('should copy plain text', 80, - 'this is a test', 'this is a test', - {expected_cell_count=14}) - - -- line number testing - statusline_test('should print the buffer number', 80, - '%n', '1', - {expected_cell_count=1}) - statusline_test('should print the current line number in the buffer', 80, - '%l', '0', - {expected_cell_count=1}) - statusline_test('should print the number of lines in the buffer', 80, - '%L', '1', - {expected_cell_count=1}) - - -- truncation testing - statusline_test('should truncate when standard text pattern is too long', 10, - '0123456789abcde', '<6789abcde') - statusline_test('should truncate when using =', 10, - 'abcdef%=ghijkl', 'abcdef<jkl') - statusline_test('should truncate centered text when using ==', 10, - 'abcde%=gone%=fghij', 'abcde<ghij') - statusline_test('should respect the `<` marker', 10, - 'abc%<defghijkl', 'abc<ghijkl') - statusline_test('should truncate at `<` with one `=`, test 1', 10, - 'abc%<def%=ghijklmno', 'abc<jklmno') - statusline_test('should truncate at `<` with one `=`, test 2', 10, - 'abcdef%=ghijkl%<mno', 'abcdefghi>') - statusline_test('should truncate at `<` with one `=`, test 3', 10, - 'abc%<def%=ghijklmno', 'abc<jklmno') - statusline_test('should truncate at `<` with one `=`, test 4', 10, - 'abc%<def%=ghij', 'abcdefghij') - statusline_test('should truncate at `<` with one `=`, test 4', 10, - 'abc%<def%=ghijk', 'abc<fghijk') - - statusline_test('should truncate at `<` with many `=`, test 4', 10, - 'ab%<cdef%=g%=h%=ijk', 'ab<efghijk') - - statusline_test('should truncate at the first `<`', 10, - 'abc%<def%<ghijklm', 'abc<hijklm') - - statusline_test('should ignore trailing %', 3, 'abc%', 'abc') - - -- alignment testing with fillchar - local function statusline_test_align (description, - statusline_cell_count, - input_stl, - expected_stl, - arg) - arg = arg or {} - statusline_test(description .. ' without fillchar', - statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg) - arg.fillchar = ('!'):byte() - statusline_test(description .. ' with fillchar `!`', - statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg) - arg.fillchar = 0x2501 - statusline_test(description .. ' with fillchar `━`', - statusline_cell_count, input_stl, expected_stl:gsub('%~', '━'), arg) - end - - statusline_test_align('should right align when using =', 20, - 'neo%=vim', 'neo~~~~~~~~~~~~~~vim') - statusline_test_align('should, when possible, center text when using %=text%=', 20, - 'abc%=neovim%=def', 'abc~~~~neovim~~~~def') - statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20, - 'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def') - statusline_test_align('should have equal spaces even with non-equal sides when using =', 20, - 'foobar%=test%=baz', 'foobar~~~test~~~~baz') - statusline_test_align('should have equal spaces even with longer right side when using =', 20, - 'a%=test%=longtext', 'a~~~test~~~~longtext') - statusline_test_align('should handle an empty left side when using ==', 20, - '%=test%=baz', '~~~~~~test~~~~~~~baz') - statusline_test_align('should handle an empty right side when using ==', 20, - 'foobar%=test%=', 'foobar~~~~~test~~~~~') - statusline_test_align('should handle consecutive empty ==', 20, - '%=%=test%=', '~~~~~~~~~~test~~~~~~') - statusline_test_align('should handle an = alone', 20, - '%=', '~~~~~~~~~~~~~~~~~~~~') - statusline_test_align('should right align text when it is alone with =', 20, - '%=foo', '~~~~~~~~~~~~~~~~~foo') - statusline_test_align('should left align text when it is alone with =', 20, - 'foo%=', 'foo~~~~~~~~~~~~~~~~~') - - statusline_test_align('should approximately center text when using %=text%=', 21, - 'abc%=neovim%=def', 'abc~~~~neovim~~~~~def') - statusline_test_align('should completely fill the buffer when using %=text%=', 21, - 'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def') - statusline_test_align('should have equal spacing even with non-equal sides when using =', 21, - 'foobar%=test%=baz', 'foobar~~~~test~~~~baz') - statusline_test_align('should have equal spacing even with longer right side when using =', 21, - 'a%=test%=longtext', 'a~~~~test~~~~longtext') - statusline_test_align('should handle an empty left side when using ==', 21, - '%=test%=baz', '~~~~~~~test~~~~~~~baz') - statusline_test_align('should handle an empty right side when using ==', 21, - 'foobar%=test%=', 'foobar~~~~~test~~~~~~') - - statusline_test_align('should quadrant the text when using 3 %=', 40, - 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef') - statusline_test_align('should work well with %t', 40, - '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned', - {file_name='test/unit/buffer_spec.lua'}) - statusline_test_align('should work well with %t and regular text', 40, - 'l%=m_l %t m_r%=r', 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r', - {file_name='test/unit/buffer_spec.lua'}) - statusline_test_align('should work well with %=, %t, %L, and %l', 40, - '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0', - {file_name='test/unit/buffer_spec.lua'}) - - statusline_test_align('should quadrant the text when using 3 %=', 41, - 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef') - statusline_test_align('should work well with %t', 41, - '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned', - {file_name='test/unit/buffer_spec.lua'}) - statusline_test_align('should work well with %t and regular text', 41, - 'l%=m_l %t m_r%=r', 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r', - {file_name='test/unit/buffer_spec.lua'}) - statusline_test_align('should work well with %=, %t, %L, and %l', 41, - '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0', - {file_name='test/unit/buffer_spec.lua'}) - - statusline_test_align('should work with 10 %=', 50, - 'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz', - 'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz') - - -- stl item testing - local tabline = '' - for i= 1, 1000 do - tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2) - end - statusline_test('should handle a large amount of any items', 20, - tabline, - '<1010101010101010101') -- Should not show any error - statusline_test('should handle a larger amount of = than stl initial item', 20, - ('%='):rep(STL_INITIAL_ITEMS * 5), - ' ') -- Should not show any error - statusline_test('should handle many extra characters', 20, - 'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5), - '<aaaaaaaaaaaaaaaaaaa') -- Does not show any error - statusline_test('should handle many extra characters and flags', 20, - 'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2), - 'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error - - - -- multi-byte testing - statusline_test('should handle multibyte characters', 10, - 'Ĉ%=x', 'Ĉ x') - statusline_test('should handle multibyte characters and different fillchars', 10, - 'Ą%=mid%=end', 'Ą@mid@@end', - {fillchar=('@'):byte()}) - - -- escaping % testing - statusline_test('should handle escape of %', 4, 'abc%%', 'abc%') - statusline_test('case where escaped % does not fit', 3, 'abc%%abcabc', '<bc') - statusline_test('escaped % is first', 1, '%%', '%') - - end) end) diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua index caf330c378..fc40fa39d4 100644 --- a/test/unit/charset/vim_str2nr_spec.lua +++ b/test/unit/charset/vim_str2nr_spec.lua @@ -63,7 +63,7 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict) cv[k] = args[k] end end - lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict) + lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict, nil) for cck, ccv in pairs(cv) do if exp[cck] ~= tonumber(ccv[0]) then error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format( diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua index b600f01ab2..883f01bd84 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/helpers.lua @@ -349,7 +349,7 @@ local special_vals = nil lua2typvalt = function(l, processed) if not special_vals then special_vals = { - [null_string] = {'VAR_STRING', {v_string=ffi.cast('char_u*', nil)}}, + [null_string] = {'VAR_STRING', {v_string=ffi.cast('char*', nil)}}, [null_list] = {'VAR_LIST', {v_list=ffi.cast('list_T*', nil)}}, [null_dict] = {'VAR_DICT', {v_dict=ffi.cast('dict_T*', nil)}}, [nil_value] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarNull}}, @@ -512,7 +512,8 @@ end local function eval0(expr) local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}), eval.tv_clear) - if eval.eval0(to_cstr(expr), tv, nil, true) == 0 then + local evalarg = ffi.new('evalarg_T', {eval_flags = eval.EVAL_EVALUATE}) + if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then return nil else return tv diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index 825377813d..34a1299725 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -43,7 +43,7 @@ local dict_watchers = eval_helpers.dict_watchers local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/memory.h', './src/nvim/mbyte.h', './src/nvim/garray.h', - './src/nvim/eval.h', './src/nvim/vim.h', + './src/nvim/eval.h', './src/nvim/vim_defs.h', './src/nvim/globals.h') local function vimconv_alloc() @@ -101,12 +101,13 @@ local function check_emsg(f, msg) saved_last_msg_hist = nil end local ret = {f()} + local last_msg = lib.last_msg_hist ~= nil and ffi.string(lib.last_msg_hist.msg) or nil if msg ~= nil then - eq(msg, ffi.string(lib.last_msg_hist.msg)) + eq(msg, last_msg) neq(saved_last_msg_hist, lib.last_msg_hist) else if saved_last_msg_hist ~= lib.last_msg_hist then - eq(nil, ffi.string(lib.last_msg_hist.msg)) + eq(nil, last_msg) else eq(saved_last_msg_hist, lib.last_msg_hist) end @@ -1429,15 +1430,16 @@ describe('typval.c', function() end describe('str()', function() itp('returns correct string', function() - local l = list(int(1), int(2), int(3), int(4), int(5)) + local l = list(int(1), 2.5, int(3), int(4), int(5)) alloc_log:clear() eq('1', tv_list_find_str(l, -5)) + eq('2.5', tv_list_find_str(l, 1)) eq('5', tv_list_find_str(l, 4)) eq('3', tv_list_find_str(l, 2)) eq('3', tv_list_find_str(l, -3)) - alloc_log:check({}) + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)}) end) itp('returns string when used with VAR_STRING items', function() local l = list('1', '2', '3', '4', '5') @@ -1461,18 +1463,16 @@ describe('typval.c', function() itp('fails with error message when index is out of range', function() local l = list(int(1), int(2), int(3), int(4), int(5)) - eq(nil, tv_list_find_str(l, -6, 'E684: list index out of range: -6')) - eq(nil, tv_list_find_str(l, 5, 'E684: list index out of range: 5')) + eq(nil, tv_list_find_str(l, -6, 'E684: List index out of range: -6')) + eq(nil, tv_list_find_str(l, 5, 'E684: List index out of range: 5')) end) itp('fails with error message on invalid types', function() - local l = list(1, empty_list, {}) + local l = list(empty_list, {}) - eq('', tv_list_find_str(l, 0, 'E806: using Float as a String')) - eq('', tv_list_find_str(l, 1, 'E730: using List as a String')) - eq('', tv_list_find_str(l, 2, 'E731: using Dictionary as a String')) - eq('', tv_list_find_str(l, -1, 'E731: using Dictionary as a String')) - eq('', tv_list_find_str(l, -2, 'E730: using List as a String')) - eq('', tv_list_find_str(l, -3, 'E806: using Float as a String')) + eq('', tv_list_find_str(l, 0, 'E730: Using a List as a String')) + eq('', tv_list_find_str(l, 1, 'E731: Using a Dictionary as a String')) + eq('', tv_list_find_str(l, -1, 'E731: Using a Dictionary as a String')) + eq('', tv_list_find_str(l, -2, 'E730: Using a List as a String')) end) end) end) @@ -1653,7 +1653,7 @@ describe('typval.c', function() eq(OK, lib.tv_dict_add(d, di)) alloc_log:check({}) eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key ""')) alloc_log:clear() lib.tv_dict_item_remove(d, di) alloc_log:check({ @@ -1745,7 +1745,7 @@ describe('typval.c', function() itp('works', function() local d = ffi.gc(dict({test={}}), nil) eq('', ffi.string(check_emsg(function() return lib.tv_dict_get_string(d, 'test', false) end, - 'E731: using Dictionary as a String'))) + 'E731: Using a Dictionary as a String'))) d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil) alloc_log:clear() local dis = dict_items(d) @@ -1765,18 +1765,24 @@ describe('typval.c', function() neq(s42, s43) eq(s43, dis.te.di_tv.vval.v_string) alloc_log:check({}) - eq('', ffi.string(check_emsg(function() return lib.tv_dict_get_string(d, 't', false) end, - 'E806: using Float as a String'))) + local s44 = check_emsg(function() return lib.tv_dict_get_string(d, 't', false) end, + nil) + eq('44.0', ffi.string(s44)) + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)}) end) itp('allocates a string copy when requested', function() - local function tv_dict_get_string_alloc(d, key, emsg) + local function tv_dict_get_string_alloc(d, key, emsg, is_float) alloc_log:clear() local ret = check_emsg(function() return lib.tv_dict_get_string(d, key, true) end, emsg) local s_ret = (ret ~= nil) and ffi.string(ret) or nil if not emsg then if s_ret then - alloc_log:check({a.str(ret, s_ret)}) + if is_float then + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null), a.str(ret, s_ret)}) + else + alloc_log:check({a.str(ret, s_ret)}) + end else alloc_log:check({}) end @@ -1785,25 +1791,29 @@ describe('typval.c', function() return s_ret end local d = ffi.gc(dict({test={}}), nil) - eq('', tv_dict_get_string_alloc(d, 'test', 'E731: using Dictionary as a String')) + eq('', tv_dict_get_string_alloc(d, 'test', 'E731: Using a Dictionary as a String')) d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil) alloc_log:clear() eq(nil, tv_dict_get_string_alloc(d, 'test')) eq('42', tv_dict_get_string_alloc(d, 'tes')) eq('45', tv_dict_get_string_alloc(d, 'xx')) eq('43', tv_dict_get_string_alloc(d, 'te')) - eq('', tv_dict_get_string_alloc(d, 't', 'E806: using Float as a String')) + eq('44.0', tv_dict_get_string_alloc(d, 't', nil, true)) end) end) describe('get_string_buf()', function() - local function tv_dict_get_string_buf(d, key, buf, emsg) + local function tv_dict_get_string_buf(d, key, is_float, buf, emsg) buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree) alloc_log:clear() local ret = check_emsg(function() return lib.tv_dict_get_string_buf(d, key, buf) end, emsg) local s_ret = (ret ~= nil) and ffi.string(ret) or nil if not emsg then - alloc_log:check({}) + if is_float then + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)}) + else + alloc_log:check({}) + end end return s_ret, ret, buf end @@ -1827,16 +1837,16 @@ describe('typval.c', function() s, r, b = tv_dict_get_string_buf(d, 'test') neq(r, b) eq('tset', s) - s, r, b = tv_dict_get_string_buf(d, 't', nil, 'E806: using Float as a String') - neq(r, b) - eq('', s) + s, r, b = tv_dict_get_string_buf(d, 't', true) + eq(r, b) + eq('1.0', s) s, r, b = tv_dict_get_string_buf(d, 'te') eq(r, b) eq('2', s) end) end) describe('get_string_buf_chk()', function() - local function tv_dict_get_string_buf_chk(d, key, len, buf, def, emsg) + local function tv_dict_get_string_buf_chk(d, key, is_float, len, buf, def, emsg) buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree) def = def or ffi.gc(lib.xstrdup('DEFAULT'), lib.xfree) len = len or #key @@ -1845,7 +1855,11 @@ describe('typval.c', function() emsg) local s_ret = (ret ~= nil) and ffi.string(ret) or nil if not emsg then - alloc_log:check({}) + if is_float then + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)}) + else + alloc_log:check({}) + end end return s_ret, ret, buf, def end @@ -1870,10 +1884,10 @@ describe('typval.c', function() neq(r, b) neq(r, def) eq('tset', s) - s, r, b, def = tv_dict_get_string_buf_chk(d, 'test', 1, nil, nil, 'E806: using Float as a String') - neq(r, b) + s, r, b, def = tv_dict_get_string_buf_chk(d, 'test', true, 1) + eq(r, b) neq(r, def) - eq(nil, s) + eq('1.0', s) s, r, b, def = tv_dict_get_string_buf_chk(d, 'te') eq(r, b) neq(r, def) @@ -1947,7 +1961,7 @@ describe('typval.c', function() alloc_log:check({}) eq({test=10, ['t-est']=int(42)}, dct2tbl(d)) eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "t-est"')) end) end) describe('list()', function() @@ -1964,7 +1978,7 @@ describe('typval.c', function() eq({test=10, tes={1, 2, 3}}, dct2tbl(d)) eq(2, l.lv_refcount) eq(FAIL, check_emsg(function() return lib.tv_dict_add_list(d, 'testt', 3, l) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) eq(2, l.lv_refcount) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 @@ -1990,7 +2004,7 @@ describe('typval.c', function() eq({test=10, tes={foo=42}}, dct2tbl(d)) eq(2, d2.dv_refcount) eq(FAIL, check_emsg(function() return lib.tv_dict_add_dict(d, 'testt', 3, d2) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) eq(2, d2.dv_refcount) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 @@ -2012,7 +2026,7 @@ describe('typval.c', function() alloc_log:check({a.di(dis.tes, 'tes')}) eq({test=10, tes=int(2)}, dct2tbl(d)) eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end, @@ -2032,7 +2046,7 @@ describe('typval.c', function() alloc_log:check({a.di(dis.tes, 'tes')}) eq({test=10, tes=1.5}, dct2tbl(d)) eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end, @@ -2055,7 +2069,7 @@ describe('typval.c', function() }) eq({test=10, tes='TEST'}, dct2tbl(d)) eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end, @@ -2085,7 +2099,7 @@ describe('typval.c', function() }) eq({test=10, tes='TEST'}, dct2tbl(d)) eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s2) end, - 'E685: Internal error: hash_add()')) + 'E685: Internal error: hash_add(): duplicate key "tes"')) alloc_log:clear() lib.emsg_skip = lib.emsg_skip + 1 eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s3) end, @@ -2831,14 +2845,14 @@ describe('typval.c', function() alloc_log:clear() for _, v in ipairs({ {lib.VAR_NUMBER, nil}, - {lib.VAR_FLOAT, 'E806: using Float as a String'}, - {lib.VAR_PARTIAL, 'E729: using Funcref as a String'}, - {lib.VAR_FUNC, 'E729: using Funcref as a String'}, - {lib.VAR_LIST, 'E730: using List as a String'}, - {lib.VAR_DICT, 'E731: using Dictionary as a String'}, + {lib.VAR_FLOAT, nil}, + {lib.VAR_PARTIAL, 'E729: Using a Funcref as a String'}, + {lib.VAR_FUNC, 'E729: Using a Funcref as a String'}, + {lib.VAR_LIST, 'E730: Using a List as a String'}, + {lib.VAR_DICT, 'E731: Using a Dictionary as a String'}, {lib.VAR_BOOL, nil}, {lib.VAR_SPECIAL, nil}, - {lib.VAR_UNKNOWN, 'E908: using an invalid value as a String'}, + {lib.VAR_UNKNOWN, 'E908: Using an invalid value as a String'}, }) do local typ = v[1] local emsg = v[2] @@ -2978,179 +2992,118 @@ describe('typval.c', function() end end) end) + + local function test_string_fn(input, fn) + for _, v in ipairs(input) do + -- Using to_cstr in place of Neovim allocated string, cannot + -- tv_clear() that. + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() + local res, buf = fn(tv) + if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_FLOAT + or tv.v_type == lib.VAR_SPECIAL or tv.v_type == lib.VAR_BOOL then + eq(buf, res) + else + neq(buf, res) + end + if res ~= nil then + return ffi.string(res) + else + return nil + end + end, emsg)) + if emsg then + alloc_log:clear() + elseif tv.v_type == lib.VAR_FLOAT then + alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)}) + else + alloc_log:check({}) + end + end + end describe('string()', function() itp('works', function() local buf = lib.tv_get_string(lua2typvalt(int(1))) local buf_chk = lib.tv_get_string_chk(lua2typvalt(int(1))) neq(buf, buf_chk) - for _, v in ipairs({ + test_string_fn({ {lib.VAR_NUMBER, {v_number=42}, nil, '42'}, {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'}, - {lib.VAR_FLOAT, {v_float=42.53}, 'E806: using Float as a String', ''}, - {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: using Funcref as a String', ''}, - {lib.VAR_FUNC, {v_string=NULL}, 'E729 |