overrides_spec.lua (12783B)
1 -- Test for Vim overrides of lua built-ins 2 local t = require('test.testutil') 3 local n = require('test.functional.testnvim')() 4 local Screen = require('test.functional.ui.screen') 5 6 local eq = t.eq 7 local NIL = vim.NIL 8 local feed = n.feed 9 local clear = n.clear 10 local fn = n.fn 11 local api = n.api 12 local command = n.command 13 local write_file = t.write_file 14 local exec_capture = n.exec_capture 15 local exec_lua = n.exec_lua 16 local pcall_err = t.pcall_err 17 local is_os = t.is_os 18 19 local fname = 'Xtest-functional-lua-overrides-luafile' 20 21 before_each(clear) 22 23 after_each(function() 24 os.remove(fname) 25 end) 26 27 describe('print', function() 28 it('returns nothing', function() 29 eq(NIL, fn.luaeval('print("abc")')) 30 eq(0, fn.luaeval('select("#", print("abc"))')) 31 end) 32 it('allows catching printed text with :execute', function() 33 eq('\nabc', fn.execute('lua print("abc")')) 34 eq('\nabc', fn.execute('luado print("abc")')) 35 eq('\nabc', fn.execute('call luaeval("print(\'abc\')")')) 36 write_file(fname, 'print("abc")') 37 eq('\nabc', fn.execute('luafile ' .. fname)) 38 39 eq('abc', exec_capture('lua print("abc")')) 40 eq('abc', exec_capture('luado print("abc")')) 41 eq('abc', exec_capture('call luaeval("print(\'abc\')")')) 42 write_file(fname, 'print("abc")') 43 eq('abc', exec_capture('luafile ' .. fname)) 44 end) 45 it('handles errors in __tostring', function() 46 write_file( 47 fname, 48 [[ 49 local meta_nilerr = { __tostring = function() error(nil) end } 50 local meta_abcerr = { __tostring = function() error("abc") end } 51 local meta_tblout = { __tostring = function() return {"TEST"} end } 52 v_nilerr = setmetatable({}, meta_nilerr) 53 v_abcerr = setmetatable({}, meta_abcerr) 54 v_tblout = setmetatable({}, meta_tblout) 55 ]] 56 ) 57 eq('', exec_capture('luafile ' .. fname)) 58 -- TODO(bfredl): these look weird, print() should not use "E5114:" style errors.. 59 eq( 60 'Vim(lua):E5108: Lua: E5114: Converting print argument #2: [NULL]', 61 pcall_err(command, 'lua print("foo", v_nilerr, "bar")') 62 ) 63 eq( 64 'Vim(lua):E5108: Lua: E5114: Converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc', 65 pcall_err(command, 'lua print("foo", v_abcerr, "bar")') 66 ) 67 eq( 68 'Vim(lua):E5108: Lua: E5114: Converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>', 69 pcall_err(command, 'lua print("foo", v_tblout, "bar")') 70 ) 71 end) 72 it('coerces error values into strings', function() 73 write_file( 74 fname, 75 [[ 76 function string_error() error("my mistake") end 77 function number_error() error(1234) end 78 function nil_error() error(nil) end 79 function table_error() error({message = "my mistake"}) end 80 function custom_error() 81 local err = {message = "my mistake", code = 11234} 82 setmetatable(err, { 83 __tostring = function(t) 84 return "Internal Error [" .. t.code .. "] " .. t.message 85 end 86 }) 87 error(err) 88 end 89 function bad_custom_error() 90 local err = {message = "my mistake", code = 11234} 91 setmetatable(err, { 92 -- intentionally not a function, downstream programmer has made an mistake 93 __tostring = "Internal Error [" .. err.code .. "] " .. err.message 94 }) 95 error(err) 96 end 97 ]] 98 ) 99 eq('', exec_capture('luafile ' .. fname)) 100 eq( 101 'Vim(lua):E5108: Lua: Xtest-functional-lua-overrides-luafile:1: my mistake', 102 pcall_err(command, 'lua string_error()') 103 ) 104 eq( 105 'Vim(lua):E5108: Lua: Xtest-functional-lua-overrides-luafile:2: 1234', 106 pcall_err(command, 'lua number_error()') 107 ) 108 eq('Vim(lua):E5108: Lua: [NULL]', pcall_err(command, 'lua nil_error()')) 109 eq('Vim(lua):E5108: Lua: [NULL]', pcall_err(command, 'lua table_error()')) 110 eq( 111 'Vim(lua):E5108: Lua: Internal Error [11234] my mistake', 112 pcall_err(command, 'lua custom_error()') 113 ) 114 eq('Vim(lua):E5108: Lua: [NULL]', pcall_err(command, 'lua bad_custom_error()')) 115 end) 116 it('prints strings with NULs and NLs correctly', function() 117 api.nvim_set_option_value('more', true, {}) 118 eq( 119 'abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n', 120 exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]) 121 ) 122 eq( 123 'abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@', 124 exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]) 125 ) 126 eq('T^@', exec_capture([[lua print("T\0")]])) 127 eq('T\n', exec_capture([[lua print("T\n")]])) 128 end) 129 it('prints empty strings correctly', function() 130 -- Regression: first test used to crash 131 eq('', exec_capture('lua print("")')) 132 eq(' def', exec_capture('lua print("", "def")')) 133 eq('abc ', exec_capture('lua print("abc", "")')) 134 eq('abc def', exec_capture('lua print("abc", "", "def")')) 135 end) 136 it('defers printing in luv event handlers', function() 137 exec_lua(function(cmd) 138 function test() 139 local timer = vim.uv.new_timer() 140 local done = false 141 timer:start(10, 0, function() 142 print('very fast') 143 timer:close() 144 done = true 145 end) 146 -- be kind to slow travis OS X jobs: 147 -- loop until we know for sure the callback has been executed 148 while not done do 149 os.execute(cmd) 150 vim.uv.run('nowait') -- fake os_breakcheck() 151 end 152 print('very slow') 153 vim.api.nvim_command('sleep 1m') -- force deferred event processing 154 end 155 end, (is_os('win') and 'timeout 1') or 'sleep 0.1') 156 eq('very slow\nvery fast', exec_capture('lua test()')) 157 end) 158 159 it('blank line in message works', function() 160 local screen = Screen.new(40, 8) 161 screen:set_default_attr_ids({ 162 [0] = { bold = true, foreground = Screen.colors.Blue }, 163 [1] = { bold = true, foreground = Screen.colors.SeaGreen }, 164 [2] = { bold = true, reverse = true }, 165 }) 166 feed([[:lua print('\na')<CR>]]) 167 screen:expect { 168 grid = [[ 169 | 170 {0:~ }|*3 171 {2: }| 172 | 173 a | 174 {1:Press ENTER or type command to continue}^ | 175 ]], 176 } 177 feed('<CR>') 178 feed([[:lua print('b\n\nc')<CR>]]) 179 screen:expect { 180 grid = [[ 181 | 182 {0:~ }|*2 183 {2: }| 184 b | 185 | 186 c | 187 {1:Press ENTER or type command to continue}^ | 188 ]], 189 } 190 end) 191 end) 192 193 describe('debug.debug', function() 194 local screen --- @type test.functional.ui.screen 195 196 before_each(function() 197 screen = Screen.new() 198 screen:set_default_attr_ids { 199 [0] = { bold = true, foreground = 255 }, 200 [1] = { bold = true, reverse = true }, 201 E = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, 202 cr = { bold = true, foreground = Screen.colors.SeaGreen4 }, 203 } 204 end) 205 206 it('works', function() 207 command([[lua 208 function Test(a) 209 print(a) 210 debug.debug() 211 print(a * 100) 212 end 213 ]]) 214 feed(':lua Test()\n') 215 screen:expect { 216 grid = [[ 217 | 218 {0:~ }|*10 219 {1: }| 220 nil | 221 lua_debug> ^ | 222 ]], 223 } 224 feed('print("TEST")\n') 225 screen:expect([[ 226 | 227 {0:~ }|*8 228 {1: }| 229 nil | 230 lua_debug> print("TEST") | 231 TEST | 232 lua_debug> ^ | 233 ]]) 234 feed('<C-c>') 235 screen:expect([[ 236 | 237 {0:~ }|*2 238 {1: }| 239 nil | 240 lua_debug> print("TEST") | 241 TEST | 242 | 243 {E:E5108: Lua: [string ":lua"]:5: attempt to perform ari}| 244 {E:thmetic on local 'a' (a nil value)} | 245 {E:stack traceback:} | 246 {E: [string ":lua"]:5: in function 'Test'} | 247 {E: [string ":lua"]:1: in main chunk} | 248 Interrupt: {cr:Press ENTER or type command to continue}^ | 249 ]]) 250 feed('<C-l>:lua Test()\n') 251 screen:expect([[ 252 | 253 {0:~ }|*10 254 {1: }| 255 nil | 256 lua_debug> ^ | 257 ]]) 258 feed('\n') 259 screen:expect([[ 260 | 261 {0:~ }|*4 262 {1: }| 263 nil | 264 lua_debug> | 265 {E:E5108: Lua: [string ":lua"]:5: attempt to perform ari}| 266 {E:thmetic on local 'a' (a nil value)} | 267 {E:stack traceback:} | 268 {E: [string ":lua"]:5: in function 'Test'} | 269 {E: [string ":lua"]:1: in main chunk} | 270 {cr:Press ENTER or type command to continue}^ | 271 ]]) 272 end) 273 274 it("can be safely exited with 'cont'", function() 275 feed('<cr>') 276 feed(':lua debug.debug() print("x")<cr>') 277 screen:expect { 278 grid = [[ 279 | 280 {0:~ }|*12 281 lua_debug> ^ | 282 ]], 283 } 284 285 feed('conttt<cr>') -- misspelled cont; invalid syntax 286 screen:expect([[ 287 | 288 {0:~ }|*8 289 {1: }| 290 lua_debug> conttt | 291 {E:E5115: Loading Lua debug string: (debug command):1: '}| 292 {E:=' expected near '<eof>'} | 293 lua_debug> ^ | 294 ]]) 295 296 feed('cont<cr>') -- exactly "cont", exit now 297 screen:expect([[ 298 | 299 {0:~ }|*6 300 {1: }| 301 lua_debug> conttt | 302 {E:E5115: Loading Lua debug string: (debug command):1: '}| 303 {E:=' expected near '<eof>'} | 304 lua_debug> cont | 305 x | 306 {cr:Press ENTER or type command to continue}^ | 307 ]]) 308 309 feed('<cr>') 310 screen:expect { 311 grid = [[ 312 ^ | 313 {0:~ }|*12 314 | 315 ]], 316 } 317 end) 318 end) 319 320 describe('os.getenv', function() 321 it('returns nothing for undefined env var', function() 322 eq(NIL, fn.luaeval('os.getenv("XTEST_1")')) 323 end) 324 it('returns env var set by the parent process', function() 325 local value = 'foo' 326 clear({ env = { ['XTEST_1'] = value } }) 327 eq(value, fn.luaeval('os.getenv("XTEST_1")')) 328 end) 329 it('returns env var set by let', function() 330 local value = 'foo' 331 command('let $XTEST_1 = "' .. value .. '"') 332 eq(value, fn.luaeval('os.getenv("XTEST_1")')) 333 end) 334 end) 335 336 -- "bit" module is always available, regardless if nvim is built with 337 -- luajit or PUC lua 5.1. 338 describe('bit module', function() 339 it('works', function() 340 eq(9, exec_lua [[ return require'bit'.band(11,13) ]]) 341 end) 342 end)