diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/lua/iter_spec.lua | 425 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 421 | ||||
-rw-r--r-- | test/functional/vimscript/eval_spec.lua | 31 | ||||
-rw-r--r-- | test/old/testdir/test_assert.vim | 10 | ||||
-rw-r--r-- | test/old/testdir/test_charsearch.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_cmdline.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_expr.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_functions.vim | 476 | ||||
-rw-r--r-- | test/old/testdir/test_listdict.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_maparg.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_matchfuzzy.vim | 8 | ||||
-rw-r--r-- | test/old/testdir/test_partial.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_search_stat.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_signs.vim | 14 | ||||
-rw-r--r-- | test/old/testdir/test_tagjump.vim | 8 | ||||
-rw-r--r-- | test/old/testdir/test_timers.vim | 12 | ||||
-rw-r--r-- | test/old/testdir/test_window_cmd.vim | 6 |
17 files changed, 951 insertions, 474 deletions
diff --git a/test/functional/lua/iter_spec.lua b/test/functional/lua/iter_spec.lua new file mode 100644 index 0000000000..6e1ecc2f7e --- /dev/null +++ b/test/functional/lua/iter_spec.lua @@ -0,0 +1,425 @@ +local helpers = require('test.functional.helpers')(after_each) +local eq = helpers.eq +local matches = helpers.matches +local pcall_err = helpers.pcall_err + +describe('vim.iter', function() + it('filter()', function() + local function odd(v) + return v % 2 ~= 0 + end + + local t = { 1, 2, 3, 4, 5 } + eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable()) + eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable()) + eq({}, vim.iter(t):filter(function(v) return v > 5 end):totable()) + + do + local it = vim.iter(ipairs(t)) + it:filter(function(i, v) return i > 1 and v < 5 end) + it:map(function(_, v) return v * 2 end) + eq({ 4, 6, 8 }, it:totable()) + end + + local it = vim.iter(string.gmatch('the quick brown fox', '%w+')) + eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable()) + end) + + it('map()', function() + local t = { 1, 2, 3, 4, 5 } + eq( + { 2, 4, 6, 8, 10 }, + vim + .iter(t) + :map(function(v) + return 2 * v + end) + :totable() + ) + + local it = vim.gsplit( + [[ + Line 1 + Line 2 + Line 3 + Line 4 + ]], + '\n' + ) + + eq( + { 'Lion 2', 'Lion 4' }, + vim + .iter(it) + :map(function(s) + local lnum = s:match('(%d+)') + if lnum and tonumber(lnum) % 2 == 0 then + return vim.trim(s:gsub('Line', 'Lion')) + end + end) + :totable() + ) + end) + + it('for loops', function() + local t = {1, 2, 3, 4, 5} + local acc = 0 + for v in vim.iter(t):map(function(v) return v * 3 end) do + acc = acc + v + end + eq(45, acc) + end) + + it('totable()', function() + do + local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end) + eq({{1, 1}, {2, 4}, {3, 9}}, it:totable()) + end + + do + local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber) + eq({1, 4, 17, 2, 9, 3}, it:totable()) + end + end) + + it('next()', function() + local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end) + eq(2, it:next()) + eq(4, it:next()) + eq(6, it:next()) + eq(nil, it:next()) + end) + + it('rev()', function() + eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable()) + + local it = vim.iter(string.gmatch("abc", "%w")) + matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it)) + end) + + it('skip()', function() + do + local t = {4, 3, 2, 1} + eq(t, vim.iter(t):skip(0):totable()) + eq({3, 2, 1}, vim.iter(t):skip(1):totable()) + eq({2, 1}, vim.iter(t):skip(2):totable()) + eq({1}, vim.iter(t):skip(#t - 1):totable()) + eq({}, vim.iter(t):skip(#t):totable()) + eq({}, vim.iter(t):skip(#t + 1):totable()) + end + + do + local function skip(n) + return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable() + end + eq({'a', 'b', 'c', 'd'}, skip(0)) + eq({'b', 'c', 'd'}, skip(1)) + eq({'c', 'd'}, skip(2)) + eq({'d'}, skip(3)) + eq({}, skip(4)) + eq({}, skip(5)) + end + end) + + it('skipback()', function() + do + local t = {4, 3, 2, 1} + eq(t, vim.iter(t):skipback(0):totable()) + eq({4, 3, 2}, vim.iter(t):skipback(1):totable()) + eq({4, 3}, vim.iter(t):skipback(2):totable()) + eq({4}, vim.iter(t):skipback(#t - 1):totable()) + eq({}, vim.iter(t):skipback(#t):totable()) + eq({}, vim.iter(t):skipback(#t + 1):totable()) + end + + local it = vim.iter(vim.gsplit('a|b|c|d', '|')) + matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0)) + end) + + it('slice()', function() + local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable()) + eq({}, vim.iter(t):slice(6, 5):totable()) + eq({}, vim.iter(t):slice(0, 0):totable()) + eq({1}, vim.iter(t):slice(1, 1):totable()) + eq({1, 2}, vim.iter(t):slice(1, 2):totable()) + eq({10}, vim.iter(t):slice(10, 10):totable()) + eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable()) + end) + + it('nth()', function() + do + local t = {4, 3, 2, 1} + eq(nil, vim.iter(t):nth(0)) + eq(4, vim.iter(t):nth(1)) + eq(3, vim.iter(t):nth(2)) + eq(2, vim.iter(t):nth(3)) + eq(1, vim.iter(t):nth(4)) + eq(nil, vim.iter(t):nth(5)) + end + + do + local function nth(n) + return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n) + end + eq(nil, nth(0)) + eq('a', nth(1)) + eq('b', nth(2)) + eq('c', nth(3)) + eq('d', nth(4)) + eq(nil, nth(5)) + end + end) + + it('nthback()', function() + do + local t = {4, 3, 2, 1} + eq(nil, vim.iter(t):nthback(0)) + eq(1, vim.iter(t):nthback(1)) + eq(2, vim.iter(t):nthback(2)) + eq(3, vim.iter(t):nthback(3)) + eq(4, vim.iter(t):nthback(4)) + eq(nil, vim.iter(t):nthback(5)) + end + + local it = vim.iter(vim.gsplit('a|b|c|d', '|')) + matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1)) + end) + + it('any()', function() + local function odd(v) + return v % 2 ~= 0 + end + + do + local t = { 4, 8, 9, 10 } + eq(true, vim.iter(t):any(odd)) + end + + do + local t = { 4, 8, 10 } + eq(false, vim.iter(t):any(odd)) + end + + do + eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end)) + eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end)) + end + end) + + it('all()', function() + local function odd(v) + return v % 2 ~= 0 + end + + do + local t = { 3, 5, 7, 9 } + eq(true, vim.iter(t):all(odd)) + end + + do + local t = { 3, 5, 7, 10 } + eq(false, vim.iter(t):all(odd)) + end + + do + eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end)) + eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end)) + end + end) + + it('last()', function() + local s = 'abcdefghijklmnopqrstuvwxyz' + eq('z', vim.iter(vim.split(s, '')):last()) + eq('z', vim.iter(vim.gsplit(s, '')):last()) + end) + + it('enumerate()', function() + local it = vim.iter(vim.gsplit('abc', '')):enumerate() + eq({1, 'a'}, {it:next()}) + eq({2, 'b'}, {it:next()}) + eq({3, 'c'}, {it:next()}) + eq({}, {it:next()}) + end) + + it('peek()', function() + do + local it = vim.iter({ 3, 6, 9, 12 }) + eq(3, it:peek()) + eq(3, it:peek()) + eq(3, it:next()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it)) + end + end) + + it('find()', function() + local t = {3, 6, 9, 12} + eq(12, vim.iter(t):find(12)) + eq(nil, vim.iter(t):find(15)) + eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end)) + + do + local it = vim.iter(t) + local pred = function(v) return v % 3 == 0 end + eq(3, it:find(pred)) + eq(6, it:find(pred)) + eq(9, it:find(pred)) + eq(12, it:find(pred)) + eq(nil, it:find(pred)) + end + + do + local it = vim.iter(vim.gsplit('AbCdE', '')) + local pred = function(s) return s:match('[A-Z]') end + eq('A', it:find(pred)) + eq('C', it:find(pred)) + eq('E', it:find(pred)) + eq(nil, it:find(pred)) + end + end) + + it('rfind()', function() + local t = {1, 2, 3, 2, 1} + do + local it = vim.iter(t) + eq(1, it:rfind(1)) + eq(1, it:rfind(1)) + eq(nil, it:rfind(1)) + end + + do + local it = vim.iter(t):enumerate() + local pred = function(i) return i % 2 ~= 0 end + eq({5, 1}, {it:rfind(pred)}) + eq({3, 3}, {it:rfind(pred)}) + eq({1, 1}, {it:rfind(pred)}) + eq(nil, it:rfind(pred)) + end + + do + local it = vim.iter(vim.gsplit('AbCdE', '')) + matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E')) + end + end) + + it('nextback()', function() + do + local it = vim.iter({ 1, 2, 3, 4 }) + eq(4, it:nextback()) + eq(3, it:nextback()) + eq(2, it:nextback()) + eq(1, it:nextback()) + eq(nil, it:nextback()) + eq(nil, it:nextback()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it)) + end + end) + + it('peekback()', function() + do + local it = vim.iter({ 1, 2, 3, 4 }) + eq(4, it:peekback()) + eq(4, it:peekback()) + eq(4, it:nextback()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it)) + end + end) + + it('fold()', function() + local t = {1, 2, 3, 4, 5} + eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end)) + eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v) + table.insert(acc, 1, v) + return acc + end)) + end) + + it('handles map-like tables', function() + local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v) + if v % 2 ~= 0 then + return k:upper(), v * 2 + end + end) + + local t = it:fold({}, function(t, k, v) + t[k] = v + return t + end) + eq({ A = 2, C = 6 }, t) + end) + + it('handles table values mid-pipeline', function() + local map = { + item = { + file = 'test', + }, + item_2 = { + file = 'test', + }, + item_3 = { + file = 'test', + }, + } + + local output = vim.iter(map):map(function(key, value) + return { [key] = value.file } + end):totable() + + table.sort(output, function(a, b) + return next(a) < next(b) + end) + + eq({ + { item = 'test' }, + { item_2 = 'test' }, + { item_3 = 'test' }, + }, output) + end) + + it('handles nil values', function() + local t = {1, 2, 3, 4, 5} + do + local it = vim.iter(t):enumerate():map(function(i, v) + if i % 2 == 0 then + return nil, v*v + end + return v, nil + end) + eq({ + { [1] = 1 }, + { [2] = 4 }, + { [1] = 3 }, + { [2] = 16 }, + { [1] = 5 }, + }, it:totable()) + end + + do + local it = vim.iter(ipairs(t)):map(function(i, v) + if i % 2 == 0 then + return nil, v*v + end + return v, nil + end) + eq({ + { [1] = 1 }, + { [2] = 4 }, + { [1] = 3 }, + { [2] = 16 }, + { [1] = 5 }, + }, it:totable()) + end + end) +end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 42927f7e1b..53c21fd668 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3031,427 +3031,6 @@ describe('lua stdlib', function() eq(false, if_nil(d, c)) eq(NIL, if_nil(a)) end) - - describe('vim.iter', function() - it('filter()', function() - local function odd(v) - return v % 2 ~= 0 - end - - local t = { 1, 2, 3, 4, 5 } - eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable()) - eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable()) - eq({}, vim.iter(t):filter(function(v) if v > 5 then return v end end):totable()) - - do - local it = vim.iter(ipairs(t)) - it:filter(function(i, v) return i > 1 and v < 5 end) - it:map(function(_, v) return v * 2 end) - eq({ 4, 6, 8 }, it:totable()) - end - - local it = vim.iter(string.gmatch('the quick brown fox', '%w+')) - eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable()) - end) - - it('map()', function() - local t = { 1, 2, 3, 4, 5 } - eq( - { 2, 4, 6, 8, 10 }, - vim - .iter(t) - :map(function(v) - return 2 * v - end) - :totable() - ) - - local it = vim.gsplit( - [[ - Line 1 - Line 2 - Line 3 - Line 4 - ]], - '\n' - ) - - eq( - { 'Lion 2', 'Lion 4' }, - vim - .iter(it) - :map(function(s) - local lnum = s:match('(%d+)') - if lnum and tonumber(lnum) % 2 == 0 then - return vim.trim(s:gsub('Line', 'Lion')) - end - end) - :totable() - ) - end) - - it('for loops', function() - local t = {1, 2, 3, 4, 5} - local acc = 0 - for v in vim.iter(t):map(function(v) return v * 3 end) do - acc = acc + v - end - eq(45, acc) - end) - - it('totable()', function() - do - local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end) - eq({{1, 1}, {2, 4}, {3, 9}}, it:totable()) - end - - do - local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber) - eq({1, 4, 17, 2, 9, 3}, it:totable()) - end - end) - - it('next()', function() - local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end) - eq(2, it:next()) - eq(4, it:next()) - eq(6, it:next()) - eq(nil, it:next()) - end) - - it('rev()', function() - eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable()) - - local it = vim.iter(string.gmatch("abc", "%w")) - matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it)) - end) - - it('skip()', function() - do - local t = {4, 3, 2, 1} - eq(t, vim.iter(t):skip(0):totable()) - eq({3, 2, 1}, vim.iter(t):skip(1):totable()) - eq({2, 1}, vim.iter(t):skip(2):totable()) - eq({1}, vim.iter(t):skip(#t - 1):totable()) - eq({}, vim.iter(t):skip(#t):totable()) - eq({}, vim.iter(t):skip(#t + 1):totable()) - end - - do - local function skip(n) - return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable() - end - eq({'a', 'b', 'c', 'd'}, skip(0)) - eq({'b', 'c', 'd'}, skip(1)) - eq({'c', 'd'}, skip(2)) - eq({'d'}, skip(3)) - eq({}, skip(4)) - eq({}, skip(5)) - end - end) - - it('skipback()', function() - do - local t = {4, 3, 2, 1} - eq(t, vim.iter(t):skipback(0):totable()) - eq({4, 3, 2}, vim.iter(t):skipback(1):totable()) - eq({4, 3}, vim.iter(t):skipback(2):totable()) - eq({4}, vim.iter(t):skipback(#t - 1):totable()) - eq({}, vim.iter(t):skipback(#t):totable()) - eq({}, vim.iter(t):skipback(#t + 1):totable()) - end - - local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0)) - end) - - it('slice()', function() - local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable()) - eq({}, vim.iter(t):slice(6, 5):totable()) - eq({}, vim.iter(t):slice(0, 0):totable()) - eq({1}, vim.iter(t):slice(1, 1):totable()) - eq({1, 2}, vim.iter(t):slice(1, 2):totable()) - eq({10}, vim.iter(t):slice(10, 10):totable()) - eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable()) - end) - - it('nth()', function() - do - local t = {4, 3, 2, 1} - eq(nil, vim.iter(t):nth(0)) - eq(4, vim.iter(t):nth(1)) - eq(3, vim.iter(t):nth(2)) - eq(2, vim.iter(t):nth(3)) - eq(1, vim.iter(t):nth(4)) - eq(nil, vim.iter(t):nth(5)) - end - - do - local function nth(n) - return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n) - end - eq(nil, nth(0)) - eq('a', nth(1)) - eq('b', nth(2)) - eq('c', nth(3)) - eq('d', nth(4)) - eq(nil, nth(5)) - end - end) - - it('nthback()', function() - do - local t = {4, 3, 2, 1} - eq(nil, vim.iter(t):nthback(0)) - eq(1, vim.iter(t):nthback(1)) - eq(2, vim.iter(t):nthback(2)) - eq(3, vim.iter(t):nthback(3)) - eq(4, vim.iter(t):nthback(4)) - eq(nil, vim.iter(t):nthback(5)) - end - - local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1)) - end) - - it('any()', function() - local function odd(v) - return v % 2 ~= 0 - end - - do - local t = { 4, 8, 9, 10 } - eq(true, vim.iter(t):any(odd)) - end - - do - local t = { 4, 8, 10 } - eq(false, vim.iter(t):any(odd)) - end - - do - eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end)) - eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end)) - end - end) - - it('all()', function() - local function odd(v) - return v % 2 ~= 0 - end - - do - local t = { 3, 5, 7, 9 } - eq(true, vim.iter(t):all(odd)) - end - - do - local t = { 3, 5, 7, 10 } - eq(false, vim.iter(t):all(odd)) - end - - do - eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end)) - eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end)) - end - end) - - it('last()', function() - local s = 'abcdefghijklmnopqrstuvwxyz' - eq('z', vim.iter(vim.split(s, '')):last()) - eq('z', vim.iter(vim.gsplit(s, '')):last()) - end) - - it('enumerate()', function() - local it = vim.iter(vim.gsplit('abc', '')):enumerate() - eq({1, 'a'}, {it:next()}) - eq({2, 'b'}, {it:next()}) - eq({3, 'c'}, {it:next()}) - eq({}, {it:next()}) - end) - - it('peek()', function() - do - local it = vim.iter({ 3, 6, 9, 12 }) - eq(3, it:peek()) - eq(3, it:peek()) - eq(3, it:next()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it)) - end - end) - - it('find()', function() - local t = {3, 6, 9, 12} - eq(12, vim.iter(t):find(12)) - eq(nil, vim.iter(t):find(15)) - eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end)) - - do - local it = vim.iter(t) - local pred = function(v) return v % 3 == 0 end - eq(3, it:find(pred)) - eq(6, it:find(pred)) - eq(9, it:find(pred)) - eq(12, it:find(pred)) - eq(nil, it:find(pred)) - end - - do - local it = vim.iter(vim.gsplit('AbCdE', '')) - local pred = function(s) return s:match('[A-Z]') end - eq('A', it:find(pred)) - eq('C', it:find(pred)) - eq('E', it:find(pred)) - eq(nil, it:find(pred)) - end - end) - - it('rfind()', function() - local t = {1, 2, 3, 2, 1} - do - local it = vim.iter(t) - eq(1, it:rfind(1)) - eq(1, it:rfind(1)) - eq(nil, it:rfind(1)) - end - - do - local it = vim.iter(t):enumerate() - local pred = function(i) return i % 2 ~= 0 end - eq({5, 1}, {it:rfind(pred)}) - eq({3, 3}, {it:rfind(pred)}) - eq({1, 1}, {it:rfind(pred)}) - eq(nil, it:rfind(pred)) - end - - do - local it = vim.iter(vim.gsplit('AbCdE', '')) - matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E')) - end - end) - - it('nextback()', function() - do - local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:nextback()) - eq(3, it:nextback()) - eq(2, it:nextback()) - eq(1, it:nextback()) - eq(nil, it:nextback()) - eq(nil, it:nextback()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it)) - end - end) - - it('peekback()', function() - do - local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:peekback()) - eq(4, it:peekback()) - eq(4, it:peekback()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it)) - end - end) - - it('fold()', function() - local t = {1, 2, 3, 4, 5} - eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end)) - eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v) - table.insert(acc, 1, v) - return acc - end)) - end) - - it('handles map-like tables', function() - local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v) - if v % 2 ~= 0 then - return k:upper(), v * 2 - end - end) - - local t = it:fold({}, function(t, k, v) - t[k] = v - return t - end) - eq({ A = 2, C = 6 }, t) - end) - - it('handles table values mid-pipeline', function() - local map = { - item = { - file = 'test', - }, - item_2 = { - file = 'test', - }, - item_3 = { - file = 'test', - }, - } - - local output = vim.iter(map):map(function(key, value) - return { [key] = value.file } - end):totable() - - table.sort(output, function(a, b) - return next(a) < next(b) - end) - - eq({ - { item = 'test' }, - { item_2 = 'test' }, - { item_3 = 'test' }, - }, output) - end) - - it('handles nil values', function() - local t = {1, 2, 3, 4, 5} - do - local it = vim.iter(t):enumerate():map(function(i, v) - if i % 2 == 0 then - return nil, v*v - end - return v, nil - end) - eq({ - { [1] = 1 }, - { [2] = 4 }, - { [1] = 3 }, - { [2] = 16 }, - { [1] = 5 }, - }, it:totable()) - end - - do - local it = vim.iter(ipairs(t)):map(function(i, v) - if i % 2 == 0 then - return nil, v*v - end - return v, nil - end) - eq({ - { [1] = 1 }, - { [2] = 4 }, - { [1] = 3 }, - { [2] = 16 }, - { [1] = 5 }, - }, it:totable()) - end - end) - end) end) describe('lua: builtin modules', function() diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua index b411b1e379..b3f2c1bfeb 100644 --- a/test/functional/vimscript/eval_spec.lua +++ b/test/functional/vimscript/eval_spec.lua @@ -191,11 +191,10 @@ describe('listing functions using :function', function() endfunction]]):format(num), exec_capture(('function <lambda>%s'):format(num))) end) - -- FIXME: If the same function is deleted, the crash still happens. #20790 it('does not crash if another function is deleted while listing', function() local screen = Screen.new(80, 24) screen:attach() - matches('Vim%(function%):E454: function list was modified', pcall_err(exec_lua, [=[ + matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[ vim.cmd([[ func Func1() endfunc @@ -219,6 +218,34 @@ describe('listing functions using :function', function() ]=])) assert_alive() end) + + it('does not crash if the same function is deleted while listing', function() + local screen = Screen.new(80, 24) + screen:attach() + matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[ + vim.cmd([[ + func Func1() + endfunc + func Func2() + endfunc + func Func3() + endfunc + ]]) + + local ns = vim.api.nvim_create_namespace('test') + + vim.ui_attach(ns, { ext_messages = true }, function(event, _, content) + if event == 'msg_show' and content[1][2] == 'function Func1()' then + vim.cmd('delfunc Func2') + end + end) + + vim.cmd('function') + + vim.ui_detach(ns) + ]=])) + assert_alive() + end) end) it('no double-free in garbage collection #16287', function() diff --git a/test/old/testdir/test_assert.vim b/test/old/testdir/test_assert.vim index 431908e95c..4386492339 100644 --- a/test/old/testdir/test_assert.vim +++ b/test/old/testdir/test_assert.vim @@ -337,6 +337,16 @@ func Test_assert_with_msg() call remove(v:errors, 0) endfunc +func Test_override() + throw 'Skipped: Nvim does not support test_override()' + call test_override('char_avail', 1) + eval 1->test_override('redraw') + call test_override('ALL', 0) + call assert_fails("call test_override('xxx', 1)", 'E475:') + call assert_fails("call test_override('redraw', 'yes')", 'E474:') + call assert_fails("call test_override('redraw', 'yes')", 'E1210:') +endfunc + func Test_mouse_position() let save_mouse = &mouse set mouse=a diff --git a/test/old/testdir/test_charsearch.vim b/test/old/testdir/test_charsearch.vim index f8f3e958ca..8d6b405743 100644 --- a/test/old/testdir/test_charsearch.vim +++ b/test/old/testdir/test_charsearch.vim @@ -39,7 +39,7 @@ func Test_charsearch() call setcharsearch({'char' : ''}) call assert_equal('', getcharsearch().char) - call assert_fails("call setcharsearch([])", 'E715:') + call assert_fails("call setcharsearch([])", 'E1206:') enew! endfunc diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim index 9d506a66c0..9ed49b44c0 100644 --- a/test/old/testdir/test_cmdline.vim +++ b/test/old/testdir/test_cmdline.vim @@ -652,7 +652,7 @@ func Test_getcompletion() call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') call assert_fails('call getcompletion("", "burp")', 'E475:') - call assert_fails('call getcompletion("abc", [])', 'E475:') + call assert_fails('call getcompletion("abc", [])', 'E1174:') endfunc " Test for getcompletion() with "fuzzy" in 'wildoptions' diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim index dee7266bb5..ff3dfb83cb 100644 --- a/test/old/testdir/test_expr.vim +++ b/test/old/testdir/test_expr.vim @@ -105,7 +105,7 @@ func Test_dict() END call CheckLegacyAndVim9Success(lines) - call CheckLegacyAndVim9Failure(["VAR i = has_key([], 'a')"], ['E715:', 'E1013:', 'E1206:']) + call CheckLegacyAndVim9Failure(["VAR i = has_key([], 'a')"], ['E1206:', 'E1013:', 'E1206:']) endfunc func Test_strgetchar() diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 7d3d74caad..b934f7fac2 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -1064,19 +1064,14 @@ func Test_byte2line_line2byte() bw! endfunc -" Test for byteidx() and byteidxcomp() functions +" Test for byteidx() using a character index func Test_byteidx() let a = '.é.' " one char of two bytes call assert_equal(0, byteidx(a, 0)) - call assert_equal(0, byteidxcomp(a, 0)) call assert_equal(1, byteidx(a, 1)) - call assert_equal(1, byteidxcomp(a, 1)) call assert_equal(3, byteidx(a, 2)) - call assert_equal(3, byteidxcomp(a, 2)) call assert_equal(4, byteidx(a, 3)) - call assert_equal(4, byteidxcomp(a, 3)) call assert_equal(-1, byteidx(a, 4)) - call assert_equal(-1, byteidxcomp(a, 4)) let b = '.é.' " normal e with composing char call assert_equal(0, b->byteidx(0)) @@ -1084,18 +1079,184 @@ func Test_byteidx() call assert_equal(4, b->byteidx(2)) call assert_equal(5, b->byteidx(3)) call assert_equal(-1, b->byteidx(4)) + + " string with multiple composing characters + let str = '-ą́-ą́' + call assert_equal(0, byteidx(str, 0)) + call assert_equal(1, byteidx(str, 1)) + call assert_equal(6, byteidx(str, 2)) + call assert_equal(7, byteidx(str, 3)) + call assert_equal(12, byteidx(str, 4)) + call assert_equal(-1, byteidx(str, 5)) + + " empty string + call assert_equal(0, byteidx('', 0)) + call assert_equal(-1, byteidx('', 1)) + + " error cases call assert_fails("call byteidx([], 0)", 'E730:') + call assert_fails("call byteidx('abc', [])", 'E745:') +endfunc + +" Test for byteidxcomp() using a character index +func Test_byteidxcomp() + let a = '.é.' " one char of two bytes + call assert_equal(0, byteidxcomp(a, 0)) + call assert_equal(1, byteidxcomp(a, 1)) + call assert_equal(3, byteidxcomp(a, 2)) + call assert_equal(4, byteidxcomp(a, 3)) + call assert_equal(-1, byteidxcomp(a, 4)) + let b = '.é.' " normal e with composing char call assert_equal(0, b->byteidxcomp(0)) call assert_equal(1, b->byteidxcomp(1)) call assert_equal(2, b->byteidxcomp(2)) call assert_equal(4, b->byteidxcomp(3)) call assert_equal(5, b->byteidxcomp(4)) call assert_equal(-1, b->byteidxcomp(5)) + + " string with multiple composing characters + let str = '-ą́-ą́' + call assert_equal(0, byteidxcomp(str, 0)) + call assert_equal(1, byteidxcomp(str, 1)) + call assert_equal(2, byteidxcomp(str, 2)) + call assert_equal(4, byteidxcomp(str, 3)) + call assert_equal(6, byteidxcomp(str, 4)) + call assert_equal(7, byteidxcomp(str, 5)) + call assert_equal(8, byteidxcomp(str, 6)) + call assert_equal(10, byteidxcomp(str, 7)) + call assert_equal(12, byteidxcomp(str, 8)) + call assert_equal(-1, byteidxcomp(str, 9)) + + " empty string + call assert_equal(0, byteidxcomp('', 0)) + call assert_equal(-1, byteidxcomp('', 1)) + + " error cases call assert_fails("call byteidxcomp([], 0)", 'E730:') + call assert_fails("call byteidxcomp('abc', [])", 'E745:') endfunc -" Test for charidx() +" Test for byteidx() using a UTF-16 index +func Test_byteidx_from_utf16_index() + " string with single byte characters + let str = "abc" + for i in range(3) + call assert_equal(i, byteidx(str, i, v:true)) + endfor + call assert_equal(3, byteidx(str, 3, v:true)) + call assert_equal(-1, byteidx(str, 4, v:true)) + + " string with two byte characters + let str = "a©©b" + call assert_equal(0, byteidx(str, 0, v:true)) + call assert_equal(1, byteidx(str, 1, v:true)) + call assert_equal(3, byteidx(str, 2, v:true)) + call assert_equal(5, byteidx(str, 3, v:true)) + call assert_equal(6, byteidx(str, 4, v:true)) + call assert_equal(-1, byteidx(str, 5, v:true)) + + " string with two byte characters + let str = "a😊😊b" + call assert_equal(0, byteidx(str, 0, v:true)) + call assert_equal(1, byteidx(str, 1, v:true)) + call assert_equal(1, byteidx(str, 2, v:true)) + call assert_equal(5, byteidx(str, 3, v:true)) + call assert_equal(5, byteidx(str, 4, v:true)) + call assert_equal(9, byteidx(str, 5, v:true)) + call assert_equal(10, byteidx(str, 6, v:true)) + call assert_equal(-1, byteidx(str, 7, v:true)) + + " string with composing characters + let str = '-á-b́' + call assert_equal(0, byteidx(str, 0, v:true)) + call assert_equal(1, byteidx(str, 1, v:true)) + call assert_equal(4, byteidx(str, 2, v:true)) + call assert_equal(5, byteidx(str, 3, v:true)) + call assert_equal(8, byteidx(str, 4, v:true)) + call assert_equal(-1, byteidx(str, 5, v:true)) + + " string with multiple composing characters + let str = '-ą́-ą́' + call assert_equal(0, byteidx(str, 0, v:true)) + call assert_equal(1, byteidx(str, 1, v:true)) + call assert_equal(6, byteidx(str, 2, v:true)) + call assert_equal(7, byteidx(str, 3, v:true)) + call assert_equal(12, byteidx(str, 4, v:true)) + call assert_equal(-1, byteidx(str, 5, v:true)) + + " empty string + call assert_equal(0, byteidx('', 0, v:true)) + call assert_equal(-1, byteidx('', 1, v:true)) + + " error cases + call assert_fails('call byteidx(str, 0, [])', 'E745:') +endfunc + +" Test for byteidxcomp() using a UTF-16 index +func Test_byteidxcomp_from_utf16_index() + " string with single byte characters + let str = "abc" + for i in range(3) + call assert_equal(i, byteidxcomp(str, i, v:true)) + endfor + call assert_equal(3, byteidxcomp(str, 3, v:true)) + call assert_equal(-1, byteidxcomp(str, 4, v:true)) + + " string with two byte characters + let str = "a©©b" + call assert_equal(0, byteidxcomp(str, 0, v:true)) + call assert_equal(1, byteidxcomp(str, 1, v:true)) + call assert_equal(3, byteidxcomp(str, 2, v:true)) + call assert_equal(5, byteidxcomp(str, 3, v:true)) + call assert_equal(6, byteidxcomp(str, 4, v:true)) + call assert_equal(-1, byteidxcomp(str, 5, v:true)) + + " string with two byte characters + let str = "a😊😊b" + call assert_equal(0, byteidxcomp(str, 0, v:true)) + call assert_equal(1, byteidxcomp(str, 1, v:true)) + call assert_equal(1, byteidxcomp(str, 2, v:true)) + call assert_equal(5, byteidxcomp(str, 3, v:true)) + call assert_equal(5, byteidxcomp(str, 4, v:true)) + call assert_equal(9, byteidxcomp(str, 5, v:true)) + call assert_equal(10, byteidxcomp(str, 6, v:true)) + call assert_equal(-1, byteidxcomp(str, 7, v:true)) + + " string with composing characters + let str = '-á-b́' + call assert_equal(0, byteidxcomp(str, 0, v:true)) + call assert_equal(1, byteidxcomp(str, 1, v:true)) + call assert_equal(2, byteidxcomp(str, 2, v:true)) + call assert_equal(4, byteidxcomp(str, 3, v:true)) + call assert_equal(5, byteidxcomp(str, 4, v:true)) + call assert_equal(6, byteidxcomp(str, 5, v:true)) + call assert_equal(8, byteidxcomp(str, 6, v:true)) + call assert_equal(-1, byteidxcomp(str, 7, v:true)) + call assert_fails('call byteidxcomp(str, 0, [])', 'E745:') + + " string with multiple composing characters + let str = '-ą́-ą́' + call assert_equal(0, byteidxcomp(str, 0, v:true)) + call assert_equal(1, byteidxcomp(str, 1, v:true)) + call assert_equal(2, byteidxcomp(str, 2, v:true)) + call assert_equal(4, byteidxcomp(str, 3, v:true)) + call assert_equal(6, byteidxcomp(str, 4, v:true)) + call assert_equal(7, byteidxcomp(str, 5, v:true)) + call assert_equal(8, byteidxcomp(str, 6, v:true)) + call assert_equal(10, byteidxcomp(str, 7, v:true)) + call assert_equal(12, byteidxcomp(str, 8, v:true)) + call assert_equal(-1, byteidxcomp(str, 9, v:true)) + + " empty string + call assert_equal(0, byteidxcomp('', 0, v:true)) + call assert_equal(-1, byteidxcomp('', 1, v:true)) + + " error cases + call assert_fails('call byteidxcomp(str, 0, [])', 'E745:') +endfunc + +" Test for charidx() using a byte index func Test_charidx() let a = 'xáb́y' call assert_equal(0, charidx(a, 0)) @@ -1104,22 +1265,256 @@ func Test_charidx() call assert_equal(3, charidx(a, 7)) call assert_equal(-1, charidx(a, 8)) call assert_equal(-1, charidx(a, -1)) - call assert_equal(-1, charidx('', 0)) - call assert_equal(-1, charidx(v:_null_string, 0)) " count composing characters - call assert_equal(0, charidx(a, 0, 1)) - call assert_equal(2, charidx(a, 2, 1)) - call assert_equal(3, charidx(a, 4, 1)) - call assert_equal(5, charidx(a, 7, 1)) - call assert_equal(-1, charidx(a, 8, 1)) + call assert_equal(0, a->charidx(0, 1)) + call assert_equal(2, a->charidx(2, 1)) + call assert_equal(3, a->charidx(4, 1)) + call assert_equal(5, a->charidx(7, 1)) + call assert_equal(-1, a->charidx(8, 1)) + + " empty string + call assert_equal(-1, charidx('', 0)) call assert_equal(-1, charidx('', 0, 1)) - call assert_fails('let x = charidx([], 1)', 'E474:') - call assert_fails('let x = charidx("abc", [])', 'E474:') - call assert_fails('let x = charidx("abc", 1, [])', 'E474:') - call assert_fails('let x = charidx("abc", 1, -1)', 'E1023:') - call assert_fails('let x = charidx("abc", 1, 2)', 'E1023:') + " error cases + call assert_equal(-1, charidx(v:_null_string, 0)) + call assert_fails('let x = charidx([], 1)', 'E1174:') + call assert_fails('let x = charidx("abc", [])', 'E1210:') + call assert_fails('let x = charidx("abc", 1, [])', 'E1212:') + call assert_fails('let x = charidx("abc", 1, -1)', 'E1212:') + call assert_fails('let x = charidx("abc", 1, 2)', 'E1212:') +endfunc + +" Test for charidx() using a UTF-16 index +func Test_charidx_from_utf16_index() + " string with single byte characters + let str = "abc" + for i in range(3) + call assert_equal(i, charidx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, charidx(str, 3, v:false, v:true)) + + " string with two byte characters + let str = "a©©b" + call assert_equal(0, charidx(str, 0, v:false, v:true)) + call assert_equal(1, charidx(str, 1, v:false, v:true)) + call assert_equal(2, charidx(str, 2, v:false, v:true)) + call assert_equal(3, charidx(str, 3, v:false, v:true)) + call assert_equal(-1, charidx(str, 4, v:false, v:true)) + + " string with four byte characters + let str = "a😊😊b" + call assert_equal(0, charidx(str, 0, v:false, v:true)) + call assert_equal(1, charidx(str, 1, v:false, v:true)) + call assert_equal(1, charidx(str, 2, v:false, v:true)) + call assert_equal(2, charidx(str, 3, v:false, v:true)) + call assert_equal(2, charidx(str, 4, v:false, v:true)) + call assert_equal(3, charidx(str, 5, v:false, v:true)) + call assert_equal(-1, charidx(str, 6, v:false, v:true)) + + " string with composing characters + let str = '-á-b́' + for i in str->strcharlen()->range() + call assert_equal(i, charidx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, charidx(str, 4, v:false, v:true)) + for i in str->strchars()->range() + call assert_equal(i, charidx(str, i, v:true, v:true)) + endfor + call assert_equal(-1, charidx(str, 6, v:true, v:true)) + + " string with multiple composing characters + let str = '-ą́-ą́' + for i in str->strcharlen()->range() + call assert_equal(i, charidx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, charidx(str, 4, v:false, v:true)) + for i in str->strchars()->range() + call assert_equal(i, charidx(str, i, v:true, v:true)) + endfor + call assert_equal(-1, charidx(str, 8, v:true, v:true)) + + " empty string + call assert_equal(-1, charidx('', 0, v:false, v:true)) + call assert_equal(-1, charidx('', 0, v:true, v:true)) + + " error cases + call assert_equal(-1, charidx('', 0, v:false, v:true)) + call assert_equal(-1, charidx('', 0, v:true, v:true)) + call assert_equal(-1, charidx(v:_null_string, 0, v:false, v:true)) + call assert_fails('let x = charidx("abc", 1, v:false, [])', 'E1212:') + call assert_fails('let x = charidx("abc", 1, v:true, [])', 'E1212:') +endfunc + +" Test for utf16idx() using a byte index +func Test_utf16idx_from_byteidx() + " UTF-16 index of a string with single byte characters + let str = "abc" + for i in range(3) + call assert_equal(i, utf16idx(str, i)) + endfor + call assert_equal(-1, utf16idx(str, 3)) + + " UTF-16 index of a string with two byte characters + let str = 'a©©b' + call assert_equal(0, str->utf16idx(0)) + call assert_equal(1, str->utf16idx(1)) + call assert_equal(1, str->utf16idx(2)) + call assert_equal(2, str->utf16idx(3)) + call assert_equal(2, str->utf16idx(4)) + call assert_equal(3, str->utf16idx(5)) + call assert_equal(-1, str->utf16idx(6)) + + " UTF-16 index of a string with four byte characters + let str = 'a😊😊b' + call assert_equal(0, utf16idx(str, 0)) + call assert_equal(2, utf16idx(str, 1)) + call assert_equal(2, utf16idx(str, 2)) + call assert_equal(2, utf16idx(str, 3)) + call assert_equal(2, utf16idx(str, 4)) + call assert_equal(4, utf16idx(str, 5)) + call assert_equal(4, utf16idx(str, 6)) + call assert_equal(4, utf16idx(str, 7)) + call assert_equal(4, utf16idx(str, 8)) + call assert_equal(5, utf16idx(str, 9)) + call assert_equal(-1, utf16idx(str, 10)) + + " UTF-16 index of a string with composing characters + let str = '-á-b́' + call assert_equal(0, utf16idx(str, 0)) + call assert_equal(1, utf16idx(str, 1)) + call assert_equal(1, utf16idx(str, 2)) + call assert_equal(1, utf16idx(str, 3)) + call assert_equal(2, utf16idx(str, 4)) + call assert_equal(3, utf16idx(str, 5)) + call assert_equal(3, utf16idx(str, 6)) + call assert_equal(3, utf16idx(str, 7)) + call assert_equal(-1, utf16idx(str, 8)) + call assert_equal(0, utf16idx(str, 0, v:true)) + call assert_equal(1, utf16idx(str, 1, v:true)) + call assert_equal(2, utf16idx(str, 2, v:true)) + call assert_equal(2, utf16idx(str, 3, v:true)) + call assert_equal(3, utf16idx(str, 4, v:true)) + call assert_equal(4, utf16idx(str, 5, v:true)) + call assert_equal(5, utf16idx(str, 6, v:true)) + call assert_equal(5, utf16idx(str, 7, v:true)) + call assert_equal(-1, utf16idx(str, 8, v:true)) + + " string with multiple composing characters + let str = '-ą́-ą́' + call assert_equal(0, utf16idx(str, 0)) + call assert_equal(1, utf16idx(str, 1)) + call assert_equal(1, utf16idx(str, 2)) + call assert_equal(1, utf16idx(str, 3)) + call assert_equal(1, utf16idx(str, 4)) + call assert_equal(1, utf16idx(str, 5)) + call assert_equal(2, utf16idx(str, 6)) + call assert_equal(3, utf16idx(str, 7)) + call assert_equal(3, utf16idx(str, 8)) + call assert_equal(3, utf16idx(str, 9)) + call assert_equal(3, utf16idx(str, 10)) + call assert_equal(3, utf16idx(str, 11)) + call assert_equal(-1, utf16idx(str, 12)) + call assert_equal(0, utf16idx(str, 0, v:true)) + call assert_equal(1, utf16idx(str, 1, v:true)) + call assert_equal(2, utf16idx(str, 2, v:true)) + call assert_equal(2, utf16idx(str, 3, v:true)) + call assert_equal(3, utf16idx(str, 4, v:true)) + call assert_equal(3, utf16idx(str, 5, v:true)) + call assert_equal(4, utf16idx(str, 6, v:true)) + call assert_equal(5, utf16idx(str, 7, v:true)) + call assert_equal(6, utf16idx(str, 8, v:true)) + call assert_equal(6, utf16idx(str, 9, v:true)) + call assert_equal(7, utf16idx(str, 10, v:true)) + call assert_equal(7, utf16idx(str, 11, v:true)) + call assert_equal(-1, utf16idx(str, 12, v:true)) + + " empty string + call assert_equal(-1, utf16idx('', 0)) + call assert_equal(-1, utf16idx('', 0, v:true)) + + " error cases + call assert_equal(-1, utf16idx("", 0)) + call assert_equal(-1, utf16idx("abc", -1)) + call assert_equal(-1, utf16idx(v:_null_string, 0)) + call assert_fails('let l = utf16idx([], 0)', 'E1174:') + call assert_fails('let l = utf16idx("ab", [])', 'E1210:') + call assert_fails('let l = utf16idx("ab", 0, [])', 'E1212:') +endfunc + +" Test for utf16idx() using a character index +func Test_utf16idx_from_charidx() + let str = "abc" + for i in str->strcharlen()->range() + call assert_equal(i, utf16idx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 3, v:false, v:true)) + + " UTF-16 index of a string with two byte characters + let str = "a©©b" + for i in str->strcharlen()->range() + call assert_equal(i, utf16idx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 4, v:false, v:true)) + + " UTF-16 index of a string with four byte characters + let str = "a😊😊b" + call assert_equal(0, utf16idx(str, 0, v:false, v:true)) + call assert_equal(2, utf16idx(str, 1, v:false, v:true)) + call assert_equal(4, utf16idx(str, 2, v:false, v:true)) + call assert_equal(5, utf16idx(str, 3, v:false, v:true)) + call assert_equal(-1, utf16idx(str, 4, v:false, v:true)) + + " UTF-16 index of a string with composing characters + let str = '-á-b́' + for i in str->strcharlen()->range() + call assert_equal(i, utf16idx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 4, v:false, v:true)) + for i in str->strchars()->range() + call assert_equal(i, utf16idx(str, i, v:true, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 6, v:true, v:true)) + + " string with multiple composing characters + let str = '-ą́-ą́' + for i in str->strcharlen()->range() + call assert_equal(i, utf16idx(str, i, v:false, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 4, v:false, v:true)) + for i in str->strchars()->range() + call assert_equal(i, utf16idx(str, i, v:true, v:true)) + endfor + call assert_equal(-1, utf16idx(str, 8, v:true, v:true)) + + " empty string + call assert_equal(-1, utf16idx('', 0, v:false, v:true)) + call assert_equal(-1, utf16idx('', 0, v:true, v:true)) + + " error cases + call assert_equal(-1, utf16idx(v:_null_string, 0, v:true, v:true)) + call assert_fails('let l = utf16idx("ab", 0, v:false, [])', 'E1212:') +endfunc + +" Test for strutf16len() +func Test_strutf16len() + call assert_equal(3, strutf16len('abc')) + call assert_equal(3, 'abc'->strutf16len(v:true)) + call assert_equal(4, strutf16len('a©©b')) + call assert_equal(4, strutf16len('a©©b', v:true)) + call assert_equal(6, strutf16len('a😊😊b')) + call assert_equal(6, strutf16len('a😊😊b', v:true)) + call assert_equal(4, strutf16len('-á-b́')) + call assert_equal(6, strutf16len('-á-b́', v:true)) + call assert_equal(4, strutf16len('-ą́-ą́')) + call assert_equal(8, strutf16len('-ą́-ą́', v:true)) + call assert_equal(0, strutf16len('')) + + " error cases + call assert_fails('let l = strutf16len([])', 'E1174:') + call assert_fails('let l = strutf16len("a", [])', 'E1212:') + call assert_equal(0, strutf16len(v:_null_string)) endfunc func Test_count() @@ -1605,7 +2000,7 @@ func Test_trim() call assert_fails('eval trim(" vim ", " ", [])', 'E745:') call assert_fails('eval trim(" vim ", " ", -1)', 'E475:') call assert_fails('eval trim(" vim ", " ", 3)', 'E475:') - call assert_fails('eval trim(" vim ", 0)', 'E475:') + call assert_fails('eval trim(" vim ", 0)', 'E1174:') let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '') call assert_equal("x", trim(chars . "x" . chars)) @@ -2007,7 +2402,7 @@ func Test_call() endfunction let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} eval mydict.len->call([], mydict)->assert_equal(4) - call assert_fails("call call('Mylen', [], 0)", 'E715:') + call assert_fails("call call('Mylen', [], 0)", 'E1206:') call assert_fails('call foo', 'E107:') " These once caused a crash. @@ -2567,7 +2962,7 @@ endfunc " Test for gettext() func Test_gettext() - call assert_fails('call gettext(1)', 'E475:') + call assert_fails('call gettext(1)', 'E1174:') endfunc func Test_builtin_check() @@ -2607,4 +3002,41 @@ func Test_builtin_check() endfunc +" Test for virtcol() +func Test_virtcol() + enew! + call setline(1, "the\tquick\tbrown\tfox") + norm! 4| + call assert_equal(8, virtcol('.')) + call assert_equal(8, virtcol('.', v:false)) + call assert_equal([4, 8], virtcol('.', v:true)) + bwipe! +endfunc + +func Test_delfunc_while_listing() + CheckRunVimInTerminal + + let lines =<< trim END + set nocompatible + for i in range(1, 999) + exe 'func ' .. 'MyFunc' .. i .. '()' + endfunc + endfor + au CmdlineLeave : call timer_start(0, {-> execute('delfunc MyFunc622')}) + END + call writefile(lines, 'Xfunctionclear', 'D') + let buf = RunVimInTerminal('-S Xfunctionclear', {'rows': 12}) + + " This was using freed memory. The height of the terminal must be so that + " the next function to be listed with "j" is the one that is deleted in the + " timer callback, tricky! + call term_sendkeys(buf, ":func /MyFunc\<CR>") + call TermWait(buf, 50) + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call term_sendkeys(buf, "\<CR>") + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim index cbed71bb0a..0ff3582da9 100644 --- a/test/old/testdir/test_listdict.vim +++ b/test/old/testdir/test_listdict.vim @@ -699,7 +699,7 @@ func Test_reverse_sort_uniq() call assert_fails('call reverse("")', 'E899:') call assert_fails('call uniq([1, 2], {x, y -> []})', 'E745:') - call assert_fails("call sort([1, 2], function('min'), 1)", "E715:") + call assert_fails("call sort([1, 2], function('min'), 1)", "E1206:") call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:") call assert_fails("call sort([1, 2], function('min'))", "E118:") endfunc diff --git a/test/old/testdir/test_maparg.vim b/test/old/testdir/test_maparg.vim index 19130c1569..12670671dd 100644 --- a/test/old/testdir/test_maparg.vim +++ b/test/old/testdir/test_maparg.vim @@ -270,7 +270,7 @@ func Test_mapset() bwipe! call assert_fails('call mapset([], v:false, {})', 'E730:') - call assert_fails('call mapset("i", 0, "")', 'E715:') + call assert_fails('call mapset("i", 0, "")', 'E1206:') call assert_fails('call mapset("i", 0, {})', 'E460:') endfunc diff --git a/test/old/testdir/test_matchfuzzy.vim b/test/old/testdir/test_matchfuzzy.vim index b46550fbc3..be5c629cf5 100644 --- a/test/old/testdir/test_matchfuzzy.vim +++ b/test/old/testdir/test_matchfuzzy.vim @@ -67,7 +67,7 @@ func Test_matchfuzzy() call assert_equal([{'id' : 6, 'val' : 'camera'}], matchfuzzy(l, 'cam', {'key' : 'val'})) call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> v.val}})) call assert_equal([], matchfuzzy(l, 'day', {'key' : 'val'})) - call assert_fails("let x = matchfuzzy(l, 'cam', 'random')", 'E715:') + call assert_fails("let x = matchfuzzy(l, 'cam', 'random')", 'E1206:') call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> []}})) call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> 1}})) call assert_fails("let x = matchfuzzy(l, 'day', {'text_cb' : {a, b -> 1}})", 'E119:') @@ -76,7 +76,7 @@ func Test_matchfuzzy() " call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E921:') call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E6000:') call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : []})", 'E730:') - call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E715:') + call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E1297:') call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : v:_null_string})", 'E475:') " Nvim doesn't have null functions " call assert_fails("let x = matchfuzzy(l, 'foo', {'text_cb' : test_null_function()})", 'E475:') @@ -144,7 +144,7 @@ func Test_matchfuzzypos() \ matchfuzzypos(l, 'cam', {'key' : 'val'})) call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> v.val}})) call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'key' : 'val'})) - call assert_fails("let x = matchfuzzypos(l, 'cam', 'random')", 'E715:') + call assert_fails("let x = matchfuzzypos(l, 'cam', 'random')", 'E1206:') call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> []}})) call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> 1}})) call assert_fails("let x = matchfuzzypos(l, 'day', {'text_cb' : {a, b -> 1}})", 'E119:') @@ -153,7 +153,7 @@ func Test_matchfuzzypos() " call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E921:') call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E6000:') call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : []})", 'E730:') - call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E715:') + call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E1297:') call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : v:_null_string})", 'E475:') " Nvim doesn't have null functions " call assert_fails("let x = matchfuzzypos(l, 'foo', {'text_cb' : test_null_function()})", 'E475:') diff --git a/test/old/testdir/test_partial.vim b/test/old/testdir/test_partial.vim index 302bc22d93..8b62e4a0e5 100644 --- a/test/old/testdir/test_partial.vim +++ b/test/old/testdir/test_partial.vim @@ -86,7 +86,7 @@ func Test_partial_dict() call assert_equal("Hello", dict.tr()) call assert_fails("let F=function('setloclist', 10)", "E923:") - call assert_fails("let F=function('setloclist', [], [])", "E922:") + call assert_fails("let F=function('setloclist', [], [])", "E1206:") endfunc func Test_partial_implicit() diff --git a/test/old/testdir/test_search_stat.vim b/test/old/testdir/test_search_stat.vim index 1b2d854829..8dfc850956 100644 --- a/test/old/testdir/test_search_stat.vim +++ b/test/old/testdir/test_search_stat.vim @@ -259,7 +259,7 @@ func Test_search_stat() endfunc func Test_searchcount_fails() - call assert_fails('echo searchcount("boo!")', 'E715:') + call assert_fails('echo searchcount("boo!")', 'E1206:') call assert_fails('echo searchcount({"timeout" : []})', 'E745:') call assert_fails('echo searchcount({"maxcount" : []})', 'E745:') call assert_fails('echo searchcount({"pattern" : []})', 'E730:') diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim index 129f1c1a0c..1e972371a5 100644 --- a/test/old/testdir/test_signs.vim +++ b/test/old/testdir/test_signs.vim @@ -463,7 +463,7 @@ func Test_sign_funcs() call assert_fails('call sign_define("sign4", {"text" : "===>"})', 'E239:') " call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:') call assert_fails('call sign_define({})', 'E731:') - call assert_fails('call sign_define("sign6", [])', 'E715:') + call assert_fails('call sign_define("sign6", [])', 'E1206:') " Tests for sign_getdefined() call assert_equal([], sign_getdefined("none")) @@ -490,8 +490,7 @@ func Test_sign_funcs() " Tests for invalid arguments to sign_place() call assert_fails('call sign_place([], "", "mySign", 1)', 'E745:') call assert_fails('call sign_place(5, "", "mySign", -1)', 'E158:') - call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])', - \ 'E715:') + call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])', 'E1206:') call assert_fails('call sign_place(-1, "", "sign1", "Xsign", \ {"lnum" : 30})', 'E474:') call assert_fails('call sign_place(10, "", "xsign1x", "Xsign", @@ -526,7 +525,7 @@ func Test_sign_funcs() call assert_fails("call sign_getplaced('dummy.sign')", 'E158:') call assert_fails('call sign_getplaced("&")', 'E158:') call assert_fails('call sign_getplaced(-1)', 'E158:') - call assert_fails('call sign_getplaced("Xsign", [])', 'E715:') + call assert_fails('call sign_getplaced("Xsign", [])', 'E1206:') call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}], \ sign_getplaced('Xsign', {'lnum' : 1000000})) call assert_fails("call sign_getplaced('Xsign', {'lnum' : []})", @@ -549,7 +548,7 @@ func Test_sign_funcs() \ {'id' : 20, 'buffer' : '&'})", 'E158:') call assert_fails("call sign_unplace('g1', \ {'id' : 20, 'buffer' : 200})", 'E158:') - call assert_fails("call sign_unplace('g1', 'mySign')", 'E715:') + call assert_fails("call sign_unplace('g1', 'mySign')", 'E1206:') call sign_unplace('*') @@ -701,7 +700,7 @@ func Test_sign_group() call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs) " Error case - call assert_fails("call sign_unplace({})", 'E474:') + call assert_fails("call sign_unplace({})", 'E1174:') " Place a sign in the global group and try to delete it using a group call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10})) @@ -1568,8 +1567,7 @@ func Test_sign_priority() \ s[0].signs) " Error case - call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', - \ [])", 'E715:') + call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', [])", 'E1206:') call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', \ {'priority' : []})", 'E745:') call sign_unplace('*') diff --git a/test/old/testdir/test_tagjump.vim b/test/old/testdir/test_tagjump.vim index be60a3535c..f330bca125 100644 --- a/test/old/testdir/test_tagjump.vim +++ b/test/old/testdir/test_tagjump.vim @@ -405,10 +405,10 @@ func Test_getsettagstack() " Error cases call assert_equal({}, gettagstack(100)) call assert_equal(-1, settagstack(100, {'items' : []})) - call assert_fails('call settagstack(1, [1, 10])', 'E715') - call assert_fails("call settagstack(1, {'items' : 10})", 'E714') - call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E928') - call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962') + call assert_fails('call settagstack(1, [1, 10])', 'E1206:') + call assert_fails("call settagstack(1, {'items' : 10})", 'E714:') + call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E1174:') + call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962:') call assert_equal(-1, settagstack(0, v:_null_dict)) set tags=Xtags diff --git a/test/old/testdir/test_timers.vim b/test/old/testdir/test_timers.vim index f94ee6c9f3..37226c7efb 100644 --- a/test/old/testdir/test_timers.vim +++ b/test/old/testdir/test_timers.vim @@ -93,7 +93,13 @@ func Test_timer_info() call timer_stop(id) call assert_equal([], timer_info(id)) - call assert_fails('call timer_info("abc")', 'E39:') + call assert_fails('call timer_info("abc")', 'E1210:') + + " check repeat count inside the callback + let g:timer_repeat = [] + let tid = timer_start(10, {tid -> execute("call add(g:timer_repeat, timer_info(tid)[0].repeat)")}, #{repeat: 3}) + call WaitForAssert({-> assert_equal([2, 1, 0], g:timer_repeat)}) + unlet g:timer_repeat endfunc func Test_timer_stopall() @@ -228,9 +234,9 @@ func Test_timer_errors() sleep 50m call assert_equal(3, g:call_count) - call assert_fails('call timer_start(100, "MyHandler", "abc")', 'E475:') + call assert_fails('call timer_start(100, "MyHandler", "abc")', 'E1206:') call assert_fails('call timer_start(100, [])', 'E921:') - call assert_fails('call timer_stop("abc")', 'E39:') + call assert_fails('call timer_stop("abc")', 'E1210:') endfunc func FuncWithCaughtError(timer) diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim index 88135199fe..9320d67498 100644 --- a/test/old/testdir/test_window_cmd.vim +++ b/test/old/testdir/test_window_cmd.vim @@ -735,7 +735,7 @@ func Test_relative_cursor_position_in_one_line_window() only! bwipe! - call assert_fails('call winrestview(v:_null_dict)', 'E474:') + call assert_fails('call winrestview(v:_null_dict)', 'E1297:') endfunc func Test_relative_cursor_position_after_move_and_resize() @@ -936,7 +936,7 @@ func Test_winrestview() call assert_equal(view, winsaveview()) bwipe! - call assert_fails('call winrestview(v:_null_dict)', 'E474:') + call assert_fails('call winrestview(v:_null_dict)', 'E1297:') endfunc func Test_win_splitmove() @@ -967,7 +967,7 @@ func Test_win_splitmove() call assert_equal(bufname(winbufnr(2)), 'b') call assert_equal(bufname(winbufnr(3)), 'a') call assert_equal(bufname(winbufnr(4)), 'd') - call assert_fails('call win_splitmove(winnr(), winnr("k"), v:_null_dict)', 'E474:') + call assert_fails('call win_splitmove(winnr(), winnr("k"), v:_null_dict)', 'E1297:') only | bd call assert_fails('call win_splitmove(winnr(), 123)', 'E957:') |