summaryrefslogtreecommitdiff
path: root/mnv/src/testdir/test_system.mnv
blob: b3f05d779d86a262193444f23250efec99960912 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
" Tests for system() and systemlist()

func Test_System()
  if !has('win32')
    call assert_equal("123\n", system('echo 123'))
    call assert_equal(['123'], systemlist('echo 123'))
    call assert_equal('123',   system('cat', '123'))
    call assert_equal(['123'], systemlist('cat', '123'))
    call assert_equal(["as\<NL>df"], systemlist('cat', ["as\<NL>df"]))
  else
    call assert_equal("123\n", system('echo 123'))
    call assert_equal(["123\r"], systemlist('echo 123'))
    call assert_equal("123\n",   system('more.com', '123'))
    call assert_equal(["123\r"], systemlist('more.com', '123'))
    call assert_equal(["as\r", "df\r"], systemlist('more.com', ["as\<NL>df"]))
  endif

  new Xdummy
  call setline(1, ['asdf', "pw\<NL>er", 'xxxx'])

  if executable('wc')
    let out = system('wc -l', bufnr('%'))
    " On OS/X we get leading spaces
    let out = substitute(out, '^ *', '', '')
    call assert_equal("3\n", out)

    let out = systemlist('wc -l', bufnr('%'))
    " On Windows we may get a trailing CR.
    if out != ["3\r"]
      " On OS/X we get leading spaces
      if type(out) == v:t_list
        let out[0] = substitute(out[0], '^ *', '', '')
      endif
      call assert_equal(['3'],  out)
    endif
  endif

  if !has('win32')
    let out = systemlist('cat', bufnr('%'))
    call assert_equal(['asdf', "pw\<NL>er", 'xxxx'],  out)
  else
    let out = systemlist('more.com', bufnr('%'))
    call assert_equal(["asdf\r", "pw\r", "er\r", "xxxx\r"],  out)
  endif
  bwipe!

  call assert_fails('call system("wc -l", 99999)', 'E86:')
endfunc

func Test_system_exmode()
  if has('unix') " echo $? only works on Unix
    let cmd = ' -es -c "source Xscript" +q; echo "result=$?"'
    " Need to put this in a script, "catch" isn't found after an unknown
    " function.
    call writefile(['try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript', 'D')
    let a = system(GetMNVCommand() . cmd)
    call assert_match('result=0', a)
    call assert_equal(0, v:shell_error)
  endif

  " Error before try does set error flag.
  call writefile(['call nosuchfunction()', 'try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript')
  if has('unix') " echo $? only works on Unix
    let a = system(GetMNVCommand() . cmd)
    call assert_notequal('0', a[0])
  endif

  let cmd = ' -es -c "source Xscript" +q'
  let a = system(GetMNVCommand() . cmd)
  call assert_notequal(0, v:shell_error)

  if has('unix') " echo $? only works on Unix
    let cmd = ' -es -c "call doesnotexist()" +q; echo $?'
    let a = system(GetMNVCommand() . cmd)
    call assert_notequal(0, a[0])
  endif

  let cmd = ' -es -c "call doesnotexist()" +q'
  let a = system(GetMNVCommand(). cmd)
  call assert_notequal(0, v:shell_error)

  if has('unix') " echo $? only works on Unix
    let cmd = ' -es -c "call doesnotexist()|let a=1" +q; echo $?'
    let a = system(GetMNVCommand() . cmd)
    call assert_notequal(0, a[0])
  endif

  let cmd = ' -es -c "call doesnotexist()|let a=1" +q'
  let a = system(GetMNVCommand() . cmd)
  call assert_notequal(0, v:shell_error)
endfunc

func Test_system_with_shell_quote()
  CheckMSWindows

  call mkdir('Xdir with spaces', 'p')
  call system('copy "%COMSPEC%" "Xdir with spaces\cmd.exe"')

  let shell_save = &shell
  let shellxquote_save = &shellxquote
  try
    " Set 'shell' always needs noshellslash.
    let shellslash_save = &shellslash
    set noshellslash
    let shell_tests = [
          \ expand('$COMSPEC'),
          \ '"' . fnamemodify('Xdir with spaces\cmd.exe', ':p') . '"',
          \]
    let &shellslash = shellslash_save

    let sxq_tests = ['', '(', '"']

    " Matrix tests: 'shell' * 'shellxquote'
    for shell in shell_tests
      let &shell = shell
      for sxq in sxq_tests
        let &shellxquote = sxq

        let msg = printf('shell=%s shellxquote=%s', &shell, &shellxquote)

        try
          let out = 'echo 123'->system()
        catch
          call assert_report(printf('%s: %s', msg, v:exception))
          continue
        endtry

        " On Windows we may get a trailing space and CR.
        if out != "123 \n"
          call assert_equal("123\n", out, msg)
        endif

      endfor
    endfor

  finally
    let &shell = shell_save
    let &shellxquote = shellxquote_save
    call delete('Xdir with spaces', 'rf')
  endtry
endfunc

" Check that MNV does not execute anything from current directory
func Test_windows_external_cmd_in_cwd()
  CheckMSWindows

  " just in case
  call system('rd /S /Q Xfolder')
  call mkdir('Xfolder', 'R')
  cd Xfolder

  let contents = ['@echo off', 'echo filename1.txt:1:AAAA']
  call writefile(contents, 'findstr.cmd')

  let file1 = ['AAAA', 'THIS FILE SHOULD NOT BE FOUND']
  let file2 = ['BBBB', 'THIS FILE SHOULD BE FOUND']

  call writefile(file1, 'filename1.txt')
  call writefile(file2, 'filename2.txt')

  if has('quickfix')
    " use silent to avoid hit-enter-prompt
    sil grep BBBB filename*.txt
    call assert_equal('filename2.txt', @%)
  endif

  let output = system('findstr BBBB filename*')
  " Match trailing newline byte
  call assert_match('filename2.txt:BBBB.', output)

  if has('gui')
    set guioptions+=!
    let output = system('findstr BBBB filename*')
    call assert_match('filename2.txt:BBBB.', output)
  endif

  cd -
  set guioptions&
endfunc

func Test_system_with_powershell()
  CheckPowerShell

  let shell_save = &shell
  let shellcmdflag_save = &shellcmdflag
  let shellxquote_save = &shellxquote
  let shellpipe_save = &shellpipe
  let shellredir_save = &shellredir
  try
    if executable('powershell')
       let &shell = 'powershell'
       let &shellcmdflag = '-Command'
       let &shellredir = '2>&1 | Out-File -Encoding default'
    else
       let &shell = 'pwsh'
       let &shellcmdflag = '-c'
       let &shellredir = '>%s 2>&1'
    endif
    let &shellxquote = has('win32') ? '"' : ''
    let &shellpipe = &shellredir

    " Make sure compound commands are handled properly.
    call assert_equal("123\n456\n", system('echo 123; echo 456'))
  finally
    let &shell = shell_save
    let &shellcmdflag = shellcmdflag_save
    let &shellxquote = shellxquote_save
    let &shellpipe = shellpipe_save
    let &shellredir = shellredir_save
  endtry
endfunc

func Test_system_list_arg()
  CheckExecutable python3

  " When the command is a List, it is executed directly without the shell.
  " Shell meta characters should not be interpreted but passed as-is.

  " Redirect characters should be passed literally.
  let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '<foo>'])
  call assert_match('^<foo>', out)

  " Environment variable syntax should not be expanded.
  if has('win32')
    let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '%USERPROFILE%'])
    call assert_match('^%USERPROFILE%', out)
  else
    let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '$HOME'])
    call assert_match('^\$HOME', out)
  endif

  " Spaces in arguments should be preserved without shell word splitting.
  let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', 'hello world'])
  call assert_match('^hello world', out)

  " Pipe and ampersand should be passed literally.
  let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', 'a&b|c'])
  call assert_match('^a&b|c', out)

  " systemlist() should work too.
  let out = systemlist(['python3', '-c', 'print("line1"); print("line2")'])
  call assert_match('^line1', out[0])
  call assert_match('^line2', out[1])

  " v:shell_error should be set.
  call system(['python3', '-c', 'import sys; sys.exit(42)'])
  call assert_equal(42, v:shell_error)
  call system(['python3', '-c', 'import sys; sys.exit(0)'])
  call assert_equal(0, v:shell_error)

  " Invalid arguments.
  call assert_fails('call system([])', 'E474:')
  call assert_fails('call systemlist([])', 'E474:')
endfunc

" mnv: shiftwidth=2 sts=2 expandtab