output_spec.lua (10508B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 local tt = require('test.functional.testterm') 5 6 local assert_alive = n.assert_alive 7 local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir 8 local eq = t.eq 9 local feed = n.feed 10 local feed_command = n.feed_command 11 local clear = n.clear 12 local command = n.command 13 local testprg = n.testprg 14 local nvim_dir = n.nvim_dir 15 local has_powershell = n.has_powershell 16 local set_shell_powershell = n.set_shell_powershell 17 local skip = t.skip 18 local is_os = t.is_os 19 20 clear() -- for has_powershell() 21 22 describe('shell command :!', function() 23 local screen 24 before_each(function() 25 clear() 26 screen = tt.setup_child_nvim({ 27 '-u', 28 'NONE', 29 '-i', 30 'NONE', 31 '--cmd', 32 'colorscheme vim', 33 '--cmd', 34 n.nvim_set .. ' notermguicolors', 35 }) 36 screen:expect([[ 37 ^ | 38 {100:~ }|*4 39 | 40 {5:-- TERMINAL --} | 41 ]]) 42 end) 43 44 it('displays output without LF/EOF. #4646 #4569 #3772', function() 45 skip(is_os('win')) 46 -- NOTE: We use a child nvim (within a :term buffer) 47 -- to avoid triggering a UI flush. 48 tt.feed_data(':!printf foo; sleep 200\n') 49 screen:expect([[ 50 | 51 {100:~ }|*2 52 {3: }| 53 :!printf foo; sleep 200 | 54 foo | 55 {5:-- TERMINAL --} | 56 ]]) 57 tt.feed_data('\3') -- Ctrl-C 58 screen:expect([[ 59 ^ | 60 {100:~ }|*4 61 | 62 {5:-- TERMINAL --} | 63 ]]) 64 end) 65 66 it('throttles shell-command output greater than ~10KB', function() 67 skip(is_os('openbsd'), 'FIXME #10804') 68 skip(is_os('win')) 69 tt.feed_data((':!%s REP 30001 foo\n'):format(testprg('shell-test'))) 70 71 -- If we observe any line starting with a dot, then throttling occurred. 72 -- Avoid false failure on slow systems. 73 screen:expect { any = '\n%.', timeout = 20000 } 74 75 -- Final chunk of output should always be displayed, never skipped. 76 -- (Throttling is non-deterministic, this test is merely a sanity check.) 77 screen:expect([[ 78 29997: foo | 79 29998: foo | 80 29999: foo | 81 30000: foo | 82 | 83 {123:Press ENTER or type command to continue}^ | 84 {5:-- TERMINAL --} | 85 ]]) 86 end) 87 end) 88 89 describe('shell command :!', function() 90 before_each(function() 91 clear() 92 end) 93 94 it('cat a binary file #4142', function() 95 feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>") 96 assert_alive() 97 end) 98 99 it([[display \x08 char #4142]], function() 100 feed(':silent !echo \08<CR>') 101 assert_alive() 102 end) 103 104 it('handles control codes', function() 105 skip(is_os('win'), 'missing printf') 106 local screen = Screen.new(50, 4) 107 -- Print TAB chars. #2958 108 feed([[:!printf '1\t2\t3'<CR>]]) 109 screen:expect([[ 110 {3: }| 111 :!printf '1\t2\t3' | 112 1 2 3 | 113 {6:Press ENTER or type command to continue}^ | 114 ]]) 115 feed([[<CR>]]) 116 117 -- Print BELL control code. #4338 118 screen.bell = false 119 feed([[:!printf '\007\007\007\007text'<CR>]]) 120 screen:expect { 121 grid = [[ 122 {3: }| 123 :!printf '\007\007\007\007text' | 124 text | 125 {6:Press ENTER or type command to continue}^ | 126 ]], 127 condition = function() 128 eq(true, screen.bell) 129 end, 130 } 131 feed([[<CR>]]) 132 133 -- Print BS control code. 134 feed([[:echo system('printf ''\010\n''')<CR>]]) 135 screen:expect([[ 136 {3: }| 137 {18:^H} | 138 | 139 {6:Press ENTER or type command to continue}^ | 140 ]]) 141 feed([[<CR>]]) 142 143 -- Print LF control code. 144 feed([[:!printf '\n'<CR>]]) 145 screen:expect([[ 146 :!printf '\n' | 147 |*2 148 {6:Press ENTER or type command to continue}^ | 149 ]]) 150 feed([[<CR>]]) 151 end) 152 153 describe('', function() 154 local screen 155 before_each(function() 156 rmdir('bang_filter_spec') 157 mkdir('bang_filter_spec') 158 write_file('bang_filter_spec/f1', 'f1') 159 write_file('bang_filter_spec/f2', 'f2') 160 write_file('bang_filter_spec/f3', 'f3') 161 screen = Screen.new(53, 10) 162 end) 163 164 after_each(function() 165 rmdir('bang_filter_spec') 166 end) 167 168 it("doesn't truncate Last line of shell output #3269", function() 169 command( 170 is_os('win') and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]] 171 or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]] 172 ) 173 local result = ( 174 is_os('win') and [[:!dir /b bang_filter_spec]] or [[:!ls bang_filter_spec ]] 175 ) 176 feed([[\l]]) 177 screen:expect([[ 178 | 179 {1:~ }|*2 180 {3: }| 181 ]] .. result .. [[ | 182 f1 | 183 f2 | 184 f3 | 185 | 186 {6:Press ENTER or type command to continue}^ | 187 ]]) 188 end) 189 190 it('handles binary and multibyte data', function() 191 feed_command('!cat test/functional/fixtures/shell_data.txt') 192 screen.bell = false 193 screen:expect { 194 grid = [[ 195 | 196 {1:~ }| 197 {3: }| 198 :!cat test/functional/fixtures/shell_data.txt | 199 ^@^A^B^C^D^E^F^H | 200 ^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_ | 201 ö 한글 <a5><c3> | 202 t <ff> | 203 | 204 {6:Press ENTER or type command to continue}^ | 205 ]], 206 condition = function() 207 eq(true, screen.bell) 208 end, 209 } 210 end) 211 212 it('handles multibyte sequences split over buffer boundaries', function() 213 command('cd ' .. nvim_dir) 214 local cmd = is_os('win') and '!shell-test UTF-8 ' or '!./shell-test UTF-8' 215 feed_command(cmd) 216 -- Note: only the first example of split composed char works 217 screen:expect([[ 218 | 219 {3: }| 220 :]] .. cmd .. [[ | 221 å | 222 ref: å̲ | 223 1: å̲ | 224 2: å ̲ | 225 3: å ̲ | 226 | 227 {6:Press ENTER or type command to continue}^ | 228 ]]) 229 end) 230 end) 231 if has_powershell() then 232 it('powershell supports literal strings', function() 233 set_shell_powershell() 234 local screen = Screen.new(45, 4) 235 feed_command([[!'Write-Output $a']]) 236 screen:expect([[ 237 :!'Write-Output $a' | 238 Write-Output $a | 239 | 240 {6:Press ENTER or type command to continue}^ | 241 ]]) 242 feed_command([[!$a = 1; Write-Output '$a']]) 243 screen:expect([[ 244 :!$a = 1; Write-Output '$a' | 245 $a | 246 | 247 {6:Press ENTER or type command to continue}^ | 248 ]]) 249 feed_command([[!"Write-Output $a"]]) 250 screen:expect([[ 251 :!"Write-Output $a" | 252 Write-Output | 253 | 254 {6:Press ENTER or type command to continue}^ | 255 ]]) 256 feed_command([[!$a = 1; Write-Output "$a"]]) 257 screen:expect([[ 258 :!$a = 1; Write-Output "$a" | 259 1 | 260 | 261 {6:Press ENTER or type command to continue}^ | 262 ]]) 263 if is_os('win') then 264 feed_command([[!& 'cmd.exe' /c 'echo $a']]) 265 screen:expect([[ 266 :!& 'cmd.exe' /c 'echo $a' | 267 $a | 268 | 269 {6:Press ENTER or type command to continue}^ | 270 ]]) 271 else 272 feed_command([[!& '/bin/sh' -c 'echo ''$a''']]) 273 screen:expect([[ 274 :!& '/bin/sh' -c 'echo ''$a''' | 275 $a | 276 | 277 {6:Press ENTER or type command to continue}^ | 278 ]]) 279 end 280 end) 281 end 282 end)