aboutsummaryrefslogtreecommitdiff
path: root/test/unit
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/buffer_spec.lua276
-rw-r--r--test/unit/charset/vim_str2nr_spec.lua2
-rw-r--r--test/unit/eval/helpers.lua5
-rw-r--r--test/unit/eval/typval_spec.lua318
-rw-r--r--test/unit/fixtures/multiqueue.c11
-rw-r--r--test/unit/fixtures/rbuffer.c5
-rw-r--r--test/unit/formatc.lua2
-rw-r--r--test/unit/helpers.lua344
-rw-r--r--test/unit/keycodes_spec.lua22
-rw-r--r--test/unit/marktree_spec.lua339
-rw-r--r--test/unit/mbyte_spec.lua243
-rw-r--r--test/unit/message_spec.lua4
-rw-r--r--test/unit/msgpack_spec.lua75
-rw-r--r--test/unit/optionstr_spec.lua4
-rw-r--r--test/unit/os/env_spec.lua2
-rw-r--r--test/unit/os/fileio_spec.lua69
-rw-r--r--test/unit/os/fs_spec.lua128
-rw-r--r--test/unit/os/shell_spec.lua2
-rw-r--r--test/unit/path_spec.lua81
-rw-r--r--test/unit/preload.lua1
-rw-r--r--test/unit/preprocess.lua178
-rw-r--r--test/unit/set.lua47
-rw-r--r--test/unit/statusline_spec.lua282
-rw-r--r--test/unit/strings_spec.lua93
-rw-r--r--test/unit/tempfile_spec.lua3
-rw-r--r--test/unit/tui_spec.lua162
-rw-r--r--test/unit/undo_spec.lua32
27 files changed, 1486 insertions, 1244 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 128625374e..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({
@@ -1677,7 +1677,7 @@ describe('typval.c', function()
eq(nil, lib.tv_dict_find(nil, 'test', -1))
eq(nil, lib.tv_dict_find(nil, nil, 0))
end)
- itp('works with NULL key', function()
+ itp('works with empty key', function()
local lua_d = {
['']=0,
t=1,
@@ -1692,7 +1692,6 @@ describe('typval.c', function()
alloc_log:check({})
local dis = dict_items(d)
eq({0, '', dis['']}, {tv_dict_find(d, '', 0)})
- eq({0, '', dis['']}, {tv_dict_find(d, nil, 0)})
end)
itp('works with len properly', function()
local lua_d = {
@@ -1746,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)
@@ -1766,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
@@ -1786,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
@@ -1828,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
@@ -1846,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
@@ -1871,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)
@@ -1911,8 +1924,6 @@ describe('typval.c', function()
local d = dict(lua_d)
eq(lua_d, dct2tbl(d))
eq({{type='fref', fref='tr'}, true},
- {tv_dict_get_callback(d, nil, 0)})
- eq({{type='fref', fref='tr'}, true},
{tv_dict_get_callback(d, '', -1)})
eq({{type='none'}, true},
{tv_dict_get_callback(d, 'x', -1)})
@@ -1950,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()
@@ -1967,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
@@ -1993,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
@@ -2015,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,
@@ -2035,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,
@@ -2058,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,
@@ -2088,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,
@@ -2834,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]
@@ -2981,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: using Funcref as a String', ''},
- {lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', ''},
- {lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', ''},
+ {lib.VAR_FLOAT, {v_float=42.53}, nil, '42.53'},
+ {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: Using a Funcref as a String', ''},
+ {lib.VAR_FUNC, {v_string=NULL}, 'E729: Using a Funcref as a String', ''},
+ {lib.VAR_LIST, {v_list=NULL}, 'E730: Using a List as a String', ''},
+ {lib.VAR_DICT, {v_dict=NULL}, 'E731: Using a Dictionar