From 4b65a0059aff80802783824ab3d973543a83a7c6 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 2 May 2019 21:55:16 +0200 Subject: test: cleanup Avoid hyper-granularity. Don't need subdirectories for every little thing. --- .../clipboard/clipboard_provider_spec.lua | 683 --------------------- test/functional/core/spellfile_spec.lua | 110 ++++ test/functional/provider/clipboard_spec.lua | 683 +++++++++++++++++++++ test/functional/spell/spellfile_spec.lua | 110 ---- 4 files changed, 793 insertions(+), 793 deletions(-) delete mode 100644 test/functional/clipboard/clipboard_provider_spec.lua create mode 100644 test/functional/core/spellfile_spec.lua create mode 100644 test/functional/provider/clipboard_spec.lua delete mode 100644 test/functional/spell/spellfile_spec.lua diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua deleted file mode 100644 index b2d75db745..0000000000 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ /dev/null @@ -1,683 +0,0 @@ --- Test clipboard provider support - -local helpers = require('test.functional.helpers')(after_each) -local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect, eq, eval, source = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source -local command = helpers.command -local meths = helpers.meths - -local function basic_register_test(noblock) - insert("some words") - - feed('^dwP') - expect('some words') - - feed('veyP') - expect('some words words') - - feed('^dwywe"-p') - expect('wordssome words') - - feed('p') - expect('wordssome words words') - - feed('yyp') - expect([[ - wordssome words words - wordssome words words]]) - feed('d-') - - insert([[ - some text, and some more - random text stuff]]) - feed('ggtav+2ed$p') - expect([[ - some text, stuff and some more - random text]]) - - -- deleting line or word uses "1/"- and doesn't clobber "0 - -- and deleting word to unnamed doesn't clobber "1 - feed('ggyyjdddw"0p"1p"-P') - expect([[ - text, stuff and some more - some text, stuff and some more - some random text]]) - - -- delete line doesn't clobber "- - feed('dd"-P') - expect([[ - text, stuff and some more - some some text, stuff and some more]]) - - -- deleting a word to named ("a) updates "1 (and not "-) - feed('gg"adwj"1P^"-P') - expect([[ - , stuff and some more - some textsome some text, stuff and some more]]) - - -- deleting a line does update "" - feed('ggdd""P') - expect([[ - , stuff and some more - some textsome some text, stuff and some more]]) - - feed('ggwjwyggP') - if noblock then - expect([[ - stuf - me t - , stuff and some more - some textsome some text, stuff and some more]]) - else - expect([[ - stuf, stuff and some more - me tsome textsome some text, stuff and some more]]) - end - - -- pasting in visual does unnamed delete of visual selection - feed('ggdG') - insert("one and two and three") - feed('"ayiwbbviw"ap^viwp$viw"-p') - expect("two and three and one") -end - -describe('clipboard', function() - local screen - - before_each(function() - clear() - screen = Screen.new(72, 4) - screen:attach() - command("set display-=msgsep") - end) - - it('unnamed register works without provider', function() - eq('"', eval('v:register')) - basic_register_test() - end) - - it('`:redir @+>` with invalid g:clipboard shows exactly one error #7184', - function() - command("let g:clipboard = 'bogus'") - feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') - screen:expect([[ - ^ | - ~ | - ~ | - clipboard: No provider. Try ":checkhealth" or ":h clipboard". | - ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) - end) - - it('`:redir @+>|bogus_cmd|redir END` + invalid g:clipboard must not recurse #7184', - function() - command("let g:clipboard = 'bogus'") - feed_command('redir @+> | bogus_cmd | redir END') - screen:expect([[ - ~ | - clipboard: No provider. Try ":checkhealth" or ":h clipboard". | - E492: Not an editor command: bogus_cmd | redir END | - Press ENTER or type command to continue^ | - ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) - end) - - it('invalid g:clipboard shows hint if :redir is not active', function() - command("let g:clipboard = 'bogus'") - eq('', eval('provider#clipboard#Executable()')) - eq('clipboard: invalid g:clipboard', eval('provider#clipboard#Error()')) - - command("let g:clipboard = 'bogus'") - -- Explicit clipboard attempt, should show a hint message. - feed_command('let @+="foo"') - screen:expect([[ - ^ | - ~ | - ~ | - clipboard: No provider. Try ":checkhealth" or ":h clipboard". | - ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) - end) - - it('valid g:clipboard', function() - -- provider#clipboard#Executable() only checks the structure. - meths.set_var('clipboard', { - ['name'] = 'clippy!', - ['copy'] = { ['+'] = 'any command', ['*'] = 'some other' }, - ['paste'] = { ['+'] = 'any command', ['*'] = 'some other' }, - }) - eq('clippy!', eval('provider#clipboard#Executable()')) - eq('', eval('provider#clipboard#Error()')) - end) - - it('g:clipboard using VimL functions', function() - -- Implements a fake clipboard provider. cache_enabled is meaningless here. - source([[let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { - \ '+': {lines, regtype -> extend(g:, {'dummy_clipboard_plus': [lines, regtype]}) }, - \ '*': {lines, regtype -> extend(g:, {'dummy_clipboard_star': [lines, regtype]}) }, - \ }, - \ 'paste': { - \ '+': {-> get(g:, 'dummy_clipboard_plus', [])}, - \ '*': {-> get(g:, 'dummy_clipboard_star', [])}, - \ }, - \ 'cache_enabled': 1, - \}]]) - - eq('', eval('provider#clipboard#Error()')) - eq('custom', eval('provider#clipboard#Executable()')) - - eq('', eval("getreg('*')")) - eq('', eval("getreg('+')")) - - command('call setreg("*", "star")') - command('call setreg("+", "plus")') - eq('star', eval("getreg('*')")) - eq('plus', eval("getreg('+')")) - - command('call setreg("*", "star", "v")') - eq({{'star'}, 'v'}, eval("g:dummy_clipboard_star")) - command('call setreg("*", "star", "V")') - eq({{'star', ''}, 'V'}, eval("g:dummy_clipboard_star")) - command('call setreg("*", "star", "b")') - eq({{'star', ''}, 'b'}, eval("g:dummy_clipboard_star")) - end) - - describe('g:clipboard[paste] VimL function', function() - it('can return empty list for empty clipboard', function() - source([[let g:dummy_clipboard = [] - let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { '*': {lines, regtype -> 0} }, - \ 'paste': { '*': {-> g:dummy_clipboard} }, - \}]]) - eq('', eval('provider#clipboard#Error()')) - eq('custom', eval('provider#clipboard#Executable()')) - eq('', eval("getreg('*')")) - end) - - it('can return a list with a single string', function() - source([=[let g:dummy_clipboard = ['hello'] - let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { '*': {lines, regtype -> 0} }, - \ 'paste': { '*': {-> g:dummy_clipboard} }, - \}]=]) - eq('', eval('provider#clipboard#Error()')) - eq('custom', eval('provider#clipboard#Executable()')) - - eq('hello', eval("getreg('*')")) - source([[let g:dummy_clipboard = [''] ]]) - eq('', eval("getreg('*')")) - end) - - it('can return a list of lines if a regtype is provided', function() - source([=[let g:dummy_clipboard = [['hello'], 'v'] - let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { '*': {lines, regtype -> 0} }, - \ 'paste': { '*': {-> g:dummy_clipboard} }, - \}]=]) - eq('', eval('provider#clipboard#Error()')) - eq('custom', eval('provider#clipboard#Executable()')) - eq('hello', eval("getreg('*')")) - end) - - it('can return a list of lines instead of [lines, regtype]', function() - source([=[let g:dummy_clipboard = ['hello', 'v'] - let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { '*': {lines, regtype -> 0} }, - \ 'paste': { '*': {-> g:dummy_clipboard} }, - \}]=]) - eq('', eval('provider#clipboard#Error()')) - eq('custom', eval('provider#clipboard#Executable()')) - eq('hello\nv', eval("getreg('*')")) - end) - end) -end) - -describe('clipboard (with fake clipboard.vim)', function() - local function reset(...) - clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...) - end - - before_each(function() - reset() - feed_command('call getreg("*")') -- force load of provider - end) - - it('`:redir @+>` invokes clipboard once-per-message', function() - eq(0, eval("g:clip_called_set")) - feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') - -- Assuming CONTRIBUTING.md has >100 lines. - assert(eval("g:clip_called_set") > 100) - end) - - it('`:redir @">` does NOT invoke clipboard', function() - -- :redir to a non-clipboard register, with `:set clipboard=unnamed` does - -- NOT propagate to the clipboard. This is consistent with Vim. - command("set clipboard=unnamedplus") - eq(0, eval("g:clip_called_set")) - feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END') - eq(0, eval("g:clip_called_set")) - end) - - it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184', - function() - local screen = Screen.new(72, 4) - screen:attach() - feed_command('redir @+> | bogus_cmd | redir END') - screen:expect([[ - ^ | - ~ | - ~ | - E492: Not an editor command: bogus_cmd | redir END | - ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) - end) - - it('has independent "* and unnamed registers by default', function() - insert("some words") - feed('^"*dwdw"*P') - expect('some ') - eq({{'some '}, 'v'}, eval("g:test_clip['*']")) - eq('words', eval("getreg('\"', 1)")) - end) - - it('supports separate "* and "+ when the provider supports it', function() - insert([[ - text: - first line - secound line - third line]]) - - feed('G"+dd"*dddd"+p"*pp') - expect([[ - text: - third line - secound line - first line]]) - -- linewise selection should be encoded as an extra newline - eq({{'third line', ''}, 'V'}, eval("g:test_clip['+']")) - eq({{'secound line', ''}, 'V'}, eval("g:test_clip['*']")) - end) - - it('handles null bytes when pasting and in getreg', function() - insert("some\022000text\n\022000very binary\022000") - feed('"*y-+"*p') - eq({{'some\ntext', '\nvery binary\n',''}, 'V'}, eval("g:test_clip['*']")) - expect("some\00text\n\00very binary\00\nsome\00text\n\00very binary\00") - - -- test getreg/getregtype - eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1)")) - eq("V", eval("getregtype('*')")) - - -- getreg supports three arguments - eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1, 0)")) - eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)")) - end) - - it('autodetects regtype', function() - feed_command("let g:test_clip['*'] = ['linewise stuff','']") - feed_command("let g:test_clip['+'] = ['charwise','stuff']") - eq("V", eval("getregtype('*')")) - eq("v", eval("getregtype('+')")) - insert("just some text") - feed('"*p"+p') - expect([[ - just some text - lcharwise - stuffinewise stuff]]) - end) - - it('support blockwise operations', function() - insert([[ - much - text]]) - feed_command("let g:test_clip['*'] = [['very','block'],'b']") - feed('gg"*P') - expect([[ - very much - blocktext]]) - eq("\0225", eval("getregtype('*')")) - feed('gg4lj4l"+ygg"+P') - expect([[ - muchvery much - ktextblocktext]]) - eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']")) - end) - - it('supports setreg()', function() - feed_command('call setreg("*", "setted\\ntext", "c")') - feed_command('call setreg("+", "explicitly\\nlines", "l")') - feed('"+P"*p') - expect([[ - esetted - textxplicitly - lines - ]]) - feed_command('call setreg("+", "blocky\\nindeed", "b")') - feed('"+p') - expect([[ - esblockyetted - teindeedxtxplicitly - lines - ]]) - end) - - it('supports :let @+ (issue #1427)', function() - feed_command("let @+ = 'some'") - feed_command("let @* = ' other stuff'") - eq({{'some'}, 'v'}, eval("g:test_clip['+']")) - eq({{' other stuff'}, 'v'}, eval("g:test_clip['*']")) - feed('"+p"*p') - expect('some other stuff') - feed_command("let @+ .= ' more'") - feed('dd"+p') - expect('some more') - end) - - it('pastes unnamed register if the provider fails', function() - insert('the text') - feed('yy') - feed_command("let g:cliperror = 1") - feed('"*p') - expect([[ - the text - the text]]) - end) - - - describe('with clipboard=unnamed', function() - -- the basic behavior of unnamed register should be the same - -- even when handled by clipboard provider - before_each(function() - feed_command('set clipboard=unnamed') - end) - - it('works', function() - basic_register_test() - end) - - it('works with pure text clipboard', function() - feed_command("let g:cliplossy = 1") - -- expect failure for block mode - basic_register_test(true) - end) - - it('links the "* and unnamed registers', function() - -- with cb=unnamed, "* and unnamed will be the same register - insert("some words") - feed('^"*dwdw"*P') - expect('words') - eq({{'words'}, 'v'}, eval("g:test_clip['*']")) - - -- "+ shouldn't have changed - eq({''}, eval("g:test_clip['+']")) - - feed_command("let g:test_clip['*'] = ['linewise stuff','']") - feed('p') - expect([[ - words - linewise stuff]]) - end) - - it('does not clobber "0 when pasting', function() - insert('a line') - feed('yy') - feed_command("let g:test_clip['*'] = ['b line','']") - feed('"0pp"0p') - expect([[ - a line - a line - b line - a line]]) - end) - - it('supports v:register and getreg() without parameters', function() - eq('*', eval('v:register')) - feed_command("let g:test_clip['*'] = [['some block',''], 'b']") - eq('some block', eval('getreg()')) - eq('\02210', eval('getregtype()')) - end) - - it('yanks visual selection when pasting', function() - insert("indeed visual") - feed_command("let g:test_clip['*'] = [['clipboard'], 'c']") - feed("viwp") - eq({{'visual'}, 'v'}, eval("g:test_clip['*']")) - expect("indeed clipboard") - - -- explicit "* should do the same - feed_command("let g:test_clip['*'] = [['star'], 'c']") - feed('viw"*p') - eq({{'clipboard'}, 'v'}, eval("g:test_clip['*']")) - expect("indeed star") - end) - - it('unamed operations work even if the provider fails', function() - insert('the text') - feed('yy') - feed_command("let g:cliperror = 1") - feed('p') - expect([[ - the text - the text]]) - end) - - it('is updated on global changes', function() - insert([[ - text - match - match - text - ]]) - feed_command('g/match/d') - eq('match\n', eval('getreg("*")')) - feed('u') - eval('setreg("*", "---")') - feed_command('g/test/') - feed('') - eq('---', eval('getreg("*")')) - end) - - it('works in the cmdline window', function() - feed('q:itextyy') - eq({{'text', ''}, 'V'}, eval("g:test_clip['*']")) - command("let g:test_clip['*'] = [['star'], 'c']") - feed('p') - eq('textstar', meths.get_current_line()) - end) - end) - - describe('clipboard=unnamedplus', function() - before_each(function() - feed_command('set clipboard=unnamedplus') - end) - - it('links the "+ and unnamed registers', function() - eq('+', eval('v:register')) - insert("one two") - feed('^"+dwdw"+P') - expect('two') - eq({{'two'}, 'v'}, eval("g:test_clip['+']")) - - -- "* shouldn't have changed - eq({''}, eval("g:test_clip['*']")) - - feed_command("let g:test_clip['+'] = ['three']") - feed('p') - expect('twothree') - end) - - it('and unnamed, yanks to both', function() - feed_command('set clipboard=unnamedplus,unnamed') - insert([[ - really unnamed - text]]) - feed('ggdd"*p"+p') - expect([[ - text - really unnamed - really unnamed]]) - eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['+']")) - eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['*']")) - - -- unnamedplus takes predecence when pasting - eq('+', eval('v:register')) - feed_command("let g:test_clip['+'] = ['the plus','']") - feed_command("let g:test_clip['*'] = ['the star','']") - feed("p") - expect([[ - text - really unnamed - really unnamed - the plus]]) - end) - - it('is updated on global changes', function() - insert([[ - text - match - match - text - ]]) - feed_command('g/match/d') - eq('match\n', eval('getreg("+")')) - feed('u') - eval('setreg("+", "---")') - feed_command('g/test/') - feed('') - eq('---', eval('getreg("+")')) - end) - end) - - it('sets v:register after startup', function() - reset() - eq('"', eval('v:register')) - reset('--cmd', 'set clipboard=unnamed') - eq('*', eval('v:register')) - end) - - it('supports :put', function() - insert("a line") - feed_command("let g:test_clip['*'] = ['some text']") - feed_command("let g:test_clip['+'] = ['more', 'text', '']") - feed_command(":put *") - expect([[ - a line - some text]]) - feed_command(":put +") - expect([[ - a line - some text - more - text]]) - end) - - it('supports "+ and "* in registers', function() - local screen = Screen.new(60, 10) - screen:attach() - feed_command("let g:test_clip['*'] = ['some', 'star data','']") - feed_command("let g:test_clip['+'] = ['such', 'plus', 'stuff']") - feed_command("registers") - screen:expect([[ - | - {0:~ }| - {0:~ }| - {4: }| - :registers | - {1:--- Registers ---} | - "* some{2:^J}star data{2:^J} | - "+ such{2:^J}plus{2:^J}stuff | - ": let g:test_clip['+'] = ['such', 'plus', 'stuff'] | - {3:Press ENTER or type command to continue}^ | - ]], { - [0] = {bold = true, foreground = Screen.colors.Blue}, - [1] = {bold = true, foreground = Screen.colors.Fuchsia}, - [2] = {foreground = Screen.colors.Blue}, - [3] = {bold = true, foreground = Screen.colors.SeaGreen}, - [4] = {bold = true, reverse = true}}) - feed('') -- clear out of Press ENTER screen - end) - - it('can paste "* to the commandline', function() - insert('s/s/t/') - feed('gg"*y$:*') - expect('t/s/t/') - feed_command("let g:test_clip['*'] = ['s/s/u']") - feed(':*') - expect('t/u/t/') - end) - - it('supports :redir @*>', function() - feed_command("let g:test_clip['*'] = ['stuff']") - feed_command('redir @*>') - -- it is made empty - eq({{''}, 'v'}, eval("g:test_clip['*']")) - feed_command('let g:test = doesnotexist') - feed('') - eq({{ - '', - '', - 'E121: Undefined variable: doesnotexist', - 'E15: Invalid expression: doesnotexist', - }, 'v'}, eval("g:test_clip['*']")) - feed_command(':echo "Howdy!"') - eq({{ - '', - '', - 'E121: Undefined variable: doesnotexist', - 'E15: Invalid expression: doesnotexist', - '', - 'Howdy!', - }, 'v'}, eval("g:test_clip['*']")) - end) - - it('handles middleclick correctly', function() - feed_command('set mouse=a') - - local screen = Screen.new(30, 5) - screen:attach() - insert([[ - the source - a target]]) - feed('gg"*ywwyw') - -- clicking depends on the exact visual layout, so expect it: - screen:expect([[ - the ^source | - a target | - ~ | - ~ | - | - ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) - - feed('<0,1>') - expect([[ - the source - the a target]]) - - -- on error, fall back to unnamed register - feed_command("let g:cliperror = 1") - feed('<6,1>') - expect([[ - the source - the a sourcetarget]]) - end) - - it('setreg("*") with clipboard=unnamed #5646', function() - source([=[ - function! Paste_without_yank(direction) range - let [reg_save,regtype_save] = [getreg('*'), getregtype('*')] - normal! gvp - call setreg('*', reg_save, regtype_save) - endfunction - xnoremap p :call Paste_without_yank('p') - set clipboard=unnamed - ]=]) - insert('some words') - feed('gg0yiw') - feed('wviwp') - expect('some some') - eq('some', eval('getreg("*")')) - end) -end) diff --git a/test/functional/core/spellfile_spec.lua b/test/functional/core/spellfile_spec.lua new file mode 100644 index 0000000000..afd2c1bce4 --- /dev/null +++ b/test/functional/core/spellfile_spec.lua @@ -0,0 +1,110 @@ +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') + +local eq = helpers.eq +local clear = helpers.clear +local meths = helpers.meths +local exc_exec = helpers.exc_exec +local rmdir = helpers.rmdir +local write_file = helpers.write_file + +local testdir = 'Xtest-functional-spell-spellfile.d' + +describe('spellfile', function() + before_each(function() + clear() + rmdir(testdir) + lfs.mkdir(testdir) + lfs.mkdir(testdir .. '/spell') + end) + after_each(function() + rmdir(testdir) + end) + -- ┌ Magic string (#VIMSPELLMAGIC) + -- │ ┌ Spell file version (#VIMSPELLVERSION) + local spellheader = 'VIMspell\050' + it('errors out when prefcond section is truncated', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- ┌ Section identifier (#SN_PREFCOND) + -- │ ┌ Section flags (#SNF_REQUIRED or zero) + -- │ │ ┌ Section length (4 bytes, MSB first) + spellheader .. '\003\001\000\000\000\003' + -- ┌ Number of regexes in section (2 bytes, MSB first) + -- │ ┌ Condition length (1 byte) + -- │ │ ┌ Condition regex (missing!) + .. '\000\001\001') + meths.set_option('spelllang', 'en') + eq('Vim(set):E758: Truncated spell file', + exc_exec('set spell')) + end) + it('errors out when prefcond regexp contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- ┌ Section identifier (#SN_PREFCOND) + -- │ ┌ Section flags (#SNF_REQUIRED or zero) + -- │ │ ┌ Section length (4 bytes, MSB first) + spellheader .. '\003\001\000\000\000\008' + -- ┌ Number of regexes in section (2 bytes, MSB first) + -- │ ┌ Condition length (1 byte) + -- │ │ ┌ Condition regex + -- │ │ │ ┌ End of sections marker + .. '\000\001\005ab\000cd\255' + -- ┌ LWORDTREE tree length (4 bytes) + -- │ ┌ KWORDTREE tree length (4 bytes) + -- │ │ ┌ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when region contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- ┌ Section identifier (#SN_REGION) + -- │ ┌ Section flags (#SNF_REQUIRED or zero) + -- │ │ ┌ Section length (4 bytes, MSB first) + spellheader .. '\000\001\000\000\000\008' + -- ┌ Regions ┌ End of sections marker + .. '01234\00067\255' + -- ┌ LWORDTREE tree length (4 bytes) + -- │ ┌ KWORDTREE tree length (4 bytes) + -- │ │ ┌ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when SAL section contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- ┌ Section identifier (#SN_SAL) + -- │ ┌ Section flags (#SNF_REQUIRED or zero) + -- │ │ ┌ Section length (4 bytes, MSB first) + spellheader .. '\005\001\000\000\000\008' + -- ┌ salflags + -- │ ┌ salcount (2 bytes, MSB first) + -- │ │ ┌ salfromlen (1 byte) + -- │ │ │ ┌ Special character + -- │ │ │ │┌ salfrom (should not contain NUL) + -- │ │ │ ││ ┌ saltolen + -- │ │ │ ││ │ ┌ salto + -- │ │ │ ││ │ │┌ End of sections marker + .. '\000\000\001\0024\000\0017\255' + -- ┌ LWORDTREE tree length (4 bytes) + -- │ ┌ KWORDTREE tree length (4 bytes) + -- │ │ ┌ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when spell header contains NUL bytes', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + spellheader:sub(1, -3) .. '\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E757: This does not look like a spell file', + exc_exec('set spell')) + end) +end) diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua new file mode 100644 index 0000000000..b2d75db745 --- /dev/null +++ b/test/functional/provider/clipboard_spec.lua @@ -0,0 +1,683 @@ +-- Test clipboard provider support + +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local feed_command, expect, eq, eval, source = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source +local command = helpers.command +local meths = helpers.meths + +local function basic_register_test(noblock) + insert("some words") + + feed('^dwP') + expect('some words') + + feed('veyP') + expect('some words words') + + feed('^dwywe"-p') + expect('wordssome words') + + feed('p') + expect('wordssome words words') + + feed('yyp') + expect([[ + wordssome words words + wordssome words words]]) + feed('d-') + + insert([[ + some text, and some more + random text stuff]]) + feed('ggtav+2ed$p') + expect([[ + some text, stuff and some more + random text]]) + + -- deleting line or word uses "1/"- and doesn't clobber "0 + -- and deleting word to unnamed doesn't clobber "1 + feed('ggyyjdddw"0p"1p"-P') + expect([[ + text, stuff and some more + some text, stuff and some more + some random text]]) + + -- delete line doesn't clobber "- + feed('dd"-P') + expect([[ + text, stuff and some more + some some text, stuff and some more]]) + + -- deleting a word to named ("a) updates "1 (and not "-) + feed('gg"adwj"1P^"-P') + expect([[ + , stuff and some more + some textsome some text, stuff and some more]]) + + -- deleting a line does update "" + feed('ggdd""P') + expect([[ + , stuff and some more + some textsome some text, stuff and some more]]) + + feed('ggwjwyggP') + if noblock then + expect([[ + stuf + me t + , stuff and some more + some textsome some text, stuff and some more]]) + else + expect([[ + stuf, stuff and some more + me tsome textsome some text, stuff and some more]]) + end + + -- pasting in visual does unnamed delete of visual selection + feed('ggdG') + insert("one and two and three") + feed('"ayiwbbviw"ap^viwp$viw"-p') + expect("two and three and one") +end + +describe('clipboard', function() + local screen + + before_each(function() + clear() + screen = Screen.new(72, 4) + screen:attach() + command("set display-=msgsep") + end) + + it('unnamed register works without provider', function() + eq('"', eval('v:register')) + basic_register_test() + end) + + it('`:redir @+>` with invalid g:clipboard shows exactly one error #7184', + function() + command("let g:clipboard = 'bogus'") + feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') + screen:expect([[ + ^ | + ~ | + ~ | + clipboard: No provider. Try ":checkhealth" or ":h clipboard". | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('`:redir @+>|bogus_cmd|redir END` + invalid g:clipboard must not recurse #7184', + function() + command("let g:clipboard = 'bogus'") + feed_command('redir @+> | bogus_cmd | redir END') + screen:expect([[ + ~ | + clipboard: No provider. Try ":checkhealth" or ":h clipboard". | + E492: Not an editor command: bogus_cmd | redir END | + Press ENTER or type command to continue^ | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('invalid g:clipboard shows hint if :redir is not active', function() + command("let g:clipboard = 'bogus'") + eq('', eval('provider#clipboard#Executable()')) + eq('clipboard: invalid g:clipboard', eval('provider#clipboard#Error()')) + + command("let g:clipboard = 'bogus'") + -- Explicit clipboard attempt, should show a hint message. + feed_command('let @+="foo"') + screen:expect([[ + ^ | + ~ | + ~ | + clipboard: No provider. Try ":checkhealth" or ":h clipboard". | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('valid g:clipboard', function() + -- provider#clipboard#Executable() only checks the structure. + meths.set_var('clipboard', { + ['name'] = 'clippy!', + ['copy'] = { ['+'] = 'any command', ['*'] = 'some other' }, + ['paste'] = { ['+'] = 'any command', ['*'] = 'some other' }, + }) + eq('clippy!', eval('provider#clipboard#Executable()')) + eq('', eval('provider#clipboard#Error()')) + end) + + it('g:clipboard using VimL functions', function() + -- Implements a fake clipboard provider. cache_enabled is meaningless here. + source([[let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { + \ '+': {lines, regtype -> extend(g:, {'dummy_clipboard_plus': [lines, regtype]}) }, + \ '*': {lines, regtype -> extend(g:, {'dummy_clipboard_star': [lines, regtype]}) }, + \ }, + \ 'paste': { + \ '+': {-> get(g:, 'dummy_clipboard_plus', [])}, + \ '*': {-> get(g:, 'dummy_clipboard_star', [])}, + \ }, + \ 'cache_enabled': 1, + \}]]) + + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + + eq('', eval("getreg('*')")) + eq('', eval("getreg('+')")) + + command('call setreg("*", "star")') + command('call setreg("+", "plus")') + eq('star', eval("getreg('*')")) + eq('plus', eval("getreg('+')")) + + command('call setreg("*", "star", "v")') + eq({{'star'}, 'v'}, eval("g:dummy_clipboard_star")) + command('call setreg("*", "star", "V")') + eq({{'star', ''}, 'V'}, eval("g:dummy_clipboard_star")) + command('call setreg("*", "star", "b")') + eq({{'star', ''}, 'b'}, eval("g:dummy_clipboard_star")) + end) + + describe('g:clipboard[paste] VimL function', function() + it('can return empty list for empty clipboard', function() + source([[let g:dummy_clipboard = [] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('', eval("getreg('*')")) + end) + + it('can return a list with a single string', function() + source([=[let g:dummy_clipboard = ['hello'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + + eq('hello', eval("getreg('*')")) + source([[let g:dummy_clipboard = [''] ]]) + eq('', eval("getreg('*')")) + end) + + it('can return a list of lines if a regtype is provided', function() + source([=[let g:dummy_clipboard = [['hello'], 'v'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('hello', eval("getreg('*')")) + end) + + it('can return a list of lines instead of [lines, regtype]', function() + source([=[let g:dummy_clipboard = ['hello', 'v'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('hello\nv', eval("getreg('*')")) + end) + end) +end) + +describe('clipboard (with fake clipboard.vim)', function() + local function reset(...) + clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...) + end + + before_each(function() + reset() + feed_command('call getreg("*")') -- force load of provider + end) + + it('`:redir @+>` invokes clipboard once-per-message', function() + eq(0, eval("g:clip_called_set")) + feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') + -- Assuming CONTRIBUTING.md has >100 lines. + assert(eval("g:clip_called_set") > 100) + end) + + it('`:redir @">` does NOT invoke clipboard', function() + -- :redir to a non-clipboard register, with `:set clipboard=unnamed` does + -- NOT propagate to the clipboard. This is consistent with Vim. + command("set clipboard=unnamedplus") + eq(0, eval("g:clip_called_set")) + feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END') + eq(0, eval("g:clip_called_set")) + end) + + it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184', + function() + local screen = Screen.new(72, 4) + screen:attach() + feed_command('redir @+> | bogus_cmd | redir END') + screen:expect([[ + ^ | + ~ | + ~ | + E492: Not an editor command: bogus_cmd | redir END | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('has independent "* and unnamed registers by default', function() + insert("some words") + feed('^"*dwdw"*P') + expect('some ') + eq({{'some '}, 'v'}, eval("g:test_clip['*']")) + eq('words', eval("getreg('\"', 1)")) + end) + + it('supports separate "* and "+ when the provider supports it', function() + insert([[ + text: + first line + secound line + third line]]) + + feed('G"+dd"*dddd"+p"*pp') + expect([[ + text: + third line + secound line + first line]]) + -- linewise selection should be encoded as an extra newline + eq({{'third line', ''}, 'V'}, eval("g:test_clip['+']")) + eq({{'secound line', ''}, 'V'}, eval("g:test_clip['*']")) + end) + + it('handles null bytes when pasting and in getreg', function() + insert("some\022000text\n\022000very binary\022000") + feed('"*y-+"*p') + eq({{'some\ntext', '\nvery binary\n',''}, 'V'}, eval("g:test_clip['*']")) + expect("some\00text\n\00very binary\00\nsome\00text\n\00very binary\00") + + -- test getreg/getregtype + eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1)")) + eq("V", eval("getregtype('*')")) + + -- getreg supports three arguments + eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1, 0)")) + eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)")) + end) + + it('autodetects regtype', function() + feed_command("let g:test_clip['*'] = ['linewise stuff','']") + feed_command("let g:test_clip['+'] = ['charwise','stuff']") + eq("V", eval("getregtype('*')")) + eq("v", eval("getregtype('+')")) + insert("just some text") + feed('"*p"+p') + expect([[ + just some text + lcharwise + stuffinewise stuff]]) + end) + + it('support blockwise operations', function() + insert([[ + much + text]]) + feed_command("let g:test_clip['*'] = [['very','block'],'b']") + feed('gg"*P') + expect([[ + very much + blocktext]]) + eq("\0225", eval("getregtype('*')")) + feed('gg4lj4l"+ygg"+P') + expect([[ + muchvery much + ktextblocktext]]) + eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']")) + end) + + it('supports setreg()', function() + feed_command('call setreg("*", "setted\\ntext", "c")') + feed_command('call setreg("+", "explicitly\\nlines", "l")') + feed('"+P"*p') + expect([[ + esetted + textxplicitly + lines + ]]) + feed_command('call setreg("+", "blocky\\nindeed", "b")') + feed('"+p') + expect([[ + esblockyetted + teindeedxtxplicitly + lines + ]]) + end) + + it('supports :let @+ (issue #1427)', function() + feed_command("let @+ = 'some'") + feed_command("let @* = ' other stuff'") + eq({{'some'}, 'v'}, eval("g:test_clip['+']")) + eq({{' other stuff'}, 'v'}, eval("g:test_clip['*']")) + feed('"+p"*p') + expect('some other stuff') + feed_command("let @+ .= ' more'") + feed('dd"+p') + expect('some more') + end) + + it('pastes unnamed register if the provider fails', function() + insert('the text') + feed('yy') + feed_command("let g:cliperror = 1") + feed('"*p') + expect([[ + the text + the text]]) + end) + + + describe('with clipboard=unnamed', function() + -- the basic behavior of unnamed register should be the same + -- even when handled by clipboard provider + before_each(function() + feed_command('set clipboard=unnamed') + end) + + it('works', function() + basic_register_test() + end) + + it('works with pure text clipboard', function() + feed_command("let g:cliplossy = 1") + -- expect failure for block mode + basic_register_test(true) + end) + + it('links the "* and unnamed registers', function() + -- with cb=unnamed, "* and unnamed will be the same register + insert("some words") + feed('^"*dwdw"*P') + expect('words') + eq({{'words'}, 'v'}, eval("g:test_clip['*']")) + + -- "+ shouldn't have changed + eq({''}, eval("g:test_clip['+']")) + + feed_command("let g:test_clip['*'] = ['linewise stuff','']") + feed('p') + expect([[ + words + linewise stuff]]) + end) + + it('does not clobber "0 when pasting', function() + insert('a line') + feed('yy') + feed_command("let g:test_clip['*'] = ['b line','']") + feed('"0pp"0p') + expect([[ + a line + a line + b line + a line]]) + end) + + it('supports v:register and getreg() without parameters', function() + eq('*', eval('v:register')) + feed_command("let g:test_clip['*'] = [['some block',''], 'b']") + eq('some block', eval('getreg()')) + eq('\02210', eval('getregtype()')) + end) + + it('yanks visual selection when pasting', function() + insert("indeed visual") + feed_command("let g:test_clip['*'] = [['clipboard'], 'c']") + feed("viwp") + eq({{'visual'}, 'v'}, eval("g:test_clip['*']")) + expect("indeed clipboard") + + -- explicit "* should do the same + feed_command("let g:test_clip['*'] = [['star'], 'c']") + feed('viw"*p') + eq({{'clipboard'}, 'v'}, eval("g:test_clip['*']")) + expect("indeed star") + end) + + it('unamed operations work even if the provider fails', function() + insert('the text') + feed('yy') + feed_command("let g:cliperror = 1") + feed('p') + expect([[ + the text + the text]]) + end) + + it('is updated on global changes', function() + insert([[ + text + match + match + text + ]]) + feed_command('g/match/d') + eq('match\n', eval('getreg("*")')) + feed('u') + eval('setreg("*", "---")') + feed_command('g/test/') + feed('') + eq('---', eval('getreg("*")')) + end) + + it('works in the cmdline window', function() + feed('q:itextyy') + eq({{'text', ''}, 'V'}, eval("g:test_clip['*']")) + command("let g:test_clip['*'] = [['star'], 'c']") + feed('p') + eq('textstar', meths.get_current_line()) + end) + end) + + describe('clipboard=unnamedplus', function() + before_each(function() + feed_command('set clipboard=unnamedplus') + end) + + it('links the "+ and unnamed registers', function() + eq('+', eval('v:register')) + insert("one two") + feed('^"+dwdw"+P') + expect('two') + eq({{'two'}, 'v'}, eval("g:test_clip['+']")) + + -- "* shouldn't have changed + eq({''}, eval("g:test_clip['*']")) + + feed_command("let g:test_clip['+'] = ['three']") + feed('p') + expect('twothree') + end) + + it('and unnamed, yanks to both', function() + feed_command('set clipboard=unnamedplus,unnamed') + insert([[ + really unnamed + text]]) + feed('ggdd"*p"+p') + expect([[ + text + really unnamed + really unnamed]]) + eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['+']")) + eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['*']")) + + -- unnamedplus takes predecence when pasting + eq('+', eval('v:register')) + feed_command("let g:test_clip['+'] = ['the plus','']") + feed_command("let g:test_clip['*'] = ['the star','']") + feed("p") + expect([[ + text + really unnamed + really unnamed + the plus]]) + end) + + it('is updated on global changes', function() + insert([[ + text + match + match + text + ]]) + feed_command('g/match/d') + eq('match\n', eval('getreg("+")')) + feed('u') + eval('setreg("+", "---")') + feed_command('g/test/') + feed('') + eq('---', eval('getreg("+")')) + end) + end) + + it('sets v:register after startup', function() + reset() + eq('"', eval('v:register')) + reset('--cmd', 'set clipboard=unnamed') + eq('*', eval('v:register')) + end) + + it('supports :put', function() + insert("a line") + feed_command("let g:test_clip['*'] = ['some text']") + feed_command("let g:test_clip['+'] = ['more', 'text', '']") + feed_command(":put *") + expect([[ + a line + some text]]) + feed_command(":put +") + expect([[ + a line + some text + more + text]]) + end) + + it('supports "+ and "* in registers', function() + local screen = Screen.new(60, 10) + screen:attach() + feed_command("let g:test_clip['*'] = ['some', 'star data','']") + feed_command("let g:test_clip['+'] = ['such', 'plus', 'stuff']") + feed_command("registers") + screen:expect([[ + | + {0:~ }| + {0:~ }| + {4: }| + :registers | + {1:--- Registers ---} | + "* some{2:^J}star data{2:^J} | + "+ such{2:^J}plus{2:^J}stuff | + ": let g:test_clip['+'] = ['such', 'plus', 'stuff'] | + {3:Press ENTER or type command to continue}^ | + ]], { + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {bold = true, foreground = Screen.colors.Fuchsia}, + [2] = {foreground = Screen.colors.Blue}, + [3] = {bold = true, foreground = Screen.colors.SeaGreen}, + [4] = {bold = true, reverse = true}}) + feed('') -- clear out of Press ENTER screen + end) + + it('can paste "* to the commandline', function() + insert('s/s/t/') + feed('gg"*y$:*') + expect('t/s/t/') + feed_command("let g:test_clip['*'] = ['s/s/u']") + feed(':*') + expect('t/u/t/') + end) + + it('supports :redir @*>', function() + feed_command("let g:test_clip['*'] = ['stuff']") + feed_command('redir @*>') + -- it is made empty + eq({{''}, 'v'}, eval("g:test_clip['*']")) + feed_command('let g:test = doesnotexist') + feed('') + eq({{ + '', + '', + 'E121: Undefined variable: doesnotexist', + 'E15: Invalid expression: doesnotexist', + }, 'v'}, eval("g:test_clip['*']")) + feed_command(':echo "Howdy!"') + eq({{ + '', + '', + 'E121: Undefined variable: doesnotexist', + 'E15: Invalid expression: doesnotexist', + '', + 'Howdy!', + }, 'v'}, eval("g:test_clip['*']")) + end) + + it('handles middleclick correctly', function() + feed_command('set mouse=a') + + local screen = Screen.new(30, 5) + screen:attach() + insert([[ + the source + a target]]) + feed('gg"*ywwyw') + -- clicking depends on the exact visual layout, so expect it: + screen:expect([[ + the ^source | + a target | + ~ | + ~ | + | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + + feed('<0,1>') + expect([[ + the source + the a target]]) + + -- on error, fall back to unnamed register + feed_command("let g:cliperror = 1") + feed('<6,1>') + expect([[ + the source + the a sourcetarget]]) + end) + + it('setreg("*") with clipboard=unnamed #5646', function() + source([=[ + function! Paste_without_yank(direction) range + let [reg_save,regtype_save] = [getreg('*'), getregtype('*')] + normal! gvp + call setreg('*', reg_save, regtype_save) + endfunction + xnoremap p :call Paste_without_yank('p') + set clipboard=unnamed + ]=]) + insert('some words') + feed('gg0yiw') + feed('wviwp') + expect('some some') + eq('some', eval('getreg("*")')) + end) +end) diff --git a/test/functional/spell/spellfile_spec.lua b/test/functional/spell/spellfile_spec.lua deleted file mode 100644 index afd2c1bce4..0000000000 --- a/test/functional/spell/spellfile_spec.lua +++ /dev/null @@ -1,110 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local lfs = require('lfs') - -local eq = helpers.eq -local clear = helpers.clear -local meths = helpers.meths -local exc_exec = helpers.exc_exec -local rmdir = helpers.rmdir -local write_file = helpers.write_file - -local testdir = 'Xtest-functional-spell-spellfile.d' - -describe('spellfile', function() - before_each(function() - clear() - rmdir(testdir) - lfs.mkdir(testdir) - lfs.mkdir(testdir .. '/spell') - end) - after_each(function() - rmdir(testdir) - end) - -- ┌ Magic string (#VIMSPELLMAGIC) - -- │ ┌ Spell file version (#VIMSPELLVERSION) - local spellheader = 'VIMspell\050' - it('errors out when prefcond section is truncated', function() - meths.set_option('runtimepath', testdir) - write_file(testdir .. '/spell/en.ascii.spl', - -- ┌ Section identifier (#SN_PREFCOND) - -- │ ┌ Section flags (#SNF_REQUIRED or zero) - -- │ │ ┌ Section length (4 bytes, MSB first) - spellheader .. '\003\001\000\000\000\003' - -- ┌ Number of regexes in section (2 bytes, MSB first) - -- │ ┌ Condition length (1 byte) - -- │ │ ┌ Condition regex (missing!) - .. '\000\001\001') - meths.set_option('spelllang', 'en') - eq('Vim(set):E758: Truncated spell file', - exc_exec('set spell')) - end) - it('errors out when prefcond regexp contains NUL byte', function() - meths.set_option('runtimepath', testdir) - write_file(testdir .. '/spell/en.ascii.spl', - -- ┌ Section identifier (#SN_PREFCOND) - -- │ ┌ Section flags (#SNF_REQUIRED or zero) - -- │ │ ┌ Section length (4 bytes, MSB first) - spellheader .. '\003\001\000\000\000\008' - -- ┌ Number of regexes in section (2 bytes, MSB first) - -- │ ┌ Condition length (1 byte) - -- │ │ ┌ Condition regex - -- │ │ │ ┌ End of sections marker - .. '\000\001\005ab\000cd\255' - -- ┌ LWORDTREE tree length (4 bytes) - -- │ ┌ KWORDTREE tree length (4 bytes) - -- │ │ ┌ PREFIXTREE tree length - .. '\000\000\000\000\000\000\000\000\000\000\000\000') - meths.set_option('spelllang', 'en') - eq('Vim(set):E759: Format error in spell file', - exc_exec('set spell')) - end) - it('errors out when region contains NUL byte', function() - meths.set_option('runtimepath', testdir) - write_file(testdir .. '/spell/en.ascii.spl', - -- ┌ Section identifier (#SN_REGION) - -- │ ┌ Section flags (#SNF_REQUIRED or zero) - -- │ │ ┌ Section length (4 bytes, MSB first) - spellheader .. '\000\001\000\000\000\008' - -- ┌ Regions ┌ End of sections marker - .. '01234\00067\255' - -- ┌ LWORDTREE tree length (4 bytes) - -- │ ┌ KWORDTREE tree length (4 bytes) - -- │ │ ┌ PREFIXTREE tree length - .. '\000\000\000\000\000\000\000\000\000\000\000\000') - meths.set_option('spelllang', 'en') - eq('Vim(set):E759: Format error in spell file', - exc_exec('set spell')) - end) - it('errors out when SAL section contains NUL byte', function() - meths.set_option('runtimepath', testdir) - write_file(testdir .. '/spell/en.ascii.spl', - -- ┌ Section identifier (#SN_SAL) - -- │ ┌ Section flags (#SNF_REQUIRED or zero) - -- │ │ ┌ Section length (4 bytes, MSB first) - spellheader .. '\005\001\000\000\000\008' - -- ┌ salflags - -- │ ┌ salcount (2 bytes, MSB first) - -- │ │ ┌ salfromlen (1 byte) - -- │ │ │ ┌ Special character - -- │ │ │ │┌ salfrom (should not contain NUL) - -- │ │ │ ││ ┌ saltolen - -- │ │ │ ││ │ ┌ salto - -- │ │ │ ││ │ │┌ End of sections marker - .. '\000\000\001\0024\000\0017\255' - -- ┌ LWORDTREE tree length (4 bytes) - -- │ ┌ KWORDTREE tree length (4 bytes) - -- │ │ ┌ PREFIXTREE tree length - .. '\000\000\000\000\000\000\000\000\000\000\000\000') - meths.set_option('spelllang', 'en') - eq('Vim(set):E759: Format error in spell file', - exc_exec('set spell')) - end) - it('errors out when spell header contains NUL bytes', function() - meths.set_option('runtimepath', testdir) - write_file(testdir .. '/spell/en.ascii.spl', - spellheader:sub(1, -3) .. '\000\000') - meths.set_option('spelllang', 'en') - eq('Vim(set):E757: This does not look like a spell file', - exc_exec('set spell')) - end) -end) -- cgit