blob: 141f48ebd5f436f96656486b6662c527be08e129 [file] [log] [blame]
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001" Test various aspects of the Vim language.
2" This was formerly in test49.
3
4"-------------------------------------------------------------------------------
5" Test environment {{{1
6"-------------------------------------------------------------------------------
7
8com! XpathINIT let g:Xpath = ''
9com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args>
10
11" Append a message to the "messages" file
12func! Xout(text)
13 split messages
14 $put =a:text
15 wq
16endfunc
17
18com! -nargs=1 Xout call Xout(<args>)
19
20" MakeScript() - Make a script file from a function. {{{2
21"
22" Create a script that consists of the body of the function a:funcname.
23" Replace any ":return" by a ":finish", any argument variable by a global
24" variable, and and every ":call" by a ":source" for the next following argument
25" in the variable argument list. This function is useful if similar tests are
26" to be made for a ":return" from a function call or a ":finish" in a script
27" file.
28function! MakeScript(funcname, ...)
29 let script = tempname()
30 execute "redir! >" . script
31 execute "function" a:funcname
32 redir END
33 execute "edit" script
34 " Delete the "function" and the "endfunction" lines. Do not include the
35 " word "function" in the pattern since it might be translated if LANG is
36 " set. When MakeScript() is being debugged, this deletes also the debugging
37 " output of its line 3 and 4.
38 exec '1,/.*' . a:funcname . '(.*)/d'
39 /^\d*\s*endfunction\>/,$d
40 %s/^\d*//e
41 %s/return/finish/e
42 %s/\<a:\(\h\w*\)/g:\1/ge
43 normal gg0
44 let cnt = 0
45 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
46 let cnt = cnt + 1
47 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
48 endwhile
49 g/^\s*$/d
50 write
51 bwipeout
52 return script
53endfunction
54
55" ExecAsScript - Source a temporary script made from a function. {{{2
56"
57" Make a temporary script file from the function a:funcname, ":source" it, and
58" delete it afterwards.
59function! ExecAsScript(funcname)
60 " Make a script from the function passed as argument.
61 let script = MakeScript(a:funcname)
62
63 " Source and delete the script.
64 exec "source" script
65 call delete(script)
66endfunction
67
68com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
69
70
71"-------------------------------------------------------------------------------
72" Test 1: :endwhile in function {{{1
73"
74" Detect if a broken loop is (incorrectly) reactivated by the
75" :endwhile. Use a :return to prevent an endless loop, and make
76" this test first to get a meaningful result on an error before other
77" tests will hang.
78"-------------------------------------------------------------------------------
79
80function! T1_F()
81 Xpath 'a'
82 let first = 1
83 while 1
84 Xpath 'b'
85 if first
86 Xpath 'c'
87 let first = 0
88 break
89 else
90 Xpath 'd'
91 return
92 endif
93 endwhile
94endfunction
95
96function! T1_G()
97 Xpath 'h'
98 let first = 1
99 while 1
100 Xpath 'i'
101 if first
102 Xpath 'j'
103 let first = 0
104 break
105 else
106 Xpath 'k'
107 return
108 endif
109 if 1 " unmatched :if
110 endwhile
111endfunction
112
113func Test_endwhile_function()
114 XpathINIT
115 call T1_F()
116 Xpath 'F'
117
118 try
119 call T1_G()
120 catch
121 " Catch missing :endif
122 call assert_true(v:exception =~ 'E171')
123 Xpath 'x'
124 endtry
125 Xpath 'G'
126
127 call assert_equal('abcFhijxG', g:Xpath)
128endfunc
129
130"-------------------------------------------------------------------------------
131" Test 2: :endwhile in script {{{1
132"
133" Detect if a broken loop is (incorrectly) reactivated by the
134" :endwhile. Use a :finish to prevent an endless loop, and place
135" this test before others that might hang to get a meaningful result
136" on an error.
137"
138" This test executes the bodies of the functions T1_F and T1_G from
139" the previous test as script files (:return replaced by :finish).
140"-------------------------------------------------------------------------------
141
142func Test_endwhile_script()
143 XpathINIT
144 ExecAsScript T1_F
145 Xpath 'F'
146
147 try
148 ExecAsScript T1_G
149 catch
150 " Catch missing :endif
151 call assert_true(v:exception =~ 'E171')
152 Xpath 'x'
153 endtry
154 Xpath 'G'
155
156 call assert_equal('abcFhijxG', g:Xpath)
157endfunc
158
159"-------------------------------------------------------------------------------
160" Test 3: :if, :elseif, :while, :continue, :break {{{1
161"-------------------------------------------------------------------------------
162
163function Test_if_while()
164 XpathINIT
165 if 1
166 Xpath 'a'
167 let loops = 3
168 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
169 if loops <= 0
170 let break_err = 1
171 let loops = -1
172 else
173 Xpath 'b' . loops
174 endif
175 if (loops == 2)
176 while loops == 2 " dummy loop
177 Xpath 'c' . loops
178 let loops = loops - 1
179 continue " stop dummy loop
180 Xpath 'd' . loops
181 endwhile
182 continue " continue main loop
183 Xpath 'e' . loops
184 elseif (loops == 1)
185 let p = 1
186 while p " dummy loop
187 Xpath 'f' . loops
188 let p = 0
189 break " break dummy loop
190 Xpath 'g' . loops
191 endwhile
192 Xpath 'h' . loops
193 unlet p
194 break " break main loop
195 Xpath 'i' . loops
196 endif
197 if (loops > 0)
198 Xpath 'j' . loops
199 endif
200 while loops == 3 " dummy loop
201 let loops = loops - 1
202 endwhile " end dummy loop
203 endwhile " end main loop
204 Xpath 'k'
205 else
206 Xpath 'l'
207 endif
208 Xpath 'm'
209 if exists("break_err")
210 Xpath 'm'
211 unlet break_err
212 endif
213
214 unlet loops
215
216 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
217endfunc
218
219"-------------------------------------------------------------------------------
220" Test 4: :return {{{1
221"-------------------------------------------------------------------------------
222
223function! T4_F()
224 if 1
225 Xpath 'a'
226 let loops = 3
227 while loops > 0 " 3: 2: 1:
228 Xpath 'b' . loops
229 if (loops == 2)
230 Xpath 'c' . loops
231 return
232 Xpath 'd' . loops
233 endif
234 Xpath 'e' . loops
235 let loops = loops - 1
236 endwhile
237 Xpath 'f'
238 else
239 Xpath 'g'
240 endif
241endfunction
242
243function Test_return()
244 XpathINIT
245 call T4_F()
246 Xpath '4'
247
248 call assert_equal('ab3e3b2c24', g:Xpath)
249endfunction
250
251
252"-------------------------------------------------------------------------------
253" Test 5: :finish {{{1
254"
255" This test executes the body of the function T4_F from the previous
256" test as a script file (:return replaced by :finish).
257"-------------------------------------------------------------------------------
258
259function Test_finish()
260 XpathINIT
261 ExecAsScript T4_F
262 Xpath '5'
263
264 call assert_equal('ab3e3b2c25', g:Xpath)
265endfunction
266
267
268
269"-------------------------------------------------------------------------------
270" Test 6: Defining functions in :while loops {{{1
271"
272" Functions can be defined inside other functions. An inner function
273" gets defined when the outer function is executed. Functions may
274" also be defined inside while loops. Expressions in braces for
275" defining the function name are allowed.
276"
277" The functions are defined when sourcing the script, only the
278" resulting path is checked in the test function.
279"-------------------------------------------------------------------------------
280
281XpathINIT
282
283" The command CALL collects the argument of all its invocations in "calls"
284" when used from a function (that is, when the global variable "calls" needs
285" the "g:" prefix). This is to check that the function code is skipped when
286" the function is defined. For inner functions, do so only if the outer
287" function is not being executed.
288"
289let calls = ""
290com! -nargs=1 CALL
291 \ if !exists("calls") && !exists("outer") |
292 \ let g:calls = g:calls . <args> |
293 \ endif
294
295let i = 0
296while i < 3
297 let i = i + 1
298 if i == 1
299 Xpath 'a'
300 function! F1(arg)
301 CALL a:arg
302 let outer = 1
303
304 let j = 0
305 while j < 1
306 Xpath 'b'
307 let j = j + 1
308 function! G1(arg)
309 CALL a:arg
310 endfunction
311 Xpath 'c'
312 endwhile
313 endfunction
314 Xpath 'd'
315
316 continue
317 endif
318
319 Xpath 'e' . i
320 function! F{i}(i, arg)
321 CALL a:arg
322 let outer = 1
323
324 if a:i == 3
325 Xpath 'f'
326 endif
327 let k = 0
328 while k < 3
329 Xpath 'g' . k
330 let k = k + 1
331 function! G{a:i}{k}(arg)
332 CALL a:arg
333 endfunction
334 Xpath 'h' . k
335 endwhile
336 endfunction
337 Xpath 'i'
338
339endwhile
340
341if exists("*G1")
342 Xpath 'j'
343endif
344if exists("*F1")
345 call F1("F1")
346 if exists("*G1")
347 call G1("G1")
348 endif
349endif
350
351if exists("G21") || exists("G22") || exists("G23")
352 Xpath 'k'
353endif
354if exists("*F2")
355 call F2(2, "F2")
356 if exists("*G21")
357 call G21("G21")
358 endif
359 if exists("*G22")
360 call G22("G22")
361 endif
362 if exists("*G23")
363 call G23("G23")
364 endif
365endif
366
367if exists("G31") || exists("G32") || exists("G33")
368 Xpath 'l'
369endif
370if exists("*F3")
371 call F3(3, "F3")
372 if exists("*G31")
373 call G31("G31")
374 endif
375 if exists("*G32")
376 call G32("G32")
377 endif
378 if exists("*G33")
379 call G33("G33")
380 endif
381endif
382
383Xpath 'm'
384
385let g:test6_result = g:Xpath
386let g:test6_calls = calls
387
388unlet calls
389delfunction F1
390delfunction G1
391delfunction F2
392delfunction G21
393delfunction G22
394delfunction G23
395delfunction G31
396delfunction G32
397delfunction G33
398
399function Test_defining_functions()
400 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
401 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
402endfunc
403
404"-------------------------------------------------------------------------------
405" Modelines {{{1
406" vim: ts=8 sw=4 tw=80 fdm=marker
407" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
408"-------------------------------------------------------------------------------