1" Tests for the terminal window.
2
3if !has('terminal')
4  finish
5endif
6
7source shared.vim
8source screendump.vim
9
10let s:python = PythonProg()
11
12" Open a terminal with a shell, assign the job to g:job and return the buffer
13" number.
14func Run_shell_in_terminal(options)
15  if has('win32')
16    let buf = term_start([&shell,'/k'], a:options)
17  else
18    let buf = term_start(&shell, a:options)
19  endif
20
21  let termlist = term_list()
22  call assert_equal(1, len(termlist))
23  call assert_equal(buf, termlist[0])
24
25  let g:job = term_getjob(buf)
26  call assert_equal(v:t_job, type(g:job))
27
28  let string = string({'job': term_getjob(buf)})
29  call assert_match("{'job': 'process \\d\\+ run'}", string)
30
31  return buf
32endfunc
33
34func Test_terminal_basic()
35  au TerminalOpen * let b:done = 'yes'
36  let buf = Run_shell_in_terminal({})
37
38  if has("unix")
39    call assert_match('^/dev/', job_info(g:job).tty_out)
40    call assert_match('^/dev/', term_gettty(''))
41  else
42    call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
43    call assert_match('^\\\\.\\pipe\\', term_gettty(''))
44  endif
45  call assert_equal('t', mode())
46  call assert_equal('yes', b:done)
47  call assert_match('%aR[^\n]*running]', execute('ls'))
48  call assert_match('%aR[^\n]*running]', execute('ls R'))
49  call assert_notmatch('%[^\n]*running]', execute('ls F'))
50  call assert_notmatch('%[^\n]*running]', execute('ls ?'))
51
52  call Stop_shell_in_terminal(buf)
53  call term_wait(buf)
54  call assert_equal('n', mode())
55  call assert_match('%aF[^\n]*finished]', execute('ls'))
56  call assert_match('%aF[^\n]*finished]', execute('ls F'))
57  call assert_notmatch('%[^\n]*finished]', execute('ls R'))
58  call assert_notmatch('%[^\n]*finished]', execute('ls ?'))
59
60  " closing window wipes out the terminal buffer a with finished job
61  close
62  call assert_equal("", bufname(buf))
63
64  au! TerminalOpen
65  unlet g:job
66endfunc
67
68func Test_terminal_make_change()
69  let buf = Run_shell_in_terminal({})
70  call Stop_shell_in_terminal(buf)
71  call term_wait(buf)
72
73  setlocal modifiable
74  exe "normal Axxx\<Esc>"
75  call assert_fails(buf . 'bwipe', 'E517')
76  undo
77
78  exe buf . 'bwipe'
79  unlet g:job
80endfunc
81
82func Test_terminal_wipe_buffer()
83  let buf = Run_shell_in_terminal({})
84  call assert_fails(buf . 'bwipe', 'E517')
85  exe buf . 'bwipe!'
86  call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
87  call assert_equal("", bufname(buf))
88
89  unlet g:job
90endfunc
91
92func Test_terminal_split_quit()
93  let buf = Run_shell_in_terminal({})
94  call term_wait(buf)
95  split
96  quit!
97  call term_wait(buf)
98  sleep 50m
99  call assert_equal('run', job_status(g:job))
100
101  quit!
102  call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
103
104  exe buf . 'bwipe'
105  unlet g:job
106endfunc
107
108func Test_terminal_hide_buffer()
109  let buf = Run_shell_in_terminal({})
110  setlocal bufhidden=hide
111  quit
112  for nr in range(1, winnr('$'))
113    call assert_notequal(winbufnr(nr), buf)
114  endfor
115  call assert_true(bufloaded(buf))
116  call assert_true(buflisted(buf))
117
118  exe 'split ' . buf . 'buf'
119  call Stop_shell_in_terminal(buf)
120  exe buf . 'bwipe'
121
122  unlet g:job
123endfunc
124
125func! s:Nasty_exit_cb(job, st)
126  exe g:buf . 'bwipe!'
127  let g:buf = 0
128endfunc
129
130func Get_cat_123_cmd()
131  if has('win32')
132    return 'cmd /c "cls && color 2 && echo 123"'
133  else
134    call writefile(["\<Esc>[32m123"], 'Xtext')
135    return "cat Xtext"
136  endif
137endfunc
138
139func Test_terminal_nasty_cb()
140  let cmd = Get_cat_123_cmd()
141  let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')})
142  let g:job = term_getjob(g:buf)
143
144  call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
145  call WaitForAssert({-> assert_equal(0, g:buf)})
146  unlet g:buf
147  unlet g:job
148  call delete('Xtext')
149endfunc
150
151func Check_123(buf)
152  let l = term_scrape(a:buf, 0)
153  call assert_true(len(l) == 0)
154  let l = term_scrape(a:buf, 999)
155  call assert_true(len(l) == 0)
156  let l = term_scrape(a:buf, 1)
157  call assert_true(len(l) > 0)
158  call assert_equal('1', l[0].chars)
159  call assert_equal('2', l[1].chars)
160  call assert_equal('3', l[2].chars)
161  call assert_equal('#00e000', l[0].fg)
162  if &background == 'light'
163    call assert_equal('#ffffff', l[0].bg)
164  else
165    call assert_equal('#000000', l[0].bg)
166  endif
167
168  let l = term_getline(a:buf, -1)
169  call assert_equal('', l)
170  let l = term_getline(a:buf, 0)
171  call assert_equal('', l)
172  let l = term_getline(a:buf, 999)
173  call assert_equal('', l)
174  let l = term_getline(a:buf, 1)
175  call assert_equal('123', l)
176endfunc
177
178func Test_terminal_scrape_123()
179  let cmd = Get_cat_123_cmd()
180  let buf = term_start(cmd)
181
182  let termlist = term_list()
183  call assert_equal(1, len(termlist))
184  call assert_equal(buf, termlist[0])
185
186  " Nothing happens with invalid buffer number
187  call term_wait(1234)
188
189  call term_wait(buf)
190  " On MS-Windows we first get a startup message of two lines, wait for the
191  " "cls" to happen, after that we have one line with three characters.
192  call WaitForAssert({-> assert_equal(3, len(term_scrape(buf, 1)))})
193  call Check_123(buf)
194
195  " Must still work after the job ended.
196  let job = term_getjob(buf)
197  call WaitForAssert({-> assert_equal("dead", job_status(job))})
198  call term_wait(buf)
199  call Check_123(buf)
200
201  exe buf . 'bwipe'
202  call delete('Xtext')
203endfunc
204
205func Test_terminal_scrape_multibyte()
206  if !has('multi_byte')
207    return
208  endif
209  call writefile(["léttまrs"], 'Xtext')
210  if has('win32')
211    " Run cmd with UTF-8 codepage to make the type command print the expected
212    " multibyte characters.
213    let buf = term_start("cmd /K chcp 65001")
214    call term_sendkeys(buf, "type Xtext\<CR>")
215    call term_sendkeys(buf, "exit\<CR>")
216    let line = 4
217  else
218    let buf = term_start("cat Xtext")
219    let line = 1
220  endif
221
222  call WaitFor({-> len(term_scrape(buf, line)) >= 7 && term_scrape(buf, line)[0].chars == "l"})
223  let l = term_scrape(buf, line)
224  call assert_true(len(l) >= 7)
225  call assert_equal('l', l[0].chars)
226  call assert_equal('é', l[1].chars)
227  call assert_equal(1, l[1].width)
228  call assert_equal('t', l[2].chars)
229  call assert_equal('t', l[3].chars)
230  call assert_equal('ま', l[4].chars)
231  call assert_equal(2, l[4].width)
232  call assert_equal('r', l[5].chars)
233  call assert_equal('s', l[6].chars)
234
235  let job = term_getjob(buf)
236  call WaitForAssert({-> assert_equal("dead", job_status(job))})
237  call term_wait(buf)
238
239  exe buf . 'bwipe'
240  call delete('Xtext')
241endfunc
242
243func Test_terminal_scroll()
244  call writefile(range(1, 200), 'Xtext')
245  if has('win32')
246    let cmd = 'cmd /c "type Xtext"'
247  else
248    let cmd = "cat Xtext"
249  endif
250  let buf = term_start(cmd)
251
252  let job = term_getjob(buf)
253  call WaitForAssert({-> assert_equal("dead", job_status(job))})
254  call term_wait(buf)
255  if has('win32')
256    " TODO: this should not be needed
257    sleep 100m
258  endif
259
260  let scrolled = term_getscrolled(buf)
261  call assert_equal('1', getline(1))
262  call assert_equal('1', term_getline(buf, 1 - scrolled))
263  call assert_equal('49', getline(49))
264  call assert_equal('49', term_getline(buf, 49 - scrolled))
265  call assert_equal('200', getline(200))
266  call assert_equal('200', term_getline(buf, 200 - scrolled))
267
268  exe buf . 'bwipe'
269  call delete('Xtext')
270endfunc
271
272func Test_terminal_scrollback()
273  let buf = Run_shell_in_terminal({'term_rows': 15})
274  set termwinscroll=100
275  call writefile(range(150), 'Xtext')
276  if has('win32')
277    call term_sendkeys(buf, "type Xtext\<CR>")
278  else
279    call term_sendkeys(buf, "cat Xtext\<CR>")
280  endif
281  let rows = term_getsize(buf)[0]
282  " On MS-Windows there is an empty line, check both last line and above it.
283  call WaitForAssert({-> assert_match( '149', term_getline(buf, rows - 1) . term_getline(buf, rows - 2))})
284  let lines = line('$')
285  call assert_inrange(91, 100, lines)
286
287  call Stop_shell_in_terminal(buf)
288  call term_wait(buf)
289  exe buf . 'bwipe'
290  set termwinscroll&
291endfunc
292
293func Test_terminal_size()
294  let cmd = Get_cat_123_cmd()
295
296  exe 'terminal ++rows=5 ' . cmd
297  let size = term_getsize('')
298  bwipe!
299  call assert_equal(5, size[0])
300
301  call term_start(cmd, {'term_rows': 6})
302  let size = term_getsize('')
303  bwipe!
304  call assert_equal(6, size[0])
305
306  vsplit
307  exe 'terminal ++rows=5 ++cols=33 ' . cmd
308  call assert_equal([5, 33], term_getsize(''))
309
310  call term_setsize('', 6, 0)
311  call assert_equal([6, 33], term_getsize(''))
312
313  call term_setsize('', 0, 35)
314  call assert_equal([6, 35], term_getsize(''))
315
316  call term_setsize('', 7, 30)
317  call assert_equal([7, 30], term_getsize(''))
318
319  bwipe!
320  call assert_fails("call term_setsize('', 7, 30)", "E955:")
321
322  call term_start(cmd, {'term_rows': 6, 'term_cols': 36})
323  let size = term_getsize('')
324  bwipe!
325  call assert_equal([6, 36], size)
326
327  exe 'vertical terminal ++cols=20 ' . cmd
328  let size = term_getsize('')
329  bwipe!
330  call assert_equal(20, size[1])
331
332  call term_start(cmd, {'vertical': 1, 'term_cols': 26})
333  let size = term_getsize('')
334  bwipe!
335  call assert_equal(26, size[1])
336
337  split
338  exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd
339  let size = term_getsize('')
340  bwipe!
341  call assert_equal([6, 20], size)
342
343  call term_start(cmd, {'vertical': 1, 'term_rows': 7, 'term_cols': 27})
344  let size = term_getsize('')
345  bwipe!
346  call assert_equal([7, 27], size)
347
348  call delete('Xtext')
349endfunc
350
351func Test_terminal_curwin()
352  let cmd = Get_cat_123_cmd()
353  call assert_equal(1, winnr('$'))
354
355  split dummy
356  exe 'terminal ++curwin ' . cmd
357  call assert_equal(2, winnr('$'))
358  bwipe!
359
360  split dummy
361  call term_start(cmd, {'curwin': 1})
362  call assert_equal(2, winnr('$'))
363  bwipe!
364
365  split dummy
366  call setline(1, 'change')
367  call assert_fails('terminal ++curwin ' . cmd, 'E37:')
368  call assert_equal(2, winnr('$'))
369  exe 'terminal! ++curwin ' . cmd
370  call assert_equal(2, winnr('$'))
371  bwipe!
372
373  split dummy
374  call setline(1, 'change')
375  call assert_fails("call term_start(cmd, {'curwin': 1})", 'E37:')
376  call assert_equal(2, winnr('$'))
377  bwipe!
378
379  split dummy
380  bwipe!
381  call delete('Xtext')
382endfunc
383
384func s:get_sleep_cmd()
385  if s:python != ''
386    let cmd = s:python . " test_short_sleep.py"
387    " 500 was not enough for Travis
388    let waittime = 900
389  else
390    echo 'This will take five seconds...'
391    let waittime = 2000
392    if has('win32')
393      let cmd = $windir . '\system32\timeout.exe 1'
394    else
395      let cmd = 'sleep 1'
396    endif
397  endif
398  return [cmd, waittime]
399endfunc
400
401func Test_terminal_finish_open_close()
402  call assert_equal(1, winnr('$'))
403
404  let [cmd, waittime] = s:get_sleep_cmd()
405
406  " shell terminal closes automatically
407  terminal
408  let buf = bufnr('%')
409  call assert_equal(2, winnr('$'))
410  " Wait for the shell to display a prompt
411  call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
412  call Stop_shell_in_terminal(buf)
413  call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
414
415  " shell terminal that does not close automatically
416  terminal ++noclose
417  let buf = bufnr('%')
418  call assert_equal(2, winnr('$'))
419  " Wait for the shell to display a prompt
420  call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
421  call Stop_shell_in_terminal(buf)
422  call assert_equal(2, winnr('$'))
423  quit
424  call assert_equal(1, winnr('$'))
425
426  exe 'terminal ++close ' . cmd
427  call assert_equal(2, winnr('$'))
428  wincmd p
429  call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
430
431  call term_start(cmd, {'term_finish': 'close'})
432  call assert_equal(2, winnr('$'))
433  wincmd p
434  call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
435  call assert_equal(1, winnr('$'))
436
437  exe 'terminal ++open ' . cmd
438  close!
439  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
440  bwipe
441
442  call term_start(cmd, {'term_finish': 'open'})
443  close!
444  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
445  bwipe
446
447  exe 'terminal ++hidden ++open ' . cmd
448  call assert_equal(1, winnr('$'))
449  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
450  bwipe
451
452  call term_start(cmd, {'term_finish': 'open', 'hidden': 1})
453  call assert_equal(1, winnr('$'))
454  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
455  bwipe
456
457  call assert_fails("call term_start(cmd, {'term_opencmd': 'open'})", 'E475:')
458  call assert_fails("call term_start(cmd, {'term_opencmd': 'split %x'})", 'E475:')
459  call assert_fails("call term_start(cmd, {'term_opencmd': 'split %d and %s'})", 'E475:')
460  call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:')
461
462  call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'})
463  close!
464  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
465  call assert_equal(4, winheight(0))
466  bwipe
467endfunc
468
469func Test_terminal_cwd()
470  if !executable('pwd')
471    return
472  endif
473  call mkdir('Xdir')
474  let buf = term_start('pwd', {'cwd': 'Xdir'})
475  call WaitForAssert({-> assert_equal('Xdir', fnamemodify(getline(1), ":t"))})
476
477  exe buf . 'bwipe'
478  call delete('Xdir', 'rf')
479endfunc
480
481func Test_terminal_servername()
482  if !has('clientserver')
483    return
484  endif
485  call s:test_environment("VIM_SERVERNAME", v:servername)
486endfunc
487
488func Test_terminal_version()
489  call s:test_environment("VIM_TERMINAL", string(v:version))
490endfunc
491
492func s:test_environment(name, value)
493  let buf = Run_shell_in_terminal({})
494  " Wait for the shell to display a prompt
495  call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
496  if has('win32')
497    call term_sendkeys(buf, "echo %" . a:name . "%\r")
498  else
499    call term_sendkeys(buf, "echo $" . a:name . "\r")
500  endif
501  call term_wait(buf)
502  call Stop_shell_in_terminal(buf)
503  call WaitForAssert({-> assert_equal(a:value, getline(2))})
504
505  exe buf . 'bwipe'
506  unlet buf
507endfunc
508
509func Test_terminal_env()
510  let buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}})
511  " Wait for the shell to display a prompt
512  call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
513  if has('win32')
514    call term_sendkeys(buf, "echo %TESTENV%\r")
515  else
516    call term_sendkeys(buf, "echo $TESTENV\r")
517  endif
518  call term_wait(buf)
519  call Stop_shell_in_terminal(buf)
520  call WaitForAssert({-> assert_equal('correct', getline(2))})
521
522  exe buf . 'bwipe'
523endfunc
524
525func Test_terminal_list_args()
526  let buf = term_start([&shell, &shellcmdflag, 'echo "123"'])
527  call assert_fails(buf . 'bwipe', 'E517')
528  exe buf . 'bwipe!'
529  call assert_equal("", bufname(buf))
530endfunction
531
532func Test_terminal_noblock()
533  let buf = term_start(&shell)
534  if has('mac')
535    " The shell or something else has a problem dealing with more than 1000
536    " characters at the same time.
537    let len = 1000
538  else
539    let len = 5000
540  endif
541
542  for c in ['a','b','c','d','e','f','g','h','i','j','k']
543    call term_sendkeys(buf, 'echo ' . repeat(c, len) . "\<cr>")
544  endfor
545  call term_sendkeys(buf, "echo done\<cr>")
546
547  " On MS-Windows there is an extra empty line below "done".  Find "done" in
548  " the last-but-one or the last-but-two line.
549  let lnum = term_getsize(buf)[0] - 1
550  call WaitFor({-> term_getline(buf, lnum) =~ "done" || term_getline(buf, lnum - 1) =~ "done"}, 10000)
551  let line = term_getline(buf, lnum)
552  if line !~ 'done'
553    let line = term_getline(buf, lnum - 1)
554  endif
555  call assert_match('done', line)
556
557  let g:job = term_getjob(buf)
558  call Stop_shell_in_terminal(buf)
559  call term_wait(buf)
560  unlet g:job
561  bwipe
562endfunc
563
564func Test_terminal_write_stdin()
565  if !executable('wc')
566    throw 'skipped: wc command not available'
567  endif
568  if has('win32')
569    " TODO: enable once writing to stdin works on MS-Windows
570    return
571  endif
572  new
573  call setline(1, ['one', 'two', 'three'])
574  %term wc
575  call WaitForAssert({-> assert_match('3', getline("$"))})
576  let nrs = split(getline('$'))
577  call assert_equal(['3', '3', '14'], nrs)
578  bwipe
579
580  new
581  call setline(1, ['one', 'two', 'three', 'four'])
582  2,3term wc
583  call WaitForAssert({-> assert_match('2', getline("$"))})
584  let nrs = split(getline('$'))
585  call assert_equal(['2', '2', '10'], nrs)
586  bwipe
587
588  if executable('python')
589    new
590    call setline(1, ['print("hello")'])
591    1term ++eof=exit() python
592    " MS-Windows echoes the input, Unix doesn't.
593    call WaitFor('getline("$") =~ "exit" || getline(1) =~ "hello"')
594    if getline(1) =~ 'hello'
595      call assert_equal('hello', getline(1))
596    else
597      call assert_equal('hello', getline(line('$') - 1))
598    endif
599    bwipe
600
601    if has('win32')
602      new
603      call setline(1, ['print("hello")'])
604      1term ++eof=<C-Z> python
605      call WaitForAssert({-> assert_match('Z', getline("$"))})
606      call assert_equal('hello', getline(line('$') - 1))
607      bwipe
608    endif
609  endif
610
611  bwipe!
612endfunc
613
614func Test_terminal_no_cmd()
615  " Todo: make this work in the GUI
616  if !has('gui_running')
617    return
618  endif
619  let buf = term_start('NONE', {})
620  call assert_notequal(0, buf)
621
622  let pty = job_info(term_getjob(buf))['tty_out']
623  call assert_notequal('', pty)
624  if has('win32')
625    silent exe '!start cmd /c "echo look here > ' . pty . '"'
626  else
627    call system('echo "look here" > ' . pty)
628  endif
629  call WaitForAssert({-> assert_match('look here', term_getline(buf, 1))})
630
631  bwipe!
632endfunc
633
634func Test_terminal_special_chars()
635  " this file name only works on Unix
636  if !has('unix')
637    return
638  endif
639  call mkdir('Xdir with spaces')
640  call writefile(['x'], 'Xdir with spaces/quoted"file')
641  term ls Xdir\ with\ spaces/quoted\"file
642  call WaitForAssert({-> assert_match('quoted"file', term_getline('', 1))})
643  call term_wait('')
644
645  call delete('Xdir with spaces', 'rf')
646  bwipe
647endfunc
648
649func Test_terminal_wrong_options()
650  call assert_fails('call term_start(&shell, {
651	\ "in_io": "file",
652	\ "in_name": "xxx",
653	\ "out_io": "file",
654	\ "out_name": "xxx",
655	\ "err_io": "file",
656	\ "err_name": "xxx"
657	\ })', 'E474:')
658  call assert_fails('call term_start(&shell, {
659	\ "out_buf": bufnr("%")
660	\ })', 'E474:')
661  call assert_fails('call term_start(&shell, {
662	\ "err_buf": bufnr("%")
663	\ })', 'E474:')
664endfunc
665
666func Test_terminal_redir_file()
667  let cmd = Get_cat_123_cmd()
668  let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
669  call term_wait(buf)
670  call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))})
671  call assert_match('123', readfile('Xfile')[0])
672  let g:job = term_getjob(buf)
673  call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
674  call delete('Xfile')
675  bwipe
676
677  if has('unix')
678    call writefile(['one line'], 'Xfile')
679    let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'})
680    call term_wait(buf)
681    call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))})
682    let g:job = term_getjob(buf)
683    call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
684    bwipe
685    call delete('Xfile')
686  endif
687endfunc
688
689func TerminalTmap(remap)
690  let buf = Run_shell_in_terminal({})
691  call assert_equal('t', mode())
692
693  if a:remap
694    tmap 123 456
695  else
696    tnoremap 123 456
697  endif
698  " don't use abcde, it's an existing command
699  tmap 456 abxde
700  call assert_equal('456', maparg('123', 't'))
701  call assert_equal('abxde', maparg('456', 't'))
702  call feedkeys("123", 'tx')
703  call WaitForAssert({-> assert_match('abxde\|456', term_getline(buf, term_getcursor(buf)[0]))})
704  let lnum = term_getcursor(buf)[0]
705  if a:remap
706    call assert_match('abxde', term_getline(buf, lnum))
707  else
708    call assert_match('456', term_getline(buf, lnum))
709  endif
710
711  call term_sendkeys(buf, "\r")
712  call Stop_shell_in_terminal(buf)
713  call term_wait(buf)
714
715  tunmap 123
716  tunmap 456
717  call assert_equal('', maparg('123', 't'))
718  close
719  unlet g:job
720endfunc
721
722func Test_terminal_tmap()
723  call TerminalTmap(1)
724  call TerminalTmap(0)
725endfunc
726
727func Test_terminal_wall()
728  let buf = Run_shell_in_terminal({})
729  wall
730  call Stop_shell_in_terminal(buf)
731  call term_wait(buf)
732  exe buf . 'bwipe'
733  unlet g:job
734endfunc
735
736func Test_terminal_wqall()
737  let buf = Run_shell_in_terminal({})
738  call assert_fails('wqall', 'E948')
739  call Stop_shell_in_terminal(buf)
740  call term_wait(buf)
741  exe buf . 'bwipe'
742  unlet g:job
743endfunc
744
745func Test_terminal_composing_unicode()
746  let save_enc = &encoding
747  set encoding=utf-8
748
749  if has('win32')
750    let cmd = "cmd /K chcp 65001"
751    let lnum = [3, 6, 9]
752  else
753    let cmd = &shell
754    let lnum = [1, 3, 5]
755  endif
756
757  enew
758  let buf = term_start(cmd, {'curwin': bufnr('')})
759  let g:job = term_getjob(buf)
760  call term_wait(buf, 50)
761
762  if has('win32')
763    call assert_equal('cmd', job_info(g:job).cmd[0])
764  else
765    call assert_equal(&shell, job_info(g:job).cmd[0])
766  endif
767
768  " ascii + composing
769  let txt = "a\u0308bc"
770  call term_sendkeys(buf, "echo " . txt . "\r")
771  call term_wait(buf, 50)
772  call assert_match("echo " . txt, term_getline(buf, lnum[0]))
773  call assert_equal(txt, term_getline(buf, lnum[0] + 1))
774  let l = term_scrape(buf, lnum[0] + 1)
775  call assert_equal("a\u0308", l[0].chars)
776  call assert_equal("b", l[1].chars)
777  call assert_equal("c", l[2].chars)
778
779  " multibyte + composing
780  let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099"
781  call term_sendkeys(buf, "echo " . txt . "\r")
782  call term_wait(buf, 50)
783  call assert_match("echo " . txt, term_getline(buf, lnum[1]))
784  call assert_equal(txt, term_getline(buf, lnum[1] + 1))
785  let l = term_scrape(buf, lnum[1] + 1)
786  call assert_equal("\u304b\u3099", l[0].chars)
787  call assert_equal("\u304e", l[1].chars)
788  call assert_equal("\u304f\u3099", l[2].chars)
789  call assert_equal("\u3052", l[3].chars)
790  call assert_equal("\u3053\u3099", l[4].chars)
791
792  " \u00a0 + composing
793  let txt = "abc\u00a0\u0308"
794  call term_sendkeys(buf, "echo " . txt . "\r")
795  call term_wait(buf, 50)
796  call assert_match("echo " . txt, term_getline(buf, lnum[2]))
797  call assert_equal(txt, term_getline(buf, lnum[2] + 1))
798  let l = term_scrape(buf, lnum[2] + 1)
799  call assert_equal("\u00a0\u0308", l[3].chars)
800
801  call term_sendkeys(buf, "exit\r")
802  call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
803  bwipe!
804  unlet g:job
805  let &encoding = save_enc
806endfunc
807
808func Test_terminal_aucmd_on_close()
809  fun Nop()
810    let s:called = 1
811  endfun
812
813  aug repro
814      au!
815      au BufWinLeave * call Nop()
816  aug END
817
818  let [cmd, waittime] = s:get_sleep_cmd()
819
820  call assert_equal(1, winnr('$'))
821  new
822  call setline(1, ['one', 'two'])
823  exe 'term ++close ' . cmd
824  wincmd p
825  call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
826  call assert_equal(1, s:called)
827  bwipe!
828
829  unlet s:called
830  au! repro
831  delfunc Nop
832endfunc
833
834func Test_terminal_term_start_empty_command()
835  let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})"
836  call assert_fails(cmd, 'E474')
837  let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})"
838  call assert_fails(cmd, 'E474')
839  let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})"
840  call assert_fails(cmd, 'E474')
841  let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})"
842  call assert_fails(cmd, 'E474')
843endfunc
844
845func Test_terminal_response_to_control_sequence()
846  if !has('unix')
847    return
848  endif
849
850  let buf = Run_shell_in_terminal({})
851  call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
852
853  call term_sendkeys(buf, "cat\<CR>")
854  call WaitForAssert({-> assert_match('cat', term_getline(buf, 1))})
855
856  " Request the cursor position.
857  call term_sendkeys(buf, "\x1b[6n\<CR>")
858
859  " Wait for output from tty to display, below an empty line.
860  call WaitForAssert({-> assert_match('3;1R', term_getline(buf, 4))})
861
862  " End "cat" gently.
863  call term_sendkeys(buf, "\<CR>\<C-D>")
864
865  call Stop_shell_in_terminal(buf)
866  exe buf . 'bwipe'
867  unlet g:job
868endfunc
869
870" Run Vim, start a terminal in that Vim with the kill argument,
871" :qall works.
872func Run_terminal_qall_kill(line1, line2)
873  " 1. Open a terminal window and wait for the prompt to appear
874  " 2. set kill using term_setkill()
875  " 3. make Vim exit, it will kill the shell
876  let after = [
877	\ a:line1,
878	\ 'let buf = bufnr("%")',
879	\ 'while term_getline(buf, 1) =~ "^\\s*$"',
880	\ '  sleep 10m',
881	\ 'endwhile',
882	\ a:line2,
883	\ 'au VimLeavePre * call writefile(["done"], "Xdone")',
884	\ 'qall',
885	\ ]
886  if !RunVim([], after, '')
887    return
888  endif
889  call assert_equal("done", readfile("Xdone")[0])
890  call delete("Xdone")
891endfunc
892
893" Run Vim in a terminal, then start a terminal in that Vim with a kill
894" argument, check that :qall works.
895func Test_terminal_qall_kill_arg()
896  call Run_terminal_qall_kill('term ++kill=kill', '')
897endfunc
898
899" Run Vim, start a terminal in that Vim, set the kill argument with
900" term_setkill(), check that :qall works.
901func Test_terminal_qall_kill_func()
902  call Run_terminal_qall_kill('term', 'call term_setkill(buf, "kill")')
903endfunc
904
905" Run Vim, start a terminal in that Vim without the kill argument,
906" check that :qall does not exit, :qall! does.
907func Test_terminal_qall_exit()
908  let after = [
909	\ 'term',
910	\ 'let buf = bufnr("%")',
911	\ 'while term_getline(buf, 1) =~ "^\\s*$"',
912	\ '  sleep 10m',
913	\ 'endwhile',
914	\ 'set nomore',
915	\ 'au VimLeavePre * call writefile(["too early"], "Xdone")',
916	\ 'qall',
917	\ 'au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone")',
918	\ 'cquit',
919	\ ]
920  if !RunVim([], after, '')
921    return
922  endif
923  call assert_equal("done", readfile("Xdone")[0])
924  call delete("Xdone")
925endfunc
926
927" Run Vim in a terminal, then start a terminal in that Vim without a kill
928" argument, check that :confirm qall works.
929func Test_terminal_qall_prompt()
930  if !CanRunVimInTerminal()
931    return
932  endif
933  let buf = RunVimInTerminal('', {})
934
935  " Open a terminal window and wait for the prompt to appear
936  call term_sendkeys(buf, ":term\<CR>")
937  call WaitForAssert({-> assert_match('\[running]', term_getline(buf, 10))})
938  call WaitForAssert({-> assert_notmatch('^\s*$', term_getline(buf, 1))})
939
940  " make Vim exit, it will prompt to kill the shell
941  call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>")
942  call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))})
943  call term_sendkeys(buf, "y")
944  call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
945
946  " close the terminal window where Vim was running
947  quit
948endfunc
949
950func Test_terminal_open_autocmd()
951  augroup repro
952    au!
953    au TerminalOpen * let s:called += 1
954  augroup END
955
956  let s:called = 0
957
958  " Open a terminal window with :terminal
959  terminal
960  call assert_equal(1, s:called)
961  bwipe!
962
963  " Open a terminal window with term_start()
964  call term_start(&shell)
965  call assert_equal(2, s:called)
966  bwipe!
967
968  " Open a hidden terminal buffer with :terminal
969  terminal ++hidden
970  call assert_equal(3, s:called)
971  for buf in term_list()
972    exe buf . "bwipe!"
973  endfor
974
975  " Open a hidden terminal buffer with term_start()
976  let buf = term_start(&shell, {'hidden': 1})
977  call assert_equal(4, s:called)
978  exe buf . "bwipe!"
979
980  unlet s:called
981  au! repro
982endfunction
983
984func Check_dump01(off)
985  call assert_equal('one two three four five', trim(getline(a:off + 1)))
986  call assert_equal('~           Select Word', trim(getline(a:off + 7)))
987  call assert_equal(':popup PopUp', trim(getline(a:off + 20)))
988endfunc
989
990func Test_terminal_dumpwrite_composing()
991  if !CanRunVimInTerminal()
992    return
993  endif
994  let save_enc = &encoding
995  set encoding=utf-8
996  call assert_equal(1, winnr('$'))
997
998  let text = " a\u0300 e\u0302 o\u0308"
999  call writefile([text], 'Xcomposing')
1000  let buf = RunVimInTerminal('--cmd "set encoding=utf-8" Xcomposing', {})
1001  call WaitForAssert({-> assert_match(text, term_getline(buf, 1))})
1002  call term_dumpwrite(buf, 'Xdump')
1003  let dumpline = readfile('Xdump')[0]
1004  call assert_match('|à| |ê| |ö', dumpline)
1005
1006  call StopVimInTerminal(buf)
1007  call delete('Xcomposing')
1008  call delete('Xdump')
1009  let &encoding = save_enc
1010endfunc
1011
1012" just testing basic functionality.
1013func Test_terminal_dumpload()
1014  call assert_equal(1, winnr('$'))
1015  call term_dumpload('dumps/Test_popup_command_01.dump')
1016  call assert_equal(2, winnr('$'))
1017  call assert_equal(20, line('$'))
1018  call Check_dump01(0)
1019  quit
1020endfunc
1021
1022func Test_terminal_dumpdiff()
1023  call assert_equal(1, winnr('$'))
1024  call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump')
1025  call assert_equal(2, winnr('$'))
1026  call assert_equal(62, line('$'))
1027  call Check_dump01(0)
1028  call Check_dump01(42)
1029  call assert_equal('           bbbbbbbbbbbbbbbbbb ', getline(26)[0:29])
1030  quit
1031endfunc
1032
1033func Test_terminal_dumpdiff_options()
1034  set laststatus=0
1035  call assert_equal(1, winnr('$'))
1036  let height = winheight(0)
1037  call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33})
1038  call assert_equal(2, winnr('$'))
1039  call assert_equal(height, winheight(winnr()))
1040  call assert_equal(33, winwidth(winnr()))
1041  call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%'))
1042  quit
1043
1044  call assert_equal(1, winnr('$'))
1045  let width = winwidth(0)
1046  call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'})
1047  call assert_equal(2, winnr('$'))
1048  call assert_equal(width, winwidth(winnr()))
1049  call assert_equal(13, winheight(winnr()))
1050  call assert_equal('something else', bufname('%'))
1051  quit
1052
1053  call assert_equal(1, winnr('$'))
1054  call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1})
1055  call assert_equal(1, winnr('$'))
1056  bwipe
1057
1058  set laststatus&
1059endfunc
1060
1061func Api_drop_common(options)
1062  call assert_equal(1, winnr('$'))
1063
1064  " Use the title termcap entries to output the escape sequence.
1065  call writefile([
1066	\ 'set title',
1067	\ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
1068	\ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''',
1069	\ 'redraw',
1070	\ "set t_ts=",
1071	\ ], 'Xscript')
1072  let buf = RunVimInTerminal('-S Xscript', {})
1073  call WaitFor({-> bufnr('Xtextfile') > 0})
1074  call assert_equal('Xtextfile', expand('%:t'))
1075  call assert_true(winnr('$') >= 3)
1076  return buf
1077endfunc
1078
1079func Test_terminal_api_drop_newwin()
1080  if !CanRunVimInTerminal()
1081    return
1082  endif
1083  let buf = Api_drop_common('')
1084  call assert_equal(0, &bin)
1085  call assert_equal('', &fenc)
1086
1087  call StopVimInTerminal(buf)
1088  call delete('Xscript')
1089  bwipe Xtextfile
1090endfunc
1091
1092func Test_terminal_api_drop_newwin_bin()
1093  if !CanRunVimInTerminal()
1094    return
1095  endif
1096  let buf = Api_drop_common(',{"bin":1}')
1097  call assert_equal(1, &bin)
1098
1099  call StopVimInTerminal(buf)
1100  call delete('Xscript')
1101  bwipe Xtextfile
1102endfunc
1103
1104func Test_terminal_api_drop_newwin_binary()
1105  if !CanRunVimInTerminal()
1106    return
1107  endif
1108  let buf = Api_drop_common(',{"binary":1}')
1109  call assert_equal(1, &bin)
1110
1111  call StopVimInTerminal(buf)
1112  call delete('Xscript')
1113  bwipe Xtextfile
1114endfunc
1115
1116func Test_terminal_api_drop_newwin_nobin()
1117  if !CanRunVimInTerminal()
1118    return
1119  endif
1120  set binary
1121  let buf = Api_drop_common(',{"nobin":1}')
1122  call assert_equal(0, &bin)
1123
1124  call StopVimInTerminal(buf)
1125  call delete('Xscript')
1126  bwipe Xtextfile
1127  set nobinary
1128endfunc
1129
1130func Test_terminal_api_drop_newwin_nobinary()
1131  if !CanRunVimInTerminal()
1132    return
1133  endif
1134  set binary
1135  let buf = Api_drop_common(',{"nobinary":1}')
1136  call assert_equal(0, &bin)
1137
1138  call StopVimInTerminal(buf)
1139  call delete('Xscript')
1140  bwipe Xtextfile
1141  set nobinary
1142endfunc
1143
1144func Test_terminal_api_drop_newwin_ff()
1145  if !CanRunVimInTerminal()
1146    return
1147  endif
1148  let buf = Api_drop_common(',{"ff":"dos"}')
1149  call assert_equal("dos", &ff)
1150
1151  call StopVimInTerminal(buf)
1152  call delete('Xscript')
1153  bwipe Xtextfile
1154endfunc
1155
1156func Test_terminal_api_drop_newwin_fileformat()
1157  if !CanRunVimInTerminal()
1158    return
1159  endif
1160  let buf = Api_drop_common(',{"fileformat":"dos"}')
1161  call assert_equal("dos", &ff)
1162
1163  call StopVimInTerminal(buf)
1164  call delete('Xscript')
1165  bwipe Xtextfile
1166endfunc
1167
1168func Test_terminal_api_drop_newwin_enc()
1169  if !CanRunVimInTerminal()
1170    return
1171  endif
1172  let buf = Api_drop_common(',{"enc":"utf-16"}')
1173  call assert_equal("utf-16", &fenc)
1174
1175  call StopVimInTerminal(buf)
1176  call delete('Xscript')
1177  bwipe Xtextfile
1178endfunc
1179
1180func Test_terminal_api_drop_newwin_encoding()
1181  if !CanRunVimInTerminal()
1182    return
1183  endif
1184  let buf = Api_drop_common(',{"encoding":"utf-16"}')
1185  call assert_equal("utf-16", &fenc)
1186
1187  call StopVimInTerminal(buf)
1188  call delete('Xscript')
1189  bwipe Xtextfile
1190endfunc
1191
1192func Test_terminal_api_drop_oldwin()
1193  if !CanRunVimInTerminal()
1194    return
1195  endif
1196  let firstwinid = win_getid()
1197  split Xtextfile
1198  let textfile_winid = win_getid()
1199  call assert_equal(2, winnr('$'))
1200  call win_gotoid(firstwinid)
1201
1202  " Use the title termcap entries to output the escape sequence.
1203  call writefile([
1204	\ 'set title',
1205	\ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
1206	\ 'let &titlestring = ''["drop","Xtextfile"]''',
1207	\ 'redraw',
1208	\ "set t_ts=",
1209	\ ], 'Xscript')
1210  let buf = RunVimInTerminal('-S Xscript', {'rows': 10})
1211  call WaitForAssert({-> assert_equal('Xtextfile', expand('%:t'))})
1212  call assert_equal(textfile_winid, win_getid())
1213
1214  call StopVimInTerminal(buf)
1215  call delete('Xscript')
1216  bwipe Xtextfile
1217endfunc
1218
1219func Tapi_TryThis(bufnum, arg)
1220  let g:called_bufnum = a:bufnum
1221  let g:called_arg = a:arg
1222endfunc
1223
1224func WriteApiCall(funcname)
1225  " Use the title termcap entries to output the escape sequence.
1226  call writefile([
1227	\ 'set title',
1228	\ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
1229	\ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''',
1230	\ 'redraw',
1231	\ "set t_ts=",
1232	\ ], 'Xscript')
1233endfunc
1234
1235func Test_terminal_api_call()
1236  if !CanRunVimInTerminal()
1237    return
1238  endif
1239
1240  call WriteApiCall('Tapi_TryThis')
1241  let buf = RunVimInTerminal('-S Xscript', {})
1242  call WaitFor({-> exists('g:called_bufnum')})
1243  call assert_equal(buf, g:called_bufnum)
1244  call assert_equal(['hello', 123], g:called_arg)
1245
1246  call StopVimInTerminal(buf)
1247  call delete('Xscript')
1248  unlet g:called_bufnum
1249  unlet g:called_arg
1250endfunc
1251
1252func Test_terminal_api_call_fails()
1253  if !CanRunVimInTerminal()
1254    return
1255  endif
1256
1257  call WriteApiCall('TryThis')
1258  call ch_logfile('Xlog', 'w')
1259  let buf = RunVimInTerminal('-S Xscript', {})
1260  call WaitForAssert({-> assert_match('Invalid function name: TryThis', string(readfile('Xlog')))})
1261
1262  call StopVimInTerminal(buf)
1263  call delete('Xscript')
1264  call ch_logfile('', '')
1265  call delete('Xlog')
1266endfunc
1267
1268let s:caught_e937 = 0
1269
1270func Tapi_Delete(bufnum, arg)
1271  try
1272    execute 'bdelete!' a:bufnum
1273  catch /E937:/
1274    let s:caught_e937 = 1
1275  endtry
1276endfunc
1277
1278func Test_terminal_api_call_fail_delete()
1279  if !CanRunVimInTerminal()
1280    return
1281  endif
1282
1283  call WriteApiCall('Tapi_Delete')
1284  let buf = RunVimInTerminal('-S Xscript', {})
1285  call WaitForAssert({-> assert_equal(1, s:caught_e937)})
1286
1287  call StopVimInTerminal(buf)
1288  call delete('Xscript')
1289  call ch_logfile('', '')
1290endfunc
1291
1292func Test_terminal_ansicolors_default()
1293  let colors = [
1294	\ '#000000', '#e00000',
1295	\ '#00e000', '#e0e000',
1296	\ '#0000e0', '#e000e0',
1297	\ '#00e0e0', '#e0e0e0',
1298	\ '#808080', '#ff4040',
1299	\ '#40ff40', '#ffff40',
1300	\ '#4040ff', '#ff40ff',
1301	\ '#40ffff', '#ffffff',
1302	\]
1303
1304  let buf = Run_shell_in_terminal({})
1305  call assert_equal(colors, term_getansicolors(buf))
1306  call Stop_shell_in_terminal(buf)
1307  call term_wait(buf)
1308
1309  exe buf . 'bwipe'
1310endfunc
1311
1312let s:test_colors = [
1313	\ '#616e64', '#0d0a79',
1314	\ '#6d610d', '#0a7373',
1315	\ '#690d0a', '#6d696e',
1316	\ '#0d0a6f', '#616e0d',
1317	\ '#0a6479', '#6d0d0a',
1318	\ '#617373', '#0d0a69',
1319	\ '#6d690d', '#0a6e6f',
1320	\ '#610d0a', '#6e6479',
1321	\]
1322
1323func Test_terminal_ansicolors_global()
1324  let g:terminal_ansi_colors = reverse(copy(s:test_colors))
1325  let buf = Run_shell_in_terminal({})
1326  call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf))
1327  call Stop_shell_in_terminal(buf)
1328  call term_wait(buf)
1329
1330  exe buf . 'bwipe'
1331  unlet g:terminal_ansi_colors
1332endfunc
1333
1334func Test_terminal_ansicolors_func()
1335  let g:terminal_ansi_colors = reverse(copy(s:test_colors))
1336  let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors})
1337  call assert_equal(s:test_colors, term_getansicolors(buf))
1338
1339  call term_setansicolors(buf, g:terminal_ansi_colors)
1340  call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf))
1341
1342  let colors = [
1343	\ 'ivory', 'AliceBlue',
1344	\ 'grey67', 'dark goldenrod',
1345	\ 'SteelBlue3', 'PaleVioletRed4',
1346	\ 'MediumPurple2', 'yellow2',
1347	\ 'RosyBrown3', 'OrangeRed2',
1348	\ 'white smoke', 'navy blue',
1349	\ 'grey47', 'gray97',
1350	\ 'MistyRose2', 'DodgerBlue4',
1351	\]
1352  call term_setansicolors(buf, colors)
1353
1354  let colors[4] = 'Invalid'
1355  call assert_fails('call term_setansicolors(buf, colors)', 'E474:')
1356
1357  call Stop_shell_in_terminal(buf)
1358  call term_wait(buf)
1359  exe buf . 'bwipe'
1360endfunc
1361
1362func Test_terminal_termwinsize_option_fixed()
1363  if !CanRunVimInTerminal()
1364    return
1365  endif
1366  set termwinsize=6x40
1367  let text = []
1368  for n in range(10)
1369    call add(text, repeat(n, 50))
1370  endfor
1371  call writefile(text, 'Xwinsize')
1372  let buf = RunVimInTerminal('Xwinsize', {})
1373  let win = bufwinid(buf)
1374  call assert_equal([6, 40], term_getsize(buf))
1375  call assert_equal(6, winheight(win))
1376  call assert_equal(40, winwidth(win))
1377
1378  " resizing the window doesn't resize the terminal.
1379  resize 10
1380  vertical resize 60
1381  call assert_equal([6, 40], term_getsize(buf))
1382  call assert_equal(10, winheight(win))
1383  call assert_equal(60, winwidth(win))
1384
1385  call StopVimInTerminal(buf)
1386  call delete('Xwinsize')
1387
1388  call assert_fails('set termwinsize=40', 'E474')
1389  call assert_fails('set termwinsize=10+40', 'E474')
1390  call assert_fails('set termwinsize=abc', 'E474')
1391
1392  set termwinsize=
1393endfunc
1394
1395func Test_terminal_termwinsize_option_zero()
1396  set termwinsize=0x0
1397  let buf = Run_shell_in_terminal({})
1398  let win = bufwinid(buf)
1399  call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1400  call Stop_shell_in_terminal(buf)
1401  call term_wait(buf)
1402  exe buf . 'bwipe'
1403
1404  set termwinsize=7x0
1405  let buf = Run_shell_in_terminal({})
1406  let win = bufwinid(buf)
1407  call assert_equal([7, winwidth(win)], term_getsize(buf))
1408  call Stop_shell_in_terminal(buf)
1409  call term_wait(buf)
1410  exe buf . 'bwipe'
1411
1412  set termwinsize=0x33
1413  let buf = Run_shell_in_terminal({})
1414  let win = bufwinid(buf)
1415  call assert_equal([winheight(win), 33], term_getsize(buf))
1416  call Stop_shell_in_terminal(buf)
1417  call term_wait(buf)
1418  exe buf . 'bwipe'
1419
1420  set termwinsize=
1421endfunc
1422
1423func Test_terminal_termwinsize_mininmum()
1424  set termwinsize=10*50
1425  vsplit
1426  let buf = Run_shell_in_terminal({})
1427  let win = bufwinid(buf)
1428  call assert_inrange(10, 1000, winheight(win))
1429  call assert_inrange(50, 1000, winwidth(win))
1430  call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1431
1432  resize 15
1433  vertical resize 60
1434  redraw
1435  call assert_equal([15, 60], term_getsize(buf))
1436  call assert_equal(15, winheight(win))
1437  call assert_equal(60, winwidth(win))
1438
1439  resize 7
1440  vertical resize 30
1441  redraw
1442  call assert_equal([10, 50], term_getsize(buf))
1443  call assert_equal(7, winheight(win))
1444  call assert_equal(30, winwidth(win))
1445
1446  call Stop_shell_in_terminal(buf)
1447  call term_wait(buf)
1448  exe buf . 'bwipe'
1449
1450  set termwinsize=0*0
1451  let buf = Run_shell_in_terminal({})
1452  let win = bufwinid(buf)
1453  call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1454  call Stop_shell_in_terminal(buf)
1455  call term_wait(buf)
1456  exe buf . 'bwipe'
1457
1458  set termwinsize=
1459endfunc
1460
1461func Test_terminal_termwinkey()
1462  call assert_equal(1, winnr('$'))
1463  let thiswin = win_getid()
1464
1465  let buf = Run_shell_in_terminal({})
1466  let termwin = bufwinid(buf)
1467  set termwinkey=<C-L>
1468  call feedkeys("\<C-L>w", 'tx')
1469  call assert_equal(thiswin, win_getid())
1470  call feedkeys("\<C-W>w", 'tx')
1471
1472  let job = term_getjob(buf)
1473  call feedkeys("\<C-L>\<C-C>", 'tx')
1474  call WaitForAssert({-> assert_equal("dead", job_status(job))})
1475endfunc
1476
1477func Test_terminal_out_err()
1478  if !has('unix')
1479    return
1480  endif
1481  call writefile([
1482	\ '#!/bin/sh',
1483	\ 'echo "this is standard error" >&2',
1484	\ 'echo "this is standard out" >&1',
1485	\ ], 'Xechoerrout.sh')
1486  call setfperm('Xechoerrout.sh', 'rwxrwx---')
1487
1488  let outfile = 'Xtermstdout'
1489  let buf = term_start(['./Xechoerrout.sh'], {'out_io': 'file', 'out_name': outfile})
1490
1491  call WaitFor({-> !empty(readfile(outfile)) && !empty(term_getline(buf, 1))})
1492  call assert_equal(['this is standard out'], readfile(outfile))
1493  call assert_equal('this is standard error', term_getline(buf, 1))
1494
1495  call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))})
1496  exe buf . 'bwipe'
1497  call delete('Xechoerrout.sh')
1498  call delete(outfile)
1499endfunc
1500
1501func Test_terminwinscroll()
1502  if !has('unix')
1503    return
1504  endif
1505
1506  " Let the terminal output more than 'termwinscroll' lines, some at the start
1507  " will be dropped.
1508  exe 'set termwinscroll=' . &lines
1509  let buf = term_start('/bin/sh')
1510  for i in range(1, &lines)
1511    call feedkeys("echo " . i . "\<CR>", 'xt')
1512    call WaitForAssert({-> assert_match(string(i), term_getline(buf, term_getcursor(buf)[0] - 1))})
1513  endfor
1514  " Go to Terminal-Normal mode to update the buffer.
1515  call feedkeys("\<C-W>N", 'xt')
1516  call assert_inrange(&lines, &lines * 110 / 100 + winheight(0), line('$'))
1517
1518  " Every "echo nr" must only appear once
1519  let lines = getline(1, line('$'))
1520  for i in range(&lines - len(lines) / 2 + 2, &lines)
1521    let filtered = filter(copy(lines), {idx, val -> val =~ 'echo ' . i . '\>'})
1522    call assert_equal(1, len(filtered), 'for "echo ' . i . '"')
1523  endfor
1524
1525  exe buf . 'bwipe!'
1526endfunc
1527
1528" Resizing the terminal window caused an ml_get error.
1529" TODO: This does not reproduce the original problem.
1530func Test_terminal_resize()
1531  set statusline=x
1532  terminal
1533  call assert_equal(2, winnr('$'))
1534
1535  " Fill the terminal with text.
1536  if has('win32')
1537    call feedkeys("dir\<CR>", 'xt')
1538  else
1539    call feedkeys("ls\<CR>", 'xt')
1540  endif
1541  " Go to Terminal-Normal mode for a moment.
1542  call feedkeys("\<C-W>N", 'xt')
1543  " Open a new window
1544  call feedkeys("i\<C-W>n", 'xt')
1545  call assert_equal(3, winnr('$'))
1546  redraw
1547
1548  close
1549  call assert_equal(2, winnr('$'))
1550  call feedkeys("exit\<CR>", 'xt')
1551  set statusline&
1552endfunc
1553
1554" must be nearly the last, we can't go back from GUI to terminal
1555func Test_zz1_terminal_in_gui()
1556  if !CanRunGui()
1557    return
1558  endif
1559
1560  " Ignore the "failed to create input context" error.
1561  call test_ignore_error('E285:')
1562
1563  gui -f
1564
1565  call assert_equal(1, winnr('$'))
1566  let buf = Run_shell_in_terminal({'term_finish': 'close'})
1567  call Stop_shell_in_terminal(buf)
1568  call term_wait(buf)
1569
1570  " closing window wipes out the terminal buffer a with finished job
1571  call WaitForAssert({-> assert_equal(1, winnr('$'))})
1572  call assert_equal("", bufname(buf))
1573
1574  unlet g:job
1575endfunc
1576
1577func Test_zz2_terminal_guioptions_bang()
1578  if !has('gui_running')
1579    return
1580  endif
1581  set guioptions+=!
1582
1583  let filename = 'Xtestscript'
1584  if has('win32')
1585    let filename .= '.bat'
1586    let prefix = ''
1587    let contents = ['@echo off', 'exit %1']
1588  else
1589    let filename .= '.sh'
1590    let prefix = './'
1591    let contents = ['#!/bin/sh', 'exit $1']
1592  endif
1593  call writefile(contents, filename)
1594  call setfperm(filename, 'rwxrwx---')
1595
1596  " Check if v:shell_error is equal to the exit status.
1597  let exitval = 0
1598  execute printf(':!%s%s %d', prefix, filename, exitval)
1599  call assert_equal(exitval, v:shell_error)
1600
1601  let exitval = 9
1602  execute printf(':!%s%s %d', prefix, filename, exitval)
1603  call assert_equal(exitval, v:shell_error)
1604
1605  set guioptions&
1606  call delete(filename)
1607endfunc
1608
1609func Test_terminal_hidden()
1610  if !has('unix')
1611    return
1612  endif
1613  term ++hidden cat
1614  let bnr = bufnr('$')
1615  call assert_equal('terminal', getbufvar(bnr, '&buftype'))
1616  exe 'sbuf ' . bnr
1617  call assert_equal('terminal', &buftype)
1618  call term_sendkeys(bnr, "asdf\<CR>")
1619  call WaitForAssert({-> assert_match('asdf', term_getline(bnr, 2))})
1620  call term_sendkeys(bnr, "\<C-D>")
1621  call WaitForAssert({-> assert_equal('finished', term_getstatus(bnr))})
1622  bwipe!
1623endfunc
1624
1625func Test_terminal_hidden_and_close()
1626  if !has('unix')
1627    return
1628  endif
1629  call assert_equal(1, winnr('$'))
1630  term ++hidden ++close ls
1631  let bnr = bufnr('$')
1632  call assert_equal('terminal', getbufvar(bnr, '&buftype'))
1633  call WaitForAssert({-> assert_false(bufexists(bnr))})
1634  call assert_equal(1, winnr('$'))
1635endfunc
1636