xref: /vim-8.2.3635/src/testdir/test_signs.vim (revision 5c56da4d)
1" Test for signs
2
3source check.vim
4CheckFeature signs
5
6source screendump.vim
7
8func Test_sign()
9  new
10  call setline(1, ['a', 'b', 'c', 'd'])
11
12  " Define some signs.
13  " We can specify icons even if not all versions of vim support icons as
14  " icon is ignored when not supported.  "(not supported)" is shown after
15  " the icon name when listing signs.
16  sign define Sign1 text=x
17
18  call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png')
19
20  " Test listing signs.
21  let a=execute('sign list')
22  call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' .
23	      \ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' .
24	      \ 'linehl=Error texthl=Title$', a)
25
26  let a=execute('sign list Sign1')
27  call assert_equal("\nsign Sign1 text=x ", a)
28
29  " Split the window to the bottom to verify sign jump will stay in the
30  " current window if the buffer is displayed there.
31  let bn = bufnr('%')
32  let wn = winnr()
33  exe 'sign place 41 line=3 name=Sign1 buffer=' . bn
34  1
35  bot split
36  exe 'sign jump 41 buffer=' . bufnr('%')
37  call assert_equal('c', getline('.'))
38  call assert_equal(3, winnr())
39  call assert_equal(bn, bufnr('%'))
40  call assert_notequal(wn, winnr())
41
42  " Create a new buffer and check that ":sign jump" switches to the old buffer.
43  1
44  new foo
45  call assert_notequal(bn, bufnr('%'))
46  exe 'sign jump 41 buffer=' . bn
47  call assert_equal(bn, bufnr('%'))
48  call assert_equal('c', getline('.'))
49
50  " Redraw to make sure that screen redraw with sign gets exercised,
51  " with and without 'rightleft'.
52  if has('rightleft')
53    set rightleft
54    redraw
55    set norightleft
56  endif
57  redraw
58
59  " Check that we can't change sign.
60  call assert_fails("sign place 40 name=Sign1 buffer=" . bufnr('%'), 'E885:')
61
62  " Check placed signs
63  let a=execute('sign place')
64  call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" .
65		\ "    line=3  id=41  name=Sign1  priority=10\n", a)
66
67  " Unplace the sign and try jumping to it again should fail.
68  sign unplace 41
69  1
70  call assert_fails("sign jump 41 buffer=" . bufnr('%'), 'E157:')
71  call assert_equal('a', getline('.'))
72
73  " Unplace sign on current line.
74  exe 'sign place 42 line=4 name=Sign2 buffer=' . bufnr('%')
75  4
76  sign unplace
77  let a=execute('sign place')
78  call assert_equal("\n--- Signs ---\n", a)
79
80  " Try again to unplace sign on current line, it should fail this time.
81  call assert_fails('sign unplace', 'E159:')
82
83  " Unplace all signs.
84  exe 'sign place 41 line=3 name=Sign1 buffer=' . bufnr('%')
85  sign unplace *
86  let a=execute('sign place')
87  call assert_equal("\n--- Signs ---\n", a)
88
89  " Place a sign without specifying the filename or buffer
90  sign place 77 line=9 name=Sign2
91  let a=execute('sign place')
92  call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" .
93		\ "    line=9  id=77  name=Sign2  priority=10\n", a)
94  sign unplace *
95
96  " Check :jump with file=...
97  edit foo
98  call setline(1, ['A', 'B', 'C', 'D'])
99
100  call Sign_command_ignore_error('sign define Sign3 text=y texthl=DoesNotExist linehl=DoesNotExist icon=doesnotexist.xpm')
101
102  let fn = expand('%:p')
103  exe 'sign place 43 line=2 name=Sign3 file=' . fn
104  edit bar
105  call assert_notequal(fn, expand('%:p'))
106  exe 'sign jump 43 file=' . fn
107  call assert_equal('B', getline('.'))
108
109  " Check for jumping to a sign in a hidden buffer
110  enew! | only!
111  edit foo
112  call setline(1, ['A', 'B', 'C', 'D'])
113  let fn = expand('%:p')
114  exe 'sign place 21 line=3 name=Sign3 file=' . fn
115  hide edit bar
116  exe 'sign jump 21 file=' . fn
117  call assert_equal('C', getline('.'))
118
119  " can't define a sign with a non-printable character as text
120  call assert_fails("sign define Sign4 text=\e linehl=Comment", 'E239:')
121  call assert_fails("sign define Sign4 text=a\e linehl=Comment", 'E239:')
122  call assert_fails("sign define Sign4 text=\ea linehl=Comment", 'E239:')
123
124  " Only 1 or 2 character text is allowed
125  call assert_fails("sign define Sign4 text=abc linehl=Comment", 'E239:')
126  call assert_fails("sign define Sign4 text= linehl=Comment", 'E239:')
127  call assert_fails("sign define Sign4 text=\\ ab  linehl=Comment", 'E239:')
128
129  " define sign with whitespace
130  sign define Sign4 text=\ X linehl=Comment
131  sign undefine Sign4
132  sign define Sign4 linehl=Comment text=\ X
133  sign undefine Sign4
134
135  sign define Sign5 text=X\  linehl=Comment
136  sign undefine Sign5
137  sign define Sign5 linehl=Comment text=X\
138  sign undefine Sign5
139
140  " define sign with backslash
141  sign define Sign4 text=\\\\ linehl=Comment
142  sign undefine Sign4
143  sign define Sign4 text=\\ linehl=Comment
144  sign undefine Sign4
145
146  " define a sign with a leading 0 in the name
147  sign unplace *
148  sign define 004 text=#> linehl=Comment
149  let a = execute('sign list 4')
150  call assert_equal("\nsign 4 text=#> linehl=Comment", a)
151  exe 'sign place 20 line=3 name=004 buffer=' . bufnr('')
152  let a = execute('sign place')
153  call assert_equal("\n--- Signs ---\nSigns for foo:\n" .
154		\ "    line=3  id=20  name=4  priority=10\n", a)
155  exe 'sign unplace 20 buffer=' . bufnr('')
156  sign undefine 004
157  call assert_fails('sign list 4', 'E155:')
158
159  " After undefining the sign, we should no longer be able to place it.
160  sign undefine Sign1
161  sign undefine Sign2
162  sign undefine Sign3
163  call assert_fails("sign place 41 line=3 name=Sign1 buffer=" .
164			  \ bufnr('%'), 'E155:')
165endfunc
166
167" Undefining placed sign is not recommended.
168" Quoting :help sign
169"
170" :sign undefine {name}
171"                Deletes a previously defined sign.  If signs with this {name}
172"                are still placed this will cause trouble.
173func Test_sign_undefine_still_placed()
174  new foobar
175  sign define Sign text=x
176  exe 'sign place 41 line=1 name=Sign buffer=' . bufnr('%')
177  sign undefine Sign
178
179  " Listing placed sign should show that sign is deleted.
180  let a=execute('sign place')
181  call assert_equal("\n--- Signs ---\nSigns for foobar:\n" .
182		\ "    line=1  id=41  name=[Deleted]  priority=10\n", a)
183
184  sign unplace 41
185  let a=execute('sign place')
186  call assert_equal("\n--- Signs ---\n", a)
187endfunc
188
189func Test_sign_completion()
190  sign define Sign1 text=x
191  sign define Sign2 text=y
192
193  call feedkeys(":sign \<C-A>\<C-B>\"\<CR>", 'tx')
194  call assert_equal('"sign define jump list place undefine unplace', @:)
195
196  call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx')
197  call assert_equal('"sign define Sign icon= linehl= text= texthl=', @:)
198
199  call feedkeys(":sign define Sign linehl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
200  call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
201	      \ 'SpellLocal SpellRare', @:)
202
203  call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
204  call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
205	      \ 'SpellLocal SpellRare', @:)
206
207  call writefile(repeat(["Sun is shining"], 30), "XsignOne")
208  call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
209  call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
210  call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
211
212  " Test for completion of arguments to ':sign undefine'
213  call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
214  call assert_equal('"sign undefine Sign1 Sign2', @:)
215
216  call feedkeys(":sign place 1 \<C-A>\<C-B>\"\<CR>", 'tx')
217  call assert_equal('"sign place 1 buffer= file= group= line= name= priority=',
218	      \ @:)
219
220  call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
221  call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
222
223  edit XsignOne
224  sign place 1 name=Sign1 line=5
225  sign place 1 name=Sign1 group=g1 line=10
226  edit XsignTwo
227  sign place 1 name=Sign2 group=g2 line=15
228
229  " Test for completion of group= and file= arguments to ':sign place'
230  call feedkeys(":sign place 1 name=Sign1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
231  call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:)
232  call feedkeys(":sign place 1 name=Sign1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
233  call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:)
234
235  " Test for completion of arguments to 'sign place' without sign identifier
236  call feedkeys(":sign place \<C-A>\<C-B>\"\<CR>", 'tx')
237  call assert_equal('"sign place buffer= file= group=', @:)
238  call feedkeys(":sign place file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
239  call assert_equal('"sign place file=XsignOne XsignTwo', @:)
240  call feedkeys(":sign place group=\<C-A>\<C-B>\"\<CR>", 'tx')
241  call assert_equal('"sign place group=g1 g2', @:)
242  call feedkeys(":sign place group=g1 file=\<C-A>\<C-B>\"\<CR>", 'tx')
243  call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:)
244
245  " Test for completion of arguments to ':sign unplace'
246  call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
247  call assert_equal('"sign unplace 1 buffer= file= group=', @:)
248  call feedkeys(":sign unplace 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
249  call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:)
250  call feedkeys(":sign unplace 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
251  call assert_equal('"sign unplace 1 group=g1 g2', @:)
252  call feedkeys(":sign unplace 1 group=g2 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
253  call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:)
254
255  " Test for completion of arguments to ':sign list'
256  call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
257  call assert_equal('"sign list Sign1 Sign2', @:)
258
259  " Test for completion of arguments to ':sign jump'
260  call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
261  call assert_equal('"sign jump 1 buffer= file= group=', @:)
262  call feedkeys(":sign jump 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
263  call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:)
264  call feedkeys(":sign jump 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
265  call assert_equal('"sign jump 1 group=g1 g2', @:)
266
267  " Error cases
268  call feedkeys(":sign here\<C-A>\<C-B>\"\<CR>", 'tx')
269  call assert_equal('"sign here', @:)
270  call feedkeys(":sign define Sign here=\<C-A>\<C-B>\"\<CR>", 'tx')
271  call assert_equal("\"sign define Sign here=\<C-A>", @:)
272  call feedkeys(":sign place 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
273  call assert_equal("\"sign place 1 here=\<C-A>", @:)
274  call feedkeys(":sign jump 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
275  call assert_equal("\"sign jump 1 here=\<C-A>", @:)
276  call feedkeys(":sign here there\<C-A>\<C-B>\"\<CR>", 'tx')
277  call assert_equal("\"sign here there\<C-A>", @:)
278  call feedkeys(":sign here there=\<C-A>\<C-B>\"\<CR>", 'tx')
279  call assert_equal("\"sign here there=\<C-A>", @:)
280
281  sign unplace * group=*
282  sign undefine Sign1
283  sign undefine Sign2
284  enew
285  call delete('XsignOne')
286  call delete('XsignTwo')
287endfunc
288
289func Test_sign_invalid_commands()
290  sign define Sign1 text=x
291
292  call assert_fails('sign', 'E471:')
293  call assert_fails('sign jump', 'E471:')
294  call assert_fails('sign xxx', 'E160:')
295  call assert_fails('sign define', 'E156:')
296  call assert_fails('sign define Sign1 xxx', 'E475:')
297  call assert_fails('sign undefine', 'E156:')
298  call assert_fails('sign list xxx', 'E155:')
299  call assert_fails('sign place 1 buffer=999', 'E158:')
300  call assert_fails('sign place 1 name=Sign1 buffer=999', 'E158:')
301  call assert_fails('sign place buffer=999', 'E158:')
302  call assert_fails('sign jump buffer=999', 'E158:')
303  call assert_fails('sign jump 1 file=', 'E158:')
304  call assert_fails('sign jump 1 group=', 'E474:')
305  call assert_fails('sign jump 1 name=', 'E474:')
306  call assert_fails('sign jump 1 name=Sign1', 'E474:')
307  call assert_fails('sign jump 1 line=100', '474:')
308  call assert_fails('sign define Sign2 text=', 'E239:')
309  " Non-numeric identifier for :sign place
310  call assert_fails("sign place abc line=3 name=Sign1 buffer=" . bufnr(''),
311								\ 'E474:')
312  " Non-numeric identifier for :sign unplace
313  call assert_fails("sign unplace abc name=Sign1 buffer=" . bufnr(''),
314								\ 'E474:')
315  " Number followed by an alphabet as sign identifier for :sign place
316  call assert_fails("sign place 1abc line=3 name=Sign1 buffer=" . bufnr(''),
317								\ 'E474:')
318  " Number followed by an alphabet as sign identifier for :sign unplace
319  call assert_fails("sign unplace 2abc name=Sign1 buffer=" . bufnr(''),
320								\ 'E474:')
321  " Sign identifier and '*' for :sign unplace
322  call assert_fails("sign unplace 2 *", 'E474:')
323  " Trailing characters after buffer number for :sign place
324  call assert_fails("sign place 1 line=3 name=Sign1 buffer=" .
325						\ bufnr('%') . 'xxx', 'E488:')
326  " Trailing characters after buffer number for :sign unplace
327  call assert_fails("sign unplace 1 buffer=" . bufnr('%') . 'xxx', 'E488:')
328  call assert_fails("sign unplace * buffer=" . bufnr('%') . 'xxx', 'E488:')
329  call assert_fails("sign unplace 1 xxx", 'E474:')
330  call assert_fails("sign unplace * xxx", 'E474:')
331  call assert_fails("sign unplace xxx", 'E474:')
332  " Placing a sign without line number
333  call assert_fails("sign place name=Sign1 buffer=" . bufnr('%'), 'E474:')
334  " Placing a sign without sign name
335  call assert_fails("sign place line=10 buffer=" . bufnr('%'), 'E474:')
336  " Unplacing a sign with line number
337  call assert_fails("sign unplace 2 line=10 buffer=" . bufnr('%'), 'E474:')
338  " Unplacing a sign with sign name
339  call assert_fails("sign unplace 2 name=Sign1 buffer=" . bufnr('%'), 'E474:')
340  " Placing a sign without sign name
341  call assert_fails("sign place 2 line=3 buffer=" . bufnr('%'), 'E474:')
342  " Placing a sign with only sign identifier
343  call assert_fails("sign place 2", 'E474:')
344  " Placing a sign with only a name
345  call assert_fails("sign place abc", 'E474:')
346  " Placing a sign with only line number
347  call assert_fails("sign place 5 line=3", 'E474:')
348  " Placing a sign with only sign group
349  call assert_fails("sign place 5 group=g1", 'E474:')
350  call assert_fails("sign place 5 group=*", 'E474:')
351  " Placing a sign with only sign priority
352  call assert_fails("sign place 5 priority=10", 'E474:')
353
354  sign undefine Sign1
355endfunc
356
357func Test_sign_delete_buffer()
358  new
359  sign define Sign text=x
360  let bufnr = bufnr('%')
361  new
362  exe 'bd ' . bufnr
363  exe 'sign place 61 line=3 name=Sign buffer=' . bufnr
364  call assert_fails('sign jump 61 buffer=' . bufnr, 'E934:')
365  sign unplace 61
366  sign undefine Sign
367endfunc
368
369" Ignore error: E255: Couldn't read in sign data!
370" This error can happen when running in the GUI.
371" Some gui like Motif do not support the png icon format.
372func Sign_command_ignore_error(cmd)
373  try
374    exe a:cmd
375  catch /E255:/
376  endtry
377endfunc
378
379" ignore error: E255: Couldn't read in sign data!
380" This error can happen when running in gui.
381func Sign_define_ignore_error(name, attr)
382  try
383    call sign_define(a:name, a:attr)
384  catch /E255:/
385  endtry
386endfunc
387
388" Test for Vim script functions for managing signs
389func Test_sign_funcs()
390  " Remove all the signs
391  call sign_unplace('*')
392  call sign_undefine()
393
394  " Tests for sign_define()
395  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
396  call assert_equal(0, "sign1"->sign_define(attr))
397  call assert_equal([{'name' : 'sign1', 'texthl' : 'Error',
398	      \ 'linehl' : 'Search', 'text' : '=>'}], sign_getdefined())
399
400  " Define a new sign without attributes and then update it
401  call sign_define("sign2")
402  let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
403	      \ 'icon' : 'sign2.ico'}
404  call Sign_define_ignore_error("sign2", attr)
405  call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
406	      \ 'linehl' : 'DiffAdd', 'text' : '!!', 'icon' : 'sign2.ico'}],
407	      \ "sign2"->sign_getdefined())
408
409  " Test for a sign name with digits
410  call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))
411  call assert_equal([{'name' : '2', 'linehl' : 'StatusLine'}],
412	      \ sign_getdefined(0002))
413  eval 0002->sign_undefine()
414
415  " Tests for invalid arguments to sign_define()
416  call assert_fails('call sign_define("sign4", {"text" : "===>"})', 'E239:')
417  call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:')
418  call assert_fails('call sign_define({})', 'E731:')
419  call assert_fails('call sign_define("sign6", [])', 'E715:')
420
421  " Tests for sign_getdefined()
422  call assert_equal([], sign_getdefined("none"))
423  call assert_fails('call sign_getdefined({})', 'E731:')
424
425  " Tests for sign_place()
426  call writefile(repeat(["Sun is shining"], 30), "Xsign")
427  edit Xsign
428
429  call assert_equal(10, sign_place(10, '', 'sign1', 'Xsign',
430	      \ {'lnum' : 20}))
431  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
432	      \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
433	      \ 'priority' : 10}]}], sign_getplaced('Xsign'))
434  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
435	      \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
436	      \ 'priority' : 10}]}],
437	      \ '%'->sign_getplaced({'lnum' : 20}))
438  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
439	      \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
440	      \ 'priority' : 10}]}],
441	      \ sign_getplaced('', {'id' : 10}))
442
443  " Tests for invalid arguments to sign_place()
444  call assert_fails('call sign_place([], "", "mySign", 1)', 'E745:')
445  call assert_fails('call sign_place(5, "", "mySign", -1)', 'E158:')
446  call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])',
447	      \ 'E715:')
448  call assert_fails('call sign_place(-1, "", "sign1", "Xsign",
449	      \ {"lnum" : 30})', 'E474:')
450  call assert_fails('call sign_place(10, "", "xsign1x", "Xsign",
451	      \ {"lnum" : 30})', 'E155:')
452  call assert_fails('call sign_place(10, "", "", "Xsign",
453	      \ {"lnum" : 30})', 'E155:')
454  call assert_fails('call sign_place(10, "", [], "Xsign",
455	      \ {"lnum" : 30})', 'E730:')
456  call assert_fails('call sign_place(5, "", "sign1", "abcxyz.xxx",
457	      \ {"lnum" : 10})', 'E158:')
458  call assert_fails('call sign_place(5, "", "sign1", "@", {"lnum" : 10})',
459	      \ 'E158:')
460  call assert_fails('call sign_place(5, "", "sign1", [], {"lnum" : 10})',
461	      \ 'E730:')
462  call assert_fails('call sign_place(21, "", "sign1", "Xsign",
463	      \ {"lnum" : -1})', 'E474:')
464  call assert_fails('call sign_place(22, "", "sign1", "Xsign",
465	      \ {"lnum" : 0})', 'E474:')
466  call assert_fails('call sign_place(22, "", "sign1", "Xsign",
467	      \ {"lnum" : []})', 'E745:')
468  call assert_equal(-1, sign_place(1, "*", "sign1", "Xsign", {"lnum" : 10}))
469
470  " Tests for sign_getplaced()
471  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
472	      \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
473	      \ 'priority' : 10}]}],
474	      \ sign_getplaced(bufnr('Xsign')))
475  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
476	      \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
477	      \ 'priority' : 10}]}],
478	      \ sign_getplaced())
479  call assert_fails("call sign_getplaced('dummy.sign')", 'E158:')
480  call assert_fails('call sign_getplaced("&")', 'E158:')
481  call assert_fails('call sign_getplaced(-1)', 'E158:')
482  call assert_fails('call sign_getplaced("Xsign", [])', 'E715:')
483  call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}],
484	      \ sign_getplaced('Xsign', {'lnum' : 1000000}))
485  call assert_fails("call sign_getplaced('Xsign', {'lnum' : []})",
486	      \ 'E745:')
487  call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}],
488	      \ sign_getplaced('Xsign', {'id' : 44}))
489  call assert_fails("call sign_getplaced('Xsign', {'id' : []})",
490	      \ 'E745:')
491
492  " Tests for sign_unplace()
493  eval 20->sign_place('', 'sign2', 'Xsign', {"lnum" : 30})
494  call assert_equal(0, sign_unplace('',
495	      \ {'id' : 20, 'buffer' : 'Xsign'}))
496  call assert_equal(-1, ''->sign_unplace(
497	      \ {'id' : 30, 'buffer' : 'Xsign'}))
498  call sign_place(20, '', 'sign2', 'Xsign', {"lnum" : 30})
499  call assert_fails("call sign_unplace('',
500	      \ {'id' : 20, 'buffer' : 'buffer.c'})", 'E158:')
501  call assert_fails("call sign_unplace('',
502	      \ {'id' : 20, 'buffer' : '&'})", 'E158:')
503  call assert_fails("call sign_unplace('g1',
504	      \ {'id' : 20, 'buffer' : 200})", 'E158:')
505  call assert_fails("call sign_unplace('g1', 'mySign')", 'E715:')
506
507  call sign_unplace('*')
508
509  " Test for modifying a placed sign
510  call assert_equal(15, sign_place(15, '', 'sign1', 'Xsign', {'lnum' : 20}))
511  call assert_equal(15, sign_place(15, '', 'sign2', 'Xsign'))
512  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
513	      \ [{'id' : 15, 'group' : '', 'lnum' : 20, 'name' : 'sign2',
514	      \ 'priority' : 10}]}],
515	      \ sign_getplaced())
516
517  " Tests for sign_undefine()
518  call assert_equal(0, sign_undefine("sign1"))
519  call assert_equal([], sign_getdefined("sign1"))
520  call assert_fails('call sign_undefine("none")', 'E155:')
521  call assert_fails('call sign_undefine({})', 'E731:')
522
523  " Test for using '.' as the line number for sign_place()
524  call Sign_define_ignore_error("sign1", attr)
525  call cursor(22, 1)
526  call assert_equal(15, sign_place(15, '', 'sign1', 'Xsign',
527	      \ {'lnum' : '.'}))
528  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
529	      \ [{'id' : 15, 'group' : '', 'lnum' : 22, 'name' : 'sign1',
530	      \ 'priority' : 10}]}],
531	      \ sign_getplaced('%', {'lnum' : 22}))
532
533  call delete("Xsign")
534  call sign_unplace('*')
535  call sign_undefine()
536  enew | only
537endfunc
538
539" Tests for sign groups
540func Test_sign_group()
541  enew | only
542  " Remove all the signs
543  call sign_unplace('*')
544  call sign_undefine()
545
546  call writefile(repeat(["Sun is shining"], 30), "Xsign")
547
548  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
549  call assert_equal(0, sign_define("sign1", attr))
550
551  edit Xsign
552  let bnum = bufnr('%')
553
554  " Error case
555  call assert_fails("call sign_place(5, [], 'sign1', 'Xsign',
556	      \ {'lnum' : 30})", 'E730:')
557
558  " place three signs with the same identifier. One in the global group and
559  " others in the named groups
560  call assert_equal(5, sign_place(5, '', 'sign1', 'Xsign',
561	      \ {'lnum' : 10}))
562  call assert_equal(5, sign_place(5, 'g1', 'sign1', bnum, {'lnum' : 20}))
563  call assert_equal(5, sign_place(5, 'g2', 'sign1', bnum, {'lnum' : 30}))
564
565  " Test for sign_getplaced() with group
566  let s = sign_getplaced('Xsign')
567  call assert_equal(1, len(s[0].signs))
568  call assert_equal(s[0].signs[0].group, '')
569  let s = sign_getplaced(bnum, {'group' : ''})
570  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
571	      \ 'priority' : 10}], s[0].signs)
572  call assert_equal(1, len(s[0].signs))
573  let s = sign_getplaced(bnum, {'group' : 'g2'})
574  call assert_equal('g2', s[0].signs[0].group)
575  let s = sign_getplaced(bnum, {'group' : 'g3'})
576  call assert_equal([], s[0].signs)
577  let s = sign_getplaced(bnum, {'group' : '*'})
578  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
579	      \ 'priority' : 10},
580	      \ {'id' : 5, 'group' : 'g1', 'name' : 'sign1', 'lnum' : 20,
581	      \  'priority' : 10},
582	      \ {'id' : 5, 'group' : 'g2', 'name' : 'sign1', 'lnum' : 30,
583	      \  'priority' : 10}],
584	      \ s[0].signs)
585
586  " Test for sign_getplaced() with id
587  let s = sign_getplaced(bnum, {'id' : 5})
588  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
589	      \ 'priority' : 10}],
590	      \ s[0].signs)
591  let s = sign_getplaced(bnum, {'id' : 5, 'group' : 'g2'})
592  call assert_equal(
593	      \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
594	      \ 'priority' : 10}],
595	      \ s[0].signs)
596  let s = sign_getplaced(bnum, {'id' : 5, 'group' : '*'})
597  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
598	      \ 'priority' : 10},
599	      \ {'id' : 5, 'group' : 'g1', 'name' : 'sign1', 'lnum' : 20,
600	      \ 'priority' : 10},
601	      \ {'id' : 5, 'group' : 'g2', 'name' : 'sign1', 'lnum' : 30,
602	      \ 'priority' : 10}],
603	      \ s[0].signs)
604  let s = sign_getplaced(bnum, {'id' : 5, 'group' : 'g3'})
605  call assert_equal([], s[0].signs)
606
607  " Test for sign_getplaced() with lnum
608  let s = sign_getplaced(bnum, {'lnum' : 20})
609  call assert_equal([], s[0].signs)
610  let s = sign_getplaced(bnum, {'lnum' : 20, 'group' : 'g1'})
611  call assert_equal(
612	      \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : 'g1',
613	      \ 'priority' : 10}],
614	      \ s[0].signs)
615  let s = sign_getplaced(bnum, {'lnum' : 30, 'group' : '*'})
616  call assert_equal(
617	      \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
618	      \ 'priority' : 10}],
619	      \ s[0].signs)
620  let s = sign_getplaced(bnum, {'lnum' : 40, 'group' : '*'})
621  call assert_equal([], s[0].signs)
622
623  " Error case
624  call assert_fails("call sign_getplaced(bnum, {'group' : []})",
625	      \ 'E730:')
626
627  " Clear the sign in global group
628  call sign_unplace('', {'id' : 5, 'buffer' : bnum})
629  let s = sign_getplaced(bnum, {'group' : '*'})
630  call assert_equal([
631	      \ {'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : 'g1',
632	      \ 'priority' : 10},
633	      \ {'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
634	      \ 'priority' : 10}],
635	      \ s[0].signs)
636
637  " Clear the sign in one of the groups
638  call sign_unplace('g1', {'buffer' : 'Xsign'})
639  let s = sign_getplaced(bnum, {'group' : '*'})
640  call assert_equal([
641	      \ {'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
642	      \ 'priority' : 10}],
643	      \ s[0].signs)
644
645  " Clear all the signs from the buffer
646  call sign_unplace('*', {'buffer' : bnum})
647  call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs)
648
649  " Clear sign across groups using an identifier
650  call sign_place(25, '', 'sign1', bnum, {'lnum' : 10})
651  call sign_place(25, 'g1', 'sign1', bnum, {'lnum' : 11})
652  call sign_place(25, 'g2', 'sign1', bnum, {'lnum' : 12})
653  call assert_equal(0, sign_unplace('*', {'id' : 25}))
654  call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs)
655
656  " Error case
657  call assert_fails("call sign_unplace({})", 'E474:')
658
659  " Place a sign in the global group and try to delete it using a group
660  call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10}))
661  call assert_equal(-1, sign_unplace('g1', {'id' : 5}))
662
663  " Place signs in multiple groups and delete all the signs in one of the
664  " group
665  call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10}))
666  call assert_equal(6, sign_place(6, '', 'sign1', bnum, {'lnum' : 11}))
667  call assert_equal(5, sign_place(5, 'g1', 'sign1', bnum, {'lnum' : 10}))
668  call assert_equal(5, sign_place(5, 'g2', 'sign1', bnum, {'lnum' : 10}))
669  call assert_equal(6, sign_place(6, 'g1', 'sign1', bnum, {'lnum' : 11}))
670  call assert_equal(6, sign_place(6, 'g2', 'sign1', bnum, {'lnum' : 11}))
671  call assert_equal(0, sign_unplace('g1'))
672  let s = sign_getplaced(bnum, {'group' : 'g1'})
673  call assert_equal([], s[0].signs)
674  let s = sign_getplaced(bnum)
675  call assert_equal(2, len(s[0].signs))
676  let s = sign_getplaced(bnum, {'group' : 'g2'})
677  call assert_equal('g2', s[0].signs[0].group)
678  call assert_equal(0, sign_unplace('', {'id' : 5}))
679  call assert_equal(0, sign_unplace('', {'id' : 6}))
680  let s = sign_getplaced(bnum, {'group' : 'g2'})
681  call assert_equal('g2', s[0].signs[0].group)
682  call assert_equal(0, sign_unplace('', {'buffer' : bnum}))
683
684  call sign_unplace('*')
685
686  " Test for :sign command and groups
687  sign place 5 line=10 name=sign1 file=Xsign
688  sign place 5 group=g1 line=10 name=sign1 file=Xsign
689  sign place 5 group=g2 line=10 name=sign1 file=Xsign
690
691  " Tests for the ':sign place' command
692
693  " :sign place file={fname}
694  let a = execute('sign place file=Xsign')
695  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
696	      \ "    line=10  id=5  name=sign1  priority=10\n", a)
697
698  " :sign place group={group} file={fname}
699  let a = execute('sign place group=g2 file=Xsign')
700  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
701	      \ "    line=10  id=5  group=g2  name=sign1  priority=10\n", a)
702
703  " :sign place group=* file={fname}
704  let a = execute('sign place group=* file=Xsign')
705  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
706	      \ "    line=10  id=5  group=g2  name=sign1  priority=10\n" .
707	      \ "    line=10  id=5  group=g1  name=sign1  priority=10\n" .
708	      \ "    line=10  id=5  name=sign1  priority=10\n", a)
709
710  " Error case: non-existing group
711  let a = execute('sign place group=xyz file=Xsign')
712  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a)
713
714  call sign_unplace('*')
715  let bnum = bufnr('Xsign')
716  exe 'sign place 5 line=10 name=sign1 buffer=' . bnum
717  exe 'sign place 5 group=g1 line=11 name=sign1 buffer=' . bnum
718  exe 'sign place 5 group=g2 line=12 name=sign1 buffer=' . bnum
719
720  " :sign place buffer={fname}
721  let a = execute('sign place buffer=' . bnum)
722  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
723	      \ "    line=10  id=5  name=sign1  priority=10\n", a)
724
725  " :sign place group={group} buffer={fname}
726  let a = execute('sign place group=g2 buffer=' . bnum)
727  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
728	      \ "    line=12  id=5  group=g2  name=sign1  priority=10\n", a)
729
730  " :sign place group=* buffer={fname}
731  let a = execute('sign place group=* buffer=' . bnum)
732  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
733	      \ "    line=10  id=5  name=sign1  priority=10\n" .
734	      \ "    line=11  id=5  group=g1  name=sign1  priority=10\n" .
735	      \ "    line=12  id=5  group=g2  name=sign1  priority=10\n", a)
736
737  " Error case: non-existing group
738  let a = execute('sign place group=xyz buffer=' . bnum)
739  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a)
740
741  " :sign place
742  let a = execute('sign place')
743  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
744	      \ "    line=10  id=5  name=sign1  priority=10\n", a)
745
746  " Place signs in more than one buffer and list the signs
747  split foo
748  set buftype=nofile
749  sign place 25 line=76 name=sign1 priority=99 file=foo
750  let a = execute('sign place')
751  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
752	      \ "    line=10  id=5  name=sign1  priority=10\n" .
753	      \ "Signs for foo:\n" .
754	      \ "    line=76  id=25  name=sign1  priority=99\n", a)
755  close
756  bwipe foo
757
758  " :sign place group={group}
759  let a = execute('sign place group=g1')
760  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
761	      \ "    line=11  id=5  group=g1  name=sign1  priority=10\n", a)
762
763  " :sign place group=*
764  let a = execute('sign place group=*')
765  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
766	      \ "    line=10  id=5  name=sign1  priority=10\n" .
767	      \ "    line=11  id=5  group=g1  name=sign1  priority=10\n" .
768	      \ "    line=12  id=5  group=g2  name=sign1  priority=10\n", a)
769
770  " Test for ':sign jump' command with groups
771  sign jump 5 group=g1 file=Xsign
772  call assert_equal(11, line('.'))
773  call assert_equal('Xsign', bufname(''))
774  sign jump 5 group=g2 file=Xsign
775  call assert_equal(12, line('.'))
776
777  " Test for :sign jump command without the filename or buffer
778  sign jump 5
779  call assert_equal(10, line('.'))
780  sign jump 5 group=g1
781  call assert_equal(11, line('.'))
782
783  " Error cases
784  call assert_fails("sign place 3 group= name=sign1 buffer=" . bnum, 'E474:')
785
786  call delete("Xsign")
787  call sign_unplace('*')
788  call sign_undefine()
789  enew | only
790endfunc
791
792" Place signs used for ":sign unplace" command test
793func Place_signs_for_test()
794  call sign_unplace('*')
795
796  sign place 3 line=10 name=sign1 file=Xsign1
797  sign place 3 group=g1 line=11 name=sign1 file=Xsign1
798  sign place 3 group=g2 line=12 name=sign1 file=Xsign1
799  sign place 4 line=15 name=sign1 file=Xsign1
800  sign place 4 group=g1 line=16 name=sign1 file=Xsign1
801  sign place 4 group=g2 line=17 name=sign1 file=Xsign1
802  sign place 5 line=20 name=sign1 file=Xsign2
803  sign place 5 group=g1 line=21 name=sign1 file=Xsign2
804  sign place 5 group=g2 line=22 name=sign1 file=Xsign2
805  sign place 6 line=25 name=sign1 file=Xsign2
806  sign place 6 group=g1 line=26 name=sign1 file=Xsign2
807  sign place 6 group=g2 line=27 name=sign1 file=Xsign2
808endfunc
809
810" Place multiple signs in a single line for test
811func Place_signs_at_line_for_test()
812  call sign_unplace('*')
813  sign place 3 line=13 name=sign1 file=Xsign1
814  sign place 3 group=g1 line=13 name=sign1 file=Xsign1
815  sign place 3 group=g2 line=13 name=sign1 file=Xsign1
816  sign place 4 line=13 name=sign1 file=Xsign1
817  sign place 4 group=g1 line=13 name=sign1 file=Xsign1
818  sign place 4 group=g2 line=13 name=sign1 file=Xsign1
819endfunc
820
821" Tests for the ':sign unplace' command
822func Test_sign_unplace()
823  enew | only
824  " Remove all the signs
825  call sign_unplace('*')
826  call sign_undefine()
827
828  " Create two files and define signs
829  call writefile(repeat(["Sun is shining"], 30), "Xsign1")
830  call writefile(repeat(["It is beautiful"], 30), "Xsign2")
831
832  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
833  call sign_define("sign1", attr)
834
835  edit Xsign1
836  let bnum1 = bufnr('%')
837  split Xsign2
838  let bnum2 = bufnr('%')
839
840  let signs1 = [{'id' : 3, 'name' : 'sign1', 'lnum' : 10, 'group' : '',
841	      \ 'priority' : 10},
842	      \ {'id' : 3, 'name' : 'sign1', 'lnum' : 11, 'group' : 'g1',
843	      \ 'priority' : 10},
844	      \ {'id' : 3, 'name' : 'sign1', 'lnum' : 12, 'group' : 'g2',
845	      \ 'priority' : 10},
846	      \ {'id' : 4, 'name' : 'sign1', 'lnum' : 15, 'group' : '',
847	      \ 'priority' : 10},
848	      \ {'id' : 4, 'name' : 'sign1', 'lnum' : 16, 'group' : 'g1',
849	      \ 'priority' : 10},
850	      \ {'id' : 4, 'name' : 'sign1', 'lnum' : 17, 'group' : 'g2',
851	      \ 'priority' : 10},]
852  let signs2 = [{'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : '',
853	      \ 'priority' : 10},
854	      \ {'id' : 5, 'name' : 'sign1', 'lnum' : 21, 'group' : 'g1',
855	      \ 'priority' : 10},
856	      \ {'id' : 5, 'name' : 'sign1', 'lnum' : 22, 'group' : 'g2',
857	      \ 'priority' : 10},
858	      \ {'id' : 6, 'name' : 'sign1', 'lnum' : 25, 'group' : '',
859	      \ 'priority' : 10},
860	      \ {'id' : 6, 'name' : 'sign1', 'lnum' : 26, 'group' : 'g1',
861	      \ 'priority' : 10},
862	      \ {'id' : 6, 'name' : 'sign1', 'lnum' : 27, 'group' : 'g2',
863	      \ 'priority' : 10},]
864
865  " Test for :sign unplace {id} file={fname}
866  call Place_signs_for_test()
867  sign unplace 3 file=Xsign1
868  sign unplace 6 file=Xsign2
869  call assert_equal(
870	      \ filter(copy(signs1),
871	      \     {idx, val -> val.id != 3 || val.group != ''}),
872	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
873  call assert_equal(
874	      \ filter(copy(signs2),
875	      \     {idx, val -> val.id != 6 || val.group != ''}),
876	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
877
878  " Test for :sign unplace {id} group={group} file={fname}
879  call Place_signs_for_test()
880  sign unplace 4 group=g1 file=Xsign1
881  sign unplace 5 group=g2 file=Xsign2
882  call assert_equal(
883	      \ filter(copy(signs1),
884	      \     {idx, val -> val.id != 4 || val.group != 'g1'}),
885	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
886  call assert_equal(
887	      \ filter(copy(signs2),
888	      \     {idx, val -> val.id != 5 || val.group != 'g2'}),
889	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
890
891  " Test for :sign unplace {id} group=* file={fname}
892  call Place_signs_for_test()
893  sign unplace 3 group=* file=Xsign1
894  sign unplace 6 group=* file=Xsign2
895  call assert_equal(
896	      \ filter(copy(signs1),
897	      \     {idx, val -> val.id != 3}),
898	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
899  call assert_equal(
900	      \ filter(copy(signs2),
901	      \     {idx, val -> val.id != 6}),
902	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
903
904  " Test for :sign unplace * file={fname}
905  call Place_signs_for_test()
906  sign unplace * file=Xsign1
907  call assert_equal(
908	      \ filter(copy(signs1),
909	      \     {idx, val -> val.group != ''}),
910	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
911  call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
912
913  " Test for :sign unplace * group={group} file={fname}
914  call Place_signs_for_test()
915  sign unplace * group=g1 file=Xsign1
916  sign unplace * group=g2 file=Xsign2
917  call assert_equal(
918	      \ filter(copy(signs1),
919	      \     {idx, val -> val.group != 'g1'}),
920	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
921  call assert_equal(
922	      \ filter(copy(signs2),
923	      \     {idx, val -> val.group != 'g2'}),
924	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
925
926  " Test for :sign unplace * group=* file={fname}
927  call Place_signs_for_test()
928  sign unplace * group=* file=Xsign2
929  call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
930  call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
931
932  " Test for :sign unplace {id} buffer={nr}
933  call Place_signs_for_test()
934  exe 'sign unplace 3 buffer=' . bnum1
935  exe 'sign unplace 6 buffer=' . bnum2
936  call assert_equal(
937	      \ filter(copy(signs1),
938	      \     {idx, val -> val.id != 3 || val.group != ''}),
939	      \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
940  call assert_equal(
941	      \ filter(copy(signs2),
942	      \     {idx, val -> val.id != 6 || val.group != ''}),
943	      \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
944
945  " Test for :sign unplace {id} group={group} buffer={nr}
946  call Place_signs_for_test()
947  exe 'sign unplace 4 group=g1 buffer=' . bnum1
948  exe 'sign unplace 5 group=g2 buffer=' . bnum2
949  call assert_equal(
950	      \ filter(copy(signs1),
951	      \     {idx, val -> val.id != 4 || val.group != 'g1'}),
952	      \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
953  call assert_equal(
954	      \ filter(copy(signs2),
955	      \     {idx, val -> val.id != 5 || val.group != 'g2'}),
956	      \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
957
958  " Test for :sign unplace {id} group=* buffer={nr}
959  call Place_signs_for_test()
960  exe 'sign unplace 3 group=* buffer=' . bnum1
961  exe 'sign unplace 6 group=* buffer=' . bnum2
962  call assert_equal(
963	      \ filter(copy(signs1),
964	      \     {idx, val -> val.id != 3}),
965	      \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
966  call assert_equal(
967	      \ filter(copy(signs2),
968	      \     {idx, val -> val.id != 6}),
969	      \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
970
971  " Test for :sign unplace * buffer={nr}
972  call Place_signs_for_test()
973  exe 'sign unplace * buffer=' . bnum1
974  call assert_equal(
975	      \ filter(copy(signs1),
976	      \     {idx, val -> val.group != ''}),
977	      \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
978  call assert_equal(signs2, sign_getplaced(bnum2, {'group' : '*'})[0].signs)
979
980  " Test for :sign unplace * group={group} buffer={nr}
981  call Place_signs_for_test()
982  exe 'sign unplace * group=g1 buffer=' . bnum1
983  exe 'sign unplace * group=g2 buffer=' . bnum2
984  call assert_equal(
985	      \ filter(copy(signs1),
986	      \     {idx, val -> val.group != 'g1'}),
987	      \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
988  call assert_equal(
989	      \ filter(copy(signs2),
990	      \     {idx, val -> val.group != 'g2'}),
991	      \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
992
993  " Test for :sign unplace * group=* buffer={nr}
994  call Place_signs_for_test()
995  exe 'sign unplace * group=* buffer=' . bnum2
996  call assert_equal(signs1, sign_getplaced(bnum1, {'group' : '*'})[0].signs)
997  call assert_equal([], sign_getplaced(bnum2, {'group' : '*'})[0].signs)
998
999  " Test for :sign unplace {id}
1000  call Place_signs_for_test()
1001  sign unplace 4
1002  sign unplace 6
1003  call assert_equal(
1004	      \ filter(copy(signs1),
1005	      \     {idx, val -> val.id != 4 || val.group != ''}),
1006	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1007  call assert_equal(
1008	      \ filter(copy(signs2),
1009	      \     {idx, val -> val.id != 6 || val.group != ''}),
1010	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1011
1012  " Test for :sign unplace {id} group={group}
1013  call Place_signs_for_test()
1014  sign unplace 4 group=g1
1015  sign unplace 6 group=g2
1016  call assert_equal(
1017	      \ filter(copy(signs1),
1018	      \     {idx, val -> val.id != 4 || val.group != 'g1'}),
1019	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1020  call assert_equal(
1021	      \ filter(copy(signs2),
1022	      \     {idx, val -> val.id != 6 || val.group != 'g2'}),
1023	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1024
1025  " Test for :sign unplace {id} group=*
1026  call Place_signs_for_test()
1027  sign unplace 3 group=*
1028  sign unplace 5 group=*
1029  call assert_equal(
1030	      \ filter(copy(signs1),
1031	      \     {idx, val -> val.id != 3}),
1032	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1033  call assert_equal(
1034	      \ filter(copy(signs2),
1035	      \     {idx, val -> val.id != 5}),
1036	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1037
1038  " Test for :sign unplace *
1039  call Place_signs_for_test()
1040  sign unplace *
1041  call assert_equal(
1042	      \ filter(copy(signs1),
1043	      \     {idx, val -> val.group != ''}),
1044	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1045  call assert_equal(
1046	      \ filter(copy(signs2),
1047	      \     {idx, val -> val.group != ''}),
1048	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1049
1050  " Test for :sign unplace * group={group}
1051  call Place_signs_for_test()
1052  sign unplace * group=g1
1053  call assert_equal(
1054	      \ filter(copy(signs1),
1055	      \     {idx, val -> val.group != 'g1'}),
1056	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1057  call assert_equal(
1058	      \ filter(copy(signs2),
1059	      \     {idx, val -> val.group != 'g1'}),
1060	      \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1061
1062  " Test for :sign unplace * group=*
1063  call Place_signs_for_test()
1064  sign unplace * group=*
1065  call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1066  call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1067
1068  " Negative test cases
1069  call Place_signs_for_test()
1070  sign unplace 3 group=xy file=Xsign1
1071  sign unplace * group=xy file=Xsign1
1072  silent! sign unplace * group=* file=FileNotPresent
1073  call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1074  call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
1075
1076  " Tests for removing sign at the current cursor position
1077
1078  " Test for ':sign unplace'
1079  let signs1 = [{'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
1080	      \ 'priority' : 10},
1081	      \ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
1082	      \ 'priority' : 10},
1083	      \ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
1084	      \ 'priority' : 10},
1085	      \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
1086	      \ 'priority' : 10},
1087	      \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
1088	      \ 'priority' : 10},
1089	      \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
1090	      \ 'priority' : 10},]
1091  exe bufwinnr('Xsign1') . 'wincmd w'
1092  call cursor(13, 1)
1093
1094  " Should remove only one sign in the global group
1095  call Place_signs_at_line_for_test()
1096  sign unplace
1097  call assert_equal(
1098	      \ filter(copy(signs1),
1099	      \     {idx, val -> val.id != 4 || val.group != ''}),
1100	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1101  " Should remove the second sign in the global group
1102  sign unplace
1103  call assert_equal(
1104	      \ filter(copy(signs1),
1105	      \     {idx, val -> val.group != ''}),
1106	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1107
1108  " Test for ':sign unplace group={group}'
1109  call Place_signs_at_line_for_test()
1110  " Should remove only one sign in group g1
1111  sign unplace group=g1
1112  call assert_equal(
1113	      \ filter(copy(signs1),
1114	      \     {idx, val -> val.id != 4 || val.group != 'g1'}),
1115	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1116  sign unplace group=g2
1117  call assert_equal(
1118	      \ filter(copy(signs1),
1119	      \     {idx, val -> val.id != 4 || val.group == ''}),
1120	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1121
1122  " Test for ':sign unplace group=*'
1123  call Place_signs_at_line_for_test()
1124  sign unplace group=*
1125  sign unplace group=*
1126  sign unplace group=*
1127  call assert_equal(
1128	      \ filter(copy(signs1),
1129	      \     {idx, val -> val.id != 4}),
1130	      \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1131  sign unplace group=*
1132  sign unplace group=*
1133  sign unplace group=*
1134  call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
1135
1136  call sign_unplace('*')
1137  call sign_undefine()
1138  enew | only
1139  call delete("Xsign1")
1140  call delete("Xsign2")
1141endfunc
1142
1143" Tests for auto-generating the sign identifier.
1144func Test_aaa_sign_id_autogen()
1145  enew | only
1146  call sign_unplace('*')
1147  call sign_undefine()
1148
1149  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
1150  call assert_equal(0, sign_define("sign1", attr))
1151
1152  call writefile(repeat(["Sun is shining"], 30), "Xsign")
1153  edit Xsign
1154
1155  call assert_equal(1, sign_place(0, '', 'sign1', 'Xsign',
1156	      \ {'lnum' : 10}))
1157  call assert_equal(2, sign_place(2, '', 'sign1', 'Xsign',
1158	      \ {'lnum' : 12}))
1159  call assert_equal(3, sign_place(0, '', 'sign1', 'Xsign',
1160	      \ {'lnum' : 14}))
1161  call sign_unplace('', {'buffer' : 'Xsign', 'id' : 2})
1162  call assert_equal(4, sign_place(0, '', 'sign1', 'Xsign',
1163	      \ {'lnum' : 12}))
1164
1165  call assert_equal(1, sign_place(0, 'g1', 'sign1', 'Xsign',
1166	      \ {'lnum' : 11}))
1167  " Check for the next generated sign id in this group
1168  call assert_equal(2, sign_place(0, 'g1', 'sign1', 'Xsign',
1169	      \ {'lnum' : 12}))
1170  call assert_equal(0, sign_unplace('g1', {'id' : 1}))
1171  call assert_equal(10,
1172	      \ sign_getplaced('Xsign', {'id' : 1})[0].signs[0].lnum)
1173
1174  call delete("Xsign")
1175  call sign_unplace('*')
1176  call sign_undefine()
1177  enew | only
1178endfunc
1179
1180" Test for sign priority
1181func Test_sign_priority()
1182  enew | only
1183  call sign_unplace('*')
1184  call sign_undefine()
1185
1186  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Search'}
1187  call sign_define("sign1", attr)
1188  call sign_define("sign2", attr)
1189  call sign_define("sign3", attr)
1190
1191  " Place three signs with different priority in the same line
1192  call writefile(repeat(["Sun is shining"], 30), "Xsign")
1193  edit Xsign
1194
1195  call sign_place(1, 'g1', 'sign1', 'Xsign',
1196	      \ {'lnum' : 11, 'priority' : 50})
1197  call sign_place(2, 'g2', 'sign2', 'Xsign',
1198	      \ {'lnum' : 11, 'priority' : 100})
1199  call sign_place(3, '', 'sign3', 'Xsign', {'lnum' : 11})
1200  let s = sign_getplaced('Xsign', {'group' : '*'})
1201  call assert_equal([
1202	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 11, 'group' : 'g2',
1203	      \ 'priority' : 100},
1204	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : 'g1',
1205	      \ 'priority' : 50},
1206	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 11, 'group' : '',
1207	      \ 'priority' : 10}],
1208	      \ s[0].signs)
1209
1210  call sign_unplace('*')
1211
1212  " Three signs on different lines with changing priorities
1213  call sign_place(1, '', 'sign1', 'Xsign',
1214	      \ {'lnum' : 11, 'priority' : 50})
1215  call sign_place(2, '', 'sign2', 'Xsign',
1216	      \ {'lnum' : 12, 'priority' : 60})
1217  call sign_place(3, '', 'sign3', 'Xsign',
1218	      \ {'lnum' : 13, 'priority' : 70})
1219  call sign_place(2, '', 'sign2', 'Xsign',
1220	      \ {'lnum' : 12, 'priority' : 40})
1221  call sign_place(3, '', 'sign3', 'Xsign',
1222	      \ {'lnum' : 13, 'priority' : 30})
1223  call sign_place(1, '', 'sign1', 'Xsign',
1224	      \ {'lnum' : 11, 'priority' : 50})
1225  let s = sign_getplaced('Xsign', {'group' : '*'})
1226  call assert_equal([
1227	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '',
1228	      \ 'priority' : 50},
1229	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '',
1230	      \ 'priority' : 40},
1231	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '',
1232	      \ 'priority' : 30}],
1233	      \ s[0].signs)
1234
1235  call sign_unplace('*')
1236
1237  " Two signs on the same line with changing priorities
1238  call sign_place(1, '', 'sign1', 'Xsign',
1239	      \ {'lnum' : 4, 'priority' : 20})
1240  call sign_place(2, '', 'sign2', 'Xsign',
1241	      \ {'lnum' : 4, 'priority' : 30})
1242  let s = sign_getplaced('Xsign', {'group' : '*'})
1243  call assert_equal([
1244	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1245	      \ 'priority' : 30},
1246	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1247	      \ 'priority' : 20}],
1248	      \ s[0].signs)
1249  " Change the priority of the last sign to highest
1250  call sign_place(1, '', 'sign1', 'Xsign',
1251	      \ {'lnum' : 4, 'priority' : 40})
1252  let s = sign_getplaced('Xsign', {'group' : '*'})
1253  call assert_equal([
1254	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1255	      \ 'priority' : 40},
1256	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1257	      \ 'priority' : 30}],
1258	      \ s[0].signs)
1259  " Change the priority of the first sign to lowest
1260  call sign_place(1, '', 'sign1', 'Xsign',
1261	      \ {'lnum' : 4, 'priority' : 25})
1262  let s = sign_getplaced('Xsign', {'group' : '*'})
1263  call assert_equal([
1264	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1265	      \ 'priority' : 30},
1266	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1267	      \ 'priority' : 25}],
1268	      \ s[0].signs)
1269  call sign_place(1, '', 'sign1', 'Xsign',
1270	      \ {'lnum' : 4, 'priority' : 45})
1271  call sign_place(2, '', 'sign2', 'Xsign',
1272	      \ {'lnum' : 4, 'priority' : 55})
1273  let s = sign_getplaced('Xsign', {'group' : '*'})
1274  call assert_equal([
1275	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1276	      \ 'priority' : 55},
1277	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1278	      \ 'priority' : 45}],
1279	      \ s[0].signs)
1280
1281  call sign_unplace('*')
1282
1283  " Three signs on the same line with changing priorities
1284  call sign_place(1, '', 'sign1', 'Xsign',
1285	      \ {'lnum' : 4, 'priority' : 40})
1286  call sign_place(2, '', 'sign2', 'Xsign',
1287	      \ {'lnum' : 4, 'priority' : 30})
1288  call sign_place(3, '', 'sign3', 'Xsign',
1289	      \ {'lnum' : 4, 'priority' : 20})
1290  let s = sign_getplaced('Xsign', {'group' : '*'})
1291  call assert_equal([
1292	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1293	      \ 'priority' : 40},
1294	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1295	      \ 'priority' : 30},
1296	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1297	      \ 'priority' : 20}],
1298	      \ s[0].signs)
1299
1300  " Change the priority of the middle sign to the highest
1301  call sign_place(2, '', 'sign2', 'Xsign',
1302	      \ {'lnum' : 4, 'priority' : 50})
1303  let s = sign_getplaced('Xsign', {'group' : '*'})
1304  call assert_equal([
1305	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1306	      \ 'priority' : 50},
1307	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1308	      \ 'priority' : 40},
1309	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1310	      \ 'priority' : 20}],
1311	      \ s[0].signs)
1312
1313  " Change the priority of the middle sign to the lowest
1314  call sign_place(1, '', 'sign1', 'Xsign',
1315	      \ {'lnum' : 4, 'priority' : 15})
1316  let s = sign_getplaced('Xsign', {'group' : '*'})
1317  call assert_equal([
1318	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1319	      \ 'priority' : 50},
1320	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1321	      \ 'priority' : 20},
1322	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1323	      \ 'priority' : 15}],
1324	      \ s[0].signs)
1325
1326  " Change the priority of the last sign to the highest
1327  call sign_place(1, '', 'sign1', 'Xsign',
1328	      \ {'lnum' : 4, 'priority' : 55})
1329  let s = sign_getplaced('Xsign', {'group' : '*'})
1330  call assert_equal([
1331	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1332	      \ 'priority' : 55},
1333	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1334	      \ 'priority' : 50},
1335	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1336	      \ 'priority' : 20}],
1337	      \ s[0].signs)
1338
1339  " Change the priority of the first sign to the lowest
1340  call sign_place(1, '', 'sign1', 'Xsign',
1341	      \ {'lnum' : 4, 'priority' : 15})
1342  let s = sign_getplaced('Xsign', {'group' : '*'})
1343  call assert_equal([
1344	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1345	      \ 'priority' : 50},
1346	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1347	      \ 'priority' : 20},
1348	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1349	      \ 'priority' : 15}],
1350	      \ s[0].signs)
1351
1352  call sign_unplace('*')
1353
1354  " Three signs on the same line with changing priorities along with other
1355  " signs
1356  call sign_place(1, '', 'sign1', 'Xsign',
1357	      \ {'lnum' : 2, 'priority' : 10})
1358  call sign_place(2, '', 'sign1', 'Xsign',
1359	      \ {'lnum' : 4, 'priority' : 30})
1360  call sign_place(3, '', 'sign2', 'Xsign',
1361	      \ {'lnum' : 4, 'priority' : 20})
1362  call sign_place(4, '', 'sign3', 'Xsign',
1363	      \ {'lnum' : 4, 'priority' : 25})
1364  call sign_place(5, '', 'sign2', 'Xsign',
1365	      \ {'lnum' : 6, 'priority' : 80})
1366  let s = sign_getplaced('Xsign', {'group' : '*'})
1367  call assert_equal([
1368	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
1369	      \ 'priority' : 10},
1370	      \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1371	      \ 'priority' : 30},
1372	      \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1373	      \ 'priority' : 25},
1374	      \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1375	      \ 'priority' : 20},
1376	      \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
1377	      \ 'priority' : 80}],
1378	      \ s[0].signs)
1379
1380  " Change the priority of the first sign to lowest
1381  call sign_place(2, '', 'sign1', 'Xsign',
1382	      \ {'lnum' : 4, 'priority' : 15})
1383  let s = sign_getplaced('Xsign', {'group' : '*'})
1384  call assert_equal([
1385	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
1386	      \ 'priority' : 10},
1387	      \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1388	      \ 'priority' : 25},
1389	      \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1390	      \ 'priority' : 20},
1391	      \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1392	      \ 'priority' : 15},
1393	      \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
1394	      \ 'priority' : 80}],
1395	      \ s[0].signs)
1396
1397  " Change the priority of the last sign to highest
1398  call sign_place(2, '', 'sign1', 'Xsign',
1399	      \ {'lnum' : 4, 'priority' : 30})
1400  let s = sign_getplaced('Xsign', {'group' : '*'})
1401  call assert_equal([
1402	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
1403	      \ 'priority' : 10},
1404	      \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1405	      \ 'priority' : 30},
1406	      \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1407	      \ 'priority' : 25},
1408	      \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1409	      \ 'priority' : 20},
1410	      \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
1411	      \ 'priority' : 80}],
1412	      \ s[0].signs)
1413
1414  " Change the priority of the middle sign to lowest
1415  call sign_place(4, '', 'sign3', 'Xsign',
1416	      \ {'lnum' : 4, 'priority' : 15})
1417  let s = sign_getplaced('Xsign', {'group' : '*'})
1418  call assert_equal([
1419	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
1420	      \ 'priority' : 10},
1421	      \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1422	      \ 'priority' : 30},
1423	      \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1424	      \ 'priority' : 20},
1425	      \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1426	      \ 'priority' : 15},
1427	      \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
1428	      \ 'priority' : 80}],
1429	      \ s[0].signs)
1430
1431  " Change the priority of the middle sign to highest
1432  call sign_place(3, '', 'sign2', 'Xsign',
1433	      \ {'lnum' : 4, 'priority' : 35})
1434  let s = sign_getplaced('Xsign', {'group' : '*'})
1435  call assert_equal([
1436	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
1437	      \ 'priority' : 10},
1438	      \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1439	      \ 'priority' : 35},
1440	      \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1441	      \ 'priority' : 30},
1442	      \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1443	      \ 'priority' : 15},
1444	      \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
1445	      \ 'priority' : 80}],
1446	      \ s[0].signs)
1447
1448  call sign_unplace('*')
1449
1450  " Multiple signs with the same priority on the same line
1451  call sign_place(1, '', 'sign1', 'Xsign',
1452              \ {'lnum' : 4, 'priority' : 20})
1453  call sign_place(2, '', 'sign2', 'Xsign',
1454              \ {'lnum' : 4, 'priority' : 20})
1455  call sign_place(3, '', 'sign3', 'Xsign',
1456              \ {'lnum' : 4, 'priority' : 20})
1457  let s = sign_getplaced('Xsign', {'group' : '*'})
1458  call assert_equal([
1459              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1460              \ 'priority' : 20},
1461              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1462              \ 'priority' : 20},
1463              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1464              \ 'priority' : 20}],
1465              \ s[0].signs)
1466  " Place the last sign again with the same priority
1467  call sign_place(1, '', 'sign1', 'Xsign',
1468              \ {'lnum' : 4, 'priority' : 20})
1469  let s = sign_getplaced('Xsign', {'group' : '*'})
1470  call assert_equal([
1471              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1472              \ 'priority' : 20},
1473              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1474              \ 'priority' : 20},
1475              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1476              \ 'priority' : 20}],
1477              \ s[0].signs)
1478  " Place the first sign again with the same priority
1479  call sign_place(1, '', 'sign1', 'Xsign',
1480              \ {'lnum' : 4, 'priority' : 20})
1481  let s = sign_getplaced('Xsign', {'group' : '*'})
1482  call assert_equal([
1483              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1484              \ 'priority' : 20},
1485              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1486              \ 'priority' : 20},
1487              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1488              \ 'priority' : 20}],
1489              \ s[0].signs)
1490  " Place the middle sign again with the same priority
1491  call sign_place(3, '', 'sign3', 'Xsign',
1492              \ {'lnum' : 4, 'priority' : 20})
1493  let s = sign_getplaced('Xsign', {'group' : '*'})
1494  call assert_equal([
1495              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
1496              \ 'priority' : 20},
1497              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
1498              \ 'priority' : 20},
1499              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
1500              \ 'priority' : 20}],
1501              \ s[0].signs)
1502
1503  call sign_unplace('*')
1504
1505  " Place multiple signs with same id on a line with different priority
1506  call sign_place(1, '', 'sign1', 'Xsign',
1507	      \ {'lnum' : 5, 'priority' : 20})
1508  call sign_place(1, '', 'sign2', 'Xsign',
1509	      \ {'lnum' : 5, 'priority' : 10})
1510  let s = sign_getplaced('Xsign', {'lnum' : 5})
1511  call assert_equal([
1512	      \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
1513	      \ 'priority' : 10}],
1514	      \ s[0].signs)
1515  call sign_place(1, '', 'sign2', 'Xsign',
1516	      \ {'lnum' : 5, 'priority' : 5})
1517  let s = sign_getplaced('Xsign', {'lnum' : 5})
1518  call assert_equal([
1519	      \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
1520	      \ 'priority' : 5}],
1521	      \ s[0].signs)
1522
1523  " Error case
1524  call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
1525	      \ [])", 'E715:')
1526  call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
1527	      \ {'priority' : []})", 'E745:')
1528  call sign_unplace('*')
1529
1530  " Tests for the :sign place command with priority
1531  sign place 5 line=10 name=sign1 priority=30 file=Xsign
1532  sign place 5 group=g1 line=10 name=sign1 priority=20 file=Xsign
1533  sign place 5 group=g2 line=10 name=sign1 priority=25 file=Xsign
1534  let a = execute('sign place group=*')
1535  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
1536	      \ "    line=10  id=5  name=sign1  priority=30\n" .
1537	      \ "    line=10  id=5  group=g2  name=sign1  priority=25\n" .
1538	      \ "    line=10  id=5  group=g1  name=sign1  priority=20\n", a)
1539
1540  " Test for :sign place group={group}
1541  let a = execute('sign place group=g1')
1542  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
1543	      \ "    line=10  id=5  group=g1  name=sign1  priority=20\n", a)
1544
1545  call sign_unplace('*')
1546  call sign_undefine()
1547  enew | only
1548  call delete("Xsign")
1549endfunc
1550
1551" Tests for memory allocation failures in sign functions
1552func Test_sign_memfailures()
1553  call writefile(repeat(["Sun is shining"], 30), "Xsign")
1554  edit Xsign
1555
1556  call test_alloc_fail(GetAllocId('sign_getdefined'), 0, 0)
1557  call assert_fails('call sign_getdefined("sign1")', 'E342:')
1558  call test_alloc_fail(GetAllocId('sign_getplaced'), 0, 0)
1559  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
1560  call test_alloc_fail(GetAllocId('sign_define_by_name'), 0, 0)
1561  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
1562  call assert_fails('call sign_define("sign1", attr)', 'E342:')
1563
1564  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
1565  call sign_define("sign1", attr)
1566  call test_alloc_fail(GetAllocId('sign_getlist'), 0, 0)
1567  call assert_fails('call sign_getdefined("sign1")', 'E342:')
1568
1569  call sign_place(3, 'g1', 'sign1', 'Xsign', {'lnum' : 10})
1570  call test_alloc_fail(GetAllocId('sign_getplaced_dict'), 0, 0)
1571  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
1572  call test_alloc_fail(GetAllocId('sign_getplaced_list'), 0, 0)
1573  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
1574
1575  call test_alloc_fail(GetAllocId('insert_sign'), 0, 0)
1576  call assert_fails('call sign_place(4, "g1", "sign1", "Xsign", {"lnum" : 11})',
1577								\ 'E342:')
1578
1579  call test_alloc_fail(GetAllocId('sign_getinfo'), 0, 0)
1580  call assert_fails('call getbufinfo()', 'E342:')
1581  call sign_place(4, 'g1', 'sign1', 'Xsign', {'lnum' : 11})
1582  call test_alloc_fail(GetAllocId('sign_getinfo'), 0, 0)
1583  call assert_fails('let binfo=getbufinfo("Xsign")', 'E342:')
1584  call assert_equal([{'lnum': 11, 'id': 4, 'name': 'sign1',
1585	      \ 'priority': 10, 'group': 'g1'}], binfo[0].signs)
1586
1587  call sign_unplace('*')
1588  call sign_undefine()
1589  enew | only
1590  call delete("Xsign")
1591endfunc
1592
1593" Test for auto-adjusting the line number of a placed sign.
1594func Test_sign_lnum_adjust()
1595  enew! | only!
1596
1597  sign define sign1 text=#> linehl=Comment
1598  call setline(1, ['A', 'B', 'C', 'D', 'E'])
1599  exe 'sign place 5 line=3 name=sign1 buffer=' . bufnr('')
1600  let l = sign_getplaced(bufnr(''))
1601  call assert_equal(3, l[0].signs[0].lnum)
1602
1603  " Add some lines before the sign and check the sign line number
1604  call append(2, ['BA', 'BB', 'BC'])
1605  let l = sign_getplaced(bufnr(''))
1606  call assert_equal(6, l[0].signs[0].lnum)
1607
1608  " Delete some lines before the sign and check the sign line number
1609  call deletebufline('%', 1, 2)
1610  let l = sign_getplaced(bufnr(''))
1611  call assert_equal(4, l[0].signs[0].lnum)
1612
1613  " Insert some lines after the sign and check the sign line number
1614  call append(5, ['DA', 'DB'])
1615  let l = sign_getplaced(bufnr(''))
1616  call assert_equal(4, l[0].signs[0].lnum)
1617
1618  " Delete some lines after the sign and check the sign line number
1619  call deletebufline('', 6, 7)
1620  let l = sign_getplaced(bufnr(''))
1621  call assert_equal(4, l[0].signs[0].lnum)
1622
1623  " Break the undo. Otherwise the undo operation below will undo all the
1624  " changes made by this function.
1625  let &undolevels=&undolevels
1626
1627  " Delete the line with the sign
1628  call deletebufline('', 4)
1629  let l = sign_getplaced(bufnr(''))
1630  call assert_equal(4, l[0].signs[0].lnum)
1631
1632  " Undo the delete operation
1633  undo
1634  let l = sign_getplaced(bufnr(''))
1635  call assert_equal(5, l[0].signs[0].lnum)
1636
1637  " Break the undo
1638  let &undolevels=&undolevels
1639
1640  " Delete few lines at the end of the buffer including the line with the sign
1641  " Sign line number should not change (as it is placed outside of the buffer)
1642  call deletebufline('', 3, 6)
1643  let l = sign_getplaced(bufnr(''))
1644  call assert_equal(5, l[0].signs[0].lnum)
1645
1646  " Undo the delete operation. Sign should be restored to the previous line
1647  undo
1648  let l = sign_getplaced(bufnr(''))
1649  call assert_equal(5, l[0].signs[0].lnum)
1650
1651  sign unplace * group=*
1652  sign undefine sign1
1653  enew!
1654endfunc
1655
1656" Test for changing the type of a placed sign
1657func Test_sign_change_type()
1658  enew! | only!
1659
1660  sign define sign1 text=#> linehl=Comment
1661  sign define sign2 text=@@ linehl=Comment
1662
1663  call setline(1, ['A', 'B', 'C', 'D'])
1664  exe 'sign place 4 line=3 name=sign1 buffer=' . bufnr('')
1665  let l = sign_getplaced(bufnr(''))
1666  call assert_equal('sign1', l[0].signs[0].name)
1667  exe 'sign place 4 name=sign2 buffer=' . bufnr('')
1668  let l = sign_getplaced(bufnr(''))
1669  call assert_equal('sign2', l[0].signs[0].name)
1670  call sign_place(4, '', 'sign1', '')
1671  let l = sign_getplaced(bufnr(''))
1672  call assert_equal('sign1', l[0].signs[0].name)
1673
1674  exe 'sign place 4 group=g1 line=4 name=sign1 buffer=' . bufnr('')
1675  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
1676  call assert_equal('sign1', l[0].signs[0].name)
1677  exe 'sign place 4 group=g1 name=sign2 buffer=' . bufnr('')
1678  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
1679  call assert_equal('sign2', l[0].signs[0].name)
1680  call sign_place(4, 'g1', 'sign1', '')
1681  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
1682  call assert_equal('sign1', l[0].signs[0].name)
1683
1684  sign unplace * group=*
1685  sign undefine sign1
1686  sign undefine sign2
1687  enew!
1688endfunc
1689
1690" Test for the sign_jump() function
1691func Test_sign_jump_func()
1692  enew! | only!
1693
1694  sign define sign1 text=#> linehl=Comment
1695
1696  edit foo
1697  set buftype=nofile
1698  call setline(1, ['A', 'B', 'C', 'D', 'E'])
1699  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
1700  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
1701  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
1702  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
1703  split bar
1704  set buftype=nofile
1705  call setline(1, ['P', 'Q', 'R', 'S', 'T'])
1706  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
1707  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
1708  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
1709  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
1710
1711  let r = sign_jump(5, '', 'foo')
1712  call assert_equal(2, r)
1713  call assert_equal(2, line('.'))
1714  let r = 6->sign_jump('g1', 'foo')
1715  call assert_equal(5, r)
1716  call assert_equal(5, line('.'))
1717  let r = sign_jump(5, '', 'bar')
1718  call assert_equal(2, r)
1719  call assert_equal(2, line('.'))
1720
1721  " Error cases
1722  call assert_fails("call sign_jump(99, '', 'bar')", 'E157:')
1723  call assert_fails("call sign_jump(0, '', 'foo')", 'E474:')
1724  call assert_fails("call sign_jump(5, 'g5', 'foo')", 'E157:')
1725  call assert_fails('call sign_jump([], "", "foo")', 'E745:')
1726  call assert_fails('call sign_jump(2, [], "foo")', 'E730:')
1727  call assert_fails('call sign_jump(2, "", {})', 'E731:')
1728  call assert_fails('call sign_jump(2, "", "baz")', 'E158:')
1729
1730  sign unplace * group=*
1731  sign undefine sign1
1732  enew! | only!
1733endfunc
1734
1735" Test for correct cursor position after the sign column appears or disappears.
1736func Test_sign_cursor_position()
1737  CheckRunVimInTerminal
1738
1739  let lines =<< trim END
1740	call setline(1, [repeat('x', 75), 'mmmm', 'yyyy'])
1741	call cursor(2,1)
1742   	sign define s1 texthl=Search text==>
1743   	sign define s2 linehl=Pmenu
1744	redraw
1745   	sign place 10 line=2 name=s1
1746  END
1747  call writefile(lines, 'XtestSigncolumn')
1748  let buf = RunVimInTerminal('-S XtestSigncolumn', {'rows': 6})
1749  call VerifyScreenDump(buf, 'Test_sign_cursor_1', {})
1750
1751  " Change the sign text
1752  call term_sendkeys(buf, ":sign define s1 text=-)\<CR>")
1753  call VerifyScreenDump(buf, 'Test_sign_cursor_2', {})
1754
1755  " Also place a line HL sign
1756  call term_sendkeys(buf, ":sign place 11 line=2 name=s2\<CR>")
1757  call VerifyScreenDump(buf, 'Test_sign_cursor_3', {})
1758
1759  " update cursor position calculation
1760  call term_sendkeys(buf, "lh")
1761  call term_sendkeys(buf, ":sign unplace 11\<CR>")
1762  call term_sendkeys(buf, ":sign unplace 10\<CR>")
1763  call VerifyScreenDump(buf, 'Test_sign_cursor_4', {})
1764
1765  " 'cursorline' highlighting overrules sign
1766  call term_sendkeys(buf, ":sign place 12 line=2 name=s2\<CR>")
1767  call term_sendkeys(buf, ":set cursorline\<CR>")
1768  call term_sendkeys(buf, ":hi CursorLine ctermbg=Green\<CR>")
1769  call term_sendkeys(buf, "2G")
1770  call term_sendkeys(buf, ":\<CR>")
1771  call VerifyScreenDump(buf, 'Test_sign_cursor_5', {})
1772
1773  " sign highlighting overrules 'cursorline'
1774  call term_sendkeys(buf, ":sign unplace 12\<CR>")
1775  call term_sendkeys(buf, ":sign place 13 line=2 priority=100 name=s2\<CR>")
1776  call term_sendkeys(buf, ":\<CR>")
1777  call VerifyScreenDump(buf, 'Test_sign_cursor_6', {})
1778
1779  " clean up
1780  call StopVimInTerminal(buf)
1781  call delete('XtestSigncolumn')
1782endfunc
1783
1784" Return the 'len' characters in screen starting from (row,col)
1785func s:ScreenLine(row, col, len)
1786  let s = ''
1787  for i in range(a:len)
1788    let s .= nr2char(screenchar(a:row, a:col + i))
1789  endfor
1790  return s
1791endfunc
1792
1793" Test for 'signcolumn' set to 'number'.
1794func Test_sign_numcol()
1795  new
1796  call append(0, "01234")
1797  " With 'signcolumn' set to 'number', make sure sign is displayed in the
1798  " number column and line number is not displayed.
1799  set numberwidth=2
1800  set number
1801  set signcolumn=number
1802  sign define sign1 text==>
1803  sign define sign2 text=V
1804  sign place 10 line=1 name=sign1
1805  redraw!
1806  call assert_equal("=> 01234", s:ScreenLine(1, 1, 8))
1807
1808  " With 'signcolumn' set to 'number', when there is no sign, make sure line
1809  " number is displayed in the number column
1810  sign unplace 10
1811  redraw!
1812  call assert_equal("1 01234", s:ScreenLine(1, 1, 7))
1813
1814  " Disable number column. Check whether sign is displayed in the sign column
1815  set numberwidth=4
1816  set nonumber
1817  sign place 10 line=1 name=sign1
1818  redraw!
1819  call assert_equal("=>01234", s:ScreenLine(1, 1, 7))
1820
1821  " Enable number column. Check whether sign is displayed in the number column
1822  set number
1823  redraw!
1824  call assert_equal(" => 01234", s:ScreenLine(1, 1, 9))
1825
1826  " Disable sign column. Make sure line number is displayed
1827  set signcolumn=no
1828  redraw!
1829  call assert_equal("  1 01234", s:ScreenLine(1, 1, 9))
1830
1831  " Enable auto sign column. Make sure both sign and line number are displayed
1832  set signcolumn=auto
1833  redraw!
1834  call assert_equal("=>  1 01234", s:ScreenLine(1, 1, 11))
1835
1836  " Test displaying signs in the number column with width 1
1837  call sign_unplace('*')
1838  call append(1, "abcde")
1839  call append(2, "01234")
1840  " Enable number column with width 1
1841  set number numberwidth=1 signcolumn=auto
1842  redraw!
1843  call assert_equal("3 01234", s:ScreenLine(3, 1, 7))
1844  " Place a sign and make sure number column width remains the same
1845  sign place 20 line=2 name=sign1
1846  redraw!
1847  call assert_equal("=>2 abcde", s:ScreenLine(2, 1, 9))
1848  call assert_equal("  3 01234", s:ScreenLine(3, 1, 9))
1849  " Set 'signcolumn' to 'number', make sure the number column width increases
1850  set signcolumn=number
1851  redraw!
1852  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
1853  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
1854  " Set 'signcolumn' to 'auto', make sure the number column width is 1.
1855  set signcolumn=auto
1856  redraw!
1857  call assert_equal("=>2 abcde", s:ScreenLine(2, 1, 9))
1858  call assert_equal("  3 01234", s:ScreenLine(3, 1, 9))
1859  " Set 'signcolumn' to 'number', make sure the number column width is 2.
1860  set signcolumn=number
1861  redraw!
1862  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
1863  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
1864  " Disable 'number' column
1865  set nonumber
1866  redraw!
1867  call assert_equal("=>abcde", s:ScreenLine(2, 1, 7))
1868  call assert_equal("  01234", s:ScreenLine(3, 1, 7))
1869  " Enable 'number' column
1870  set number
1871  redraw!
1872  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
1873  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
1874  " Remove the sign and make sure the width of the number column is 1.
1875  call sign_unplace('', {'id' : 20})
1876  redraw!
1877  call assert_equal("3 01234", s:ScreenLine(3, 1, 7))
1878  " When the first sign is placed with 'signcolumn' set to number, verify that
1879  " the number column width increases
1880  sign place 30 line=1 name=sign1
1881  redraw!
1882  call assert_equal("=> 01234", s:ScreenLine(1, 1, 8))
1883  call assert_equal(" 2 abcde", s:ScreenLine(2, 1, 8))
1884  " Add sign with multi-byte text
1885  set numberwidth=4
1886  sign place 40 line=2 name=sign2
1887  redraw!
1888  call assert_equal(" => 01234", s:ScreenLine(1, 1, 9))
1889  call assert_equal(" V abcde", s:ScreenLine(2, 1, 9))
1890
1891  sign unplace * group=*
1892  sign undefine sign1
1893  set signcolumn&
1894  set number&
1895  enew!  | close
1896endfunc
1897
1898" Test for managing multiple signs using the sign functions
1899func Test_sign_funcs_multi()
1900  call writefile(repeat(["Sun is shining"], 30), "Xsign")
1901  edit Xsign
1902  let bnum = bufnr('')
1903
1904  " Define multiple signs at once
1905  call assert_equal([0, 0, 0, 0], sign_define([
1906	      \ {'name' : 'sign1', 'text' : '=>', 'linehl' : 'Search',
1907	      \ 'texthl' : 'Search'},
1908	      \ {'name' : 'sign2', 'text' : '=>', 'linehl' : 'Search',
1909	      \ 'texthl' : 'Search'},
1910	      \ {'name' : 'sign3', 'text' : '=>', 'linehl' : 'Search',
1911	      \ 'texthl' : 'Search'},
1912	      \ {'name' : 'sign4', 'text' : '=>', 'linehl' : 'Search',
1913	      \ 'texthl' : 'Search'}]))
1914
1915  " Negative cases for sign_define()
1916  call assert_equal([], sign_define([]))
1917  call assert_equal([-1], sign_define([{}]))
1918  call assert_fails('call sign_define([6])', 'E715:')
1919  call assert_fails('call sign_define(["abc"])', 'E715:')
1920  call assert_fails('call sign_define([[]])', 'E715:')
1921
1922  " Place multiple signs at once with specific sign identifier
1923  let l = sign_placelist([{'id' : 1, 'group' : 'g1', 'name' : 'sign1',
1924	      \ 'buffer' : 'Xsign', 'lnum' : 11, 'priority' : 50},
1925	      \ {'id' : 2, 'group' : 'g2', 'name' : 'sign2',
1926	      \ 'buffer' : 'Xsign', 'lnum' : 11, 'priority' : 100},
1927	      \ {'id' : 3, 'group' : '', 'name' : 'sign3',
1928	      \ 'buffer' : 'Xsign', 'lnum' : 11}])
1929  call assert_equal([1, 2, 3], l)
1930  let s = sign_getplaced('Xsign', {'group' : '*'})
1931  call assert_equal([
1932	      \ {'id' : 2, 'name' : 'sign2', 'lnum' : 11,
1933	      \ 'group' : 'g2', 'priority' : 100},
1934	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11,
1935	      \ 'group' : 'g1', 'priority' : 50},
1936	      \ {'id' : 3, 'name' : 'sign3', 'lnum' : 11,
1937	      \ 'group' : '', 'priority' : 10}], s[0].signs)
1938
1939  call sign_unplace('*')
1940
1941  " Place multiple signs at once with auto-generated sign identifier
1942  call assert_equal([1, 1, 5], sign_placelist([
1943	      \ {'group' : 'g1', 'name' : 'sign1',
1944	      \ 'buffer' : 'Xsign', 'lnum' : 11},
1945	      \ {'group' : 'g2', 'name' : 'sign2',
1946	      \ 'buffer' : 'Xsign', 'lnum' : 11},
1947	      \ {'group' : '', 'name' : 'sign3',
1948	      \ 'buffer' : 'Xsign', 'lnum' : 11}]))
1949  let s = sign_getplaced('Xsign', {'group' : '*'})
1950  call assert_equal([
1951	      \ {'id' : 5, 'name' : 'sign3', 'lnum' : 11,
1952	      \ 'group' : '', 'priority' : 10},
1953	      \ {'id' : 1, 'name' : 'sign2', 'lnum' : 11,
1954	      \ 'group' : 'g2', 'priority' : 10},
1955	      \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11,
1956	      \ 'group' : 'g1', 'priority' : 10}], s[0].signs)
1957
1958  " Change an existing sign without specifying the group
1959  call assert_equal([5], [{'id' : 5, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
1960  let s = sign_getplaced('Xsign', {'id' : 5, 'group' : ''})
1961  call assert_equal([{'id' : 5, 'name' : 'sign1', 'lnum' : 11,
1962	      \ 'group' : '', 'priority' : 10}], s[0].signs)
1963
1964  " Place a sign using '.' as the line number
1965  call cursor(23, 1)
1966  call assert_equal([7], sign_placelist([
1967	      \ {'id' : 7, 'name' : 'sign1', 'buffer' : '%', 'lnum' : '.'}]))
1968  let s = sign_getplaced('%', {'lnum' : '.'})
1969  call assert_equal([{'id' : 7, 'name' : 'sign1', 'lnum' : 23,
1970	      \ 'group' : '', 'priority' : 10}], s[0].signs)
1971
1972  " Place sign without a sign name
1973  call assert_equal([-1], sign_placelist([{'id' : 10, 'buffer' : 'Xsign',
1974	      \ 'lnum' : 12, 'group' : ''}]))
1975
1976  " Place sign without a buffer
1977  call assert_equal([-1], sign_placelist([{'id' : 10, 'name' : 'sign1',
1978	      \ 'lnum' : 12, 'group' : ''}]))
1979
1980  " Invalid arguments
1981  call assert_equal([], sign_placelist([]))
1982  call assert_fails('call sign_placelist({})', "E714:")
1983  call assert_fails('call sign_placelist([[]])', "E715:")
1984  call assert_fails('call sign_placelist(["abc"])', "E715:")
1985  call assert_fails('call sign_placelist([100])', "E715:")
1986
1987  " Unplace multiple signs
1988  call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 5},
1989	      \ {'id' : 1, 'group' : 'g1'}, {'id' : 1, 'group' : 'g2'}]))
1990
1991  " Invalid arguments
1992  call assert_equal([], []->sign_unplacelist())
1993  call assert_fails('call sign_unplacelist({})', "E714:")
1994  call assert_fails('call sign_unplacelist([[]])', "E715:")
1995  call assert_fails('call sign_unplacelist(["abc"])', "E715:")
1996  call assert_fails('call sign_unplacelist([100])', "E715:")
1997  call assert_fails("call sign_unplacelist([{'id' : -1}])", 'E474:')
1998
1999  call assert_equal([0, 0, 0, 0],
2000	      \ sign_undefine(['sign1', 'sign2', 'sign3', 'sign4']))
2001  call assert_equal([], sign_getdefined())
2002
2003  " Invalid arguments
2004  call assert_equal([], sign_undefine([]))
2005  call assert_fails('call sign_undefine([[]])', 'E730:')
2006  call assert_fails('call sign_undefine([{}])', 'E731:')
2007  call assert_fails('call sign_undefine(["1abc2"])', 'E155:')
2008
2009  call sign_unplace('*')
2010  call sign_undefine()
2011  enew!
2012  call delete("Xsign")
2013endfunc
2014
2015func Test_sign_null_list()
2016  eval test_null_list()->sign_define()
2017  eval test_null_list()->sign_placelist()
2018  eval test_null_list()->sign_undefine()
2019  eval test_null_list()->sign_unplacelist()
2020endfunc
2021
2022" vim: shiftwidth=2 sts=2 expandtab
2023