blob: 1da1c1cab457f4840d85ec546a9cddc3ce6fad28 [file] [log] [blame]
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * testing.c: Support for tests.
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_EVAL) || defined(PROTO)
17
18/*
19 * Prepare "gap" for an assert error and add the sourcing position.
20 */
21 static void
22prepare_assert_error(garray_T *gap)
23{
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010024 char buf[NUMBUFLEN];
Bram Moolenaar4f25b1a2020-09-10 19:25:05 +020025 char_u *sname = estack_sfile(ESTACK_NONE);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020026
27 ga_init2(gap, 1, 100);
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010028 if (sname != NULL)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020029 {
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010030 ga_concat(gap, sname);
31 if (SOURCING_LNUM > 0)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020032 ga_concat(gap, (char_u *)" ");
33 }
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010034 if (SOURCING_LNUM > 0)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020035 {
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010036 sprintf(buf, "line %ld", (long)SOURCING_LNUM);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020037 ga_concat(gap, (char_u *)buf);
38 }
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010039 if (sname != NULL || SOURCING_LNUM > 0)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020040 ga_concat(gap, (char_u *)": ");
Bram Moolenaar1a47ae32019-12-29 23:04:25 +010041 vim_free(sname);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020042}
43
44/*
45 * Append "p[clen]" to "gap", escaping unprintable characters.
46 * Changes NL to \n, CR to \r, etc.
47 */
48 static void
49ga_concat_esc(garray_T *gap, char_u *p, int clen)
50{
51 char_u buf[NUMBUFLEN];
52
53 if (clen > 1)
54 {
55 mch_memmove(buf, p, clen);
56 buf[clen] = NUL;
57 ga_concat(gap, buf);
58 }
59 else switch (*p)
60 {
61 case BS: ga_concat(gap, (char_u *)"\\b"); break;
62 case ESC: ga_concat(gap, (char_u *)"\\e"); break;
63 case FF: ga_concat(gap, (char_u *)"\\f"); break;
64 case NL: ga_concat(gap, (char_u *)"\\n"); break;
65 case TAB: ga_concat(gap, (char_u *)"\\t"); break;
66 case CAR: ga_concat(gap, (char_u *)"\\r"); break;
67 case '\\': ga_concat(gap, (char_u *)"\\\\"); break;
68 default:
Bram Moolenaar7177da92020-07-12 23:09:20 +020069 if (*p < ' ' || *p == 0x7f)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +020070 {
71 vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
72 ga_concat(gap, buf);
73 }
74 else
75 ga_append(gap, *p);
76 break;
77 }
78}
79
80/*
81 * Append "str" to "gap", escaping unprintable characters.
82 * Changes NL to \n, CR to \r, etc.
83 */
84 static void
85ga_concat_shorten_esc(garray_T *gap, char_u *str)
86{
87 char_u *p;
88 char_u *s;
89 int c;
90 int clen;
91 char_u buf[NUMBUFLEN];
92 int same_len;
93
94 if (str == NULL)
95 {
96 ga_concat(gap, (char_u *)"NULL");
97 return;
98 }
99
100 for (p = str; *p != NUL; ++p)
101 {
102 same_len = 1;
103 s = p;
104 c = mb_ptr2char_adv(&s);
105 clen = s - p;
106 while (*s != NUL && c == mb_ptr2char(s))
107 {
108 ++same_len;
109 s += clen;
110 }
111 if (same_len > 20)
112 {
113 ga_concat(gap, (char_u *)"\\[");
114 ga_concat_esc(gap, p, clen);
115 ga_concat(gap, (char_u *)" occurs ");
116 vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len);
117 ga_concat(gap, buf);
118 ga_concat(gap, (char_u *)" times]");
119 p = s - 1;
120 }
121 else
122 ga_concat_esc(gap, p, clen);
123 }
124}
125
126/*
127 * Fill "gap" with information about an assert error.
128 */
129 static void
130fill_assert_error(
131 garray_T *gap,
132 typval_T *opt_msg_tv,
133 char_u *exp_str,
Bram Moolenaar4a021df2020-06-13 15:13:38 +0200134 typval_T *exp_tv_arg,
135 typval_T *got_tv_arg,
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200136 assert_type_T atype)
137{
138 char_u numbuf[NUMBUFLEN];
139 char_u *tofree;
Bram Moolenaar4a021df2020-06-13 15:13:38 +0200140 typval_T *exp_tv = exp_tv_arg;
141 typval_T *got_tv = got_tv_arg;
142 int did_copy = FALSE;
143 int omitted = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200144
Bram Moolenaar1d634542020-08-18 13:41:50 +0200145 if (opt_msg_tv->v_type != VAR_UNKNOWN
146 && !(opt_msg_tv->v_type == VAR_STRING
147 && (opt_msg_tv->vval.v_string == NULL
148 || *opt_msg_tv->vval.v_string == NUL)))
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200149 {
150 ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0));
151 vim_free(tofree);
152 ga_concat(gap, (char_u *)": ");
153 }
154
155 if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH)
156 ga_concat(gap, (char_u *)"Pattern ");
157 else if (atype == ASSERT_NOTEQUAL)
158 ga_concat(gap, (char_u *)"Expected not equal to ");
159 else
160 ga_concat(gap, (char_u *)"Expected ");
161 if (exp_str == NULL)
162 {
Bram Moolenaar4a021df2020-06-13 15:13:38 +0200163 // When comparing dictionaries, drop the items that are equal, so that
164 // it's a lot easier to see what differs.
165 if (atype != ASSERT_NOTEQUAL
166 && exp_tv->v_type == VAR_DICT && got_tv->v_type == VAR_DICT
167 && exp_tv->vval.v_dict != NULL && got_tv->vval.v_dict != NULL)
168 {
169 dict_T *exp_d = exp_tv->vval.v_dict;
170 dict_T *got_d = got_tv->vval.v_dict;
171 hashitem_T *hi;
172 dictitem_T *item2;
173 int todo;
174
175 did_copy = TRUE;
176 exp_tv->vval.v_dict = dict_alloc();
177 got_tv->vval.v_dict = dict_alloc();
178 if (exp_tv->vval.v_dict == NULL || got_tv->vval.v_dict == NULL)
179 return;
180
181 todo = (int)exp_d->dv_hashtab.ht_used;
182 for (hi = exp_d->dv_hashtab.ht_array; todo > 0; ++hi)
183 {
184 if (!HASHITEM_EMPTY(hi))
185 {
186 item2 = dict_find(got_d, hi->hi_key, -1);
187 if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv,
188 &item2->di_tv, FALSE, FALSE))
189 {
190 // item of exp_d not present in got_d or values differ.
191 dict_add_tv(exp_tv->vval.v_dict,
192 (char *)hi->hi_key, &HI2DI(hi)->di_tv);
193 if (item2 != NULL)
194 dict_add_tv(got_tv->vval.v_dict,
195 (char *)hi->hi_key, &item2->di_tv);
196 }
197 else
198 ++omitted;
199 --todo;
200 }
201 }
202
203 // Add items only present in got_d.
204 todo = (int)got_d->dv_hashtab.ht_used;
205 for (hi = got_d->dv_hashtab.ht_array; todo > 0; ++hi)
206 {
207 if (!HASHITEM_EMPTY(hi))
208 {
209 item2 = dict_find(exp_d, hi->hi_key, -1);
210 if (item2 == NULL)
211 // item of got_d not present in exp_d
212 dict_add_tv(got_tv->vval.v_dict,
213 (char *)hi->hi_key, &HI2DI(hi)->di_tv);
214 --todo;
215 }
216 }
217 }
218
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200219 ga_concat_shorten_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0));
220 vim_free(tofree);
221 }
222 else
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100223 {
224 ga_concat(gap, (char_u *)"'");
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200225 ga_concat_shorten_esc(gap, exp_str);
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100226 ga_concat(gap, (char_u *)"'");
227 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200228 if (atype != ASSERT_NOTEQUAL)
229 {
230 if (atype == ASSERT_MATCH)
231 ga_concat(gap, (char_u *)" does not match ");
232 else if (atype == ASSERT_NOTMATCH)
233 ga_concat(gap, (char_u *)" does match ");
234 else
235 ga_concat(gap, (char_u *)" but got ");
236 ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
237 vim_free(tofree);
Bram Moolenaar4a021df2020-06-13 15:13:38 +0200238
239 if (omitted != 0)
240 {
241 char buf[100];
242
243 vim_snprintf(buf, 100, " - %d equal item%s omitted",
244 omitted, omitted == 1 ? "" : "s");
245 ga_concat(gap, (char_u *)buf);
246 }
247 }
248
249 if (did_copy)
250 {
251 clear_tv(exp_tv);
252 clear_tv(got_tv);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200253 }
254}
255
256 static int
257assert_equal_common(typval_T *argvars, assert_type_T atype)
258{
259 garray_T ga;
260
261 if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)
262 != (atype == ASSERT_EQUAL))
263 {
264 prepare_assert_error(&ga);
265 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
266 atype);
267 assert_error(&ga);
268 ga_clear(&ga);
269 return 1;
270 }
271 return 0;
272}
273
274 static int
275assert_match_common(typval_T *argvars, assert_type_T atype)
276{
277 garray_T ga;
278 char_u buf1[NUMBUFLEN];
279 char_u buf2[NUMBUFLEN];
Bram Moolenaar7177da92020-07-12 23:09:20 +0200280 int called_emsg_before = called_emsg;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200281 char_u *pat = tv_get_string_buf_chk(&argvars[0], buf1);
282 char_u *text = tv_get_string_buf_chk(&argvars[1], buf2);
283
Bram Moolenaar7177da92020-07-12 23:09:20 +0200284 if (called_emsg == called_emsg_before
285 && pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH))
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200286 {
287 prepare_assert_error(&ga);
288 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
289 atype);
290 assert_error(&ga);
291 ga_clear(&ga);
292 return 1;
293 }
294 return 0;
295}
296
297/*
298 * Common for assert_true() and assert_false().
299 * Return non-zero for failure.
300 */
301 static int
302assert_bool(typval_T *argvars, int isTrue)
303{
304 int error = FALSE;
305 garray_T ga;
306
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100307 if (argvars[0].v_type == VAR_BOOL
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200308 && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE))
309 return 0;
310 if (argvars[0].v_type != VAR_NUMBER
311 || (tv_get_number_chk(&argvars[0], &error) == 0) == isTrue
312 || error)
313 {
314 prepare_assert_error(&ga);
315 fill_assert_error(&ga, &argvars[1],
316 (char_u *)(isTrue ? "True" : "False"),
317 NULL, &argvars[0], ASSERT_OTHER);
318 assert_error(&ga);
319 ga_clear(&ga);
320 return 1;
321 }
322 return 0;
323}
324
325 static void
326assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, char_u *cmd)
327{
328 char_u *tofree;
329 char_u numbuf[NUMBUFLEN];
330
331 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
332 {
333 ga_concat(gap, echo_string(&argvars[2], &tofree, numbuf, 0));
334 vim_free(tofree);
335 }
336 else
337 ga_concat(gap, cmd);
338}
339
340 static int
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +0200341assert_beeps(typval_T *argvars, int no_beep)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200342{
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200343 char_u *cmd;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200344 garray_T ga;
345 int ret = 0;
346
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200347 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
348 return 0;
349
350 cmd = tv_get_string_chk(&argvars[0]);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200351 called_vim_beep = FALSE;
352 suppress_errthrow = TRUE;
353 emsg_silent = FALSE;
354 do_cmdline_cmd(cmd);
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +0200355 if (no_beep ? called_vim_beep : !called_vim_beep)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200356 {
357 prepare_assert_error(&ga);
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +0200358 if (no_beep)
359 ga_concat(&ga, (char_u *)"command did beep: ");
360 else
361 ga_concat(&ga, (char_u *)"command did not beep: ");
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200362 ga_concat(&ga, cmd);
363 assert_error(&ga);
364 ga_clear(&ga);
365 ret = 1;
366 }
367
368 suppress_errthrow = FALSE;
369 emsg_on_display = FALSE;
370 return ret;
371}
372
373/*
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200374 * "assert_beeps(cmd)" function
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200375 */
376 void
377f_assert_beeps(typval_T *argvars, typval_T *rettv)
378{
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +0200379 rettv->vval.v_number = assert_beeps(argvars, FALSE);
380}
381
382/*
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200383 * "assert_nobeep(cmd)" function
Bram Moolenaar5b8cabf2021-04-02 18:55:57 +0200384 */
385 void
386f_assert_nobeep(typval_T *argvars, typval_T *rettv)
387{
388 rettv->vval.v_number = assert_beeps(argvars, TRUE);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200389}
390
391/*
392 * "assert_equal(expected, actual[, msg])" function
393 */
394 void
395f_assert_equal(typval_T *argvars, typval_T *rettv)
396{
397 rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
398}
399
400 static int
401assert_equalfile(typval_T *argvars)
402{
403 char_u buf1[NUMBUFLEN];
404 char_u buf2[NUMBUFLEN];
Bram Moolenaar7177da92020-07-12 23:09:20 +0200405 int called_emsg_before = called_emsg;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200406 char_u *fname1 = tv_get_string_buf_chk(&argvars[0], buf1);
407 char_u *fname2 = tv_get_string_buf_chk(&argvars[1], buf2);
408 garray_T ga;
409 FILE *fd1;
410 FILE *fd2;
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200411 char line1[200];
412 char line2[200];
413 int lineidx = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200414
Bram Moolenaar7177da92020-07-12 23:09:20 +0200415 if (called_emsg > called_emsg_before)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200416 return 0;
417
418 IObuff[0] = NUL;
419 fd1 = mch_fopen((char *)fname1, READBIN);
420 if (fd1 == NULL)
421 {
422 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1);
423 }
424 else
425 {
426 fd2 = mch_fopen((char *)fname2, READBIN);
427 if (fd2 == NULL)
428 {
429 fclose(fd1);
430 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2);
431 }
432 else
433 {
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200434 int c1, c2;
435 long count = 0;
436 long linecount = 1;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200437
438 for (;;)
439 {
440 c1 = fgetc(fd1);
441 c2 = fgetc(fd2);
442 if (c1 == EOF)
443 {
444 if (c2 != EOF)
445 STRCPY(IObuff, "first file is shorter");
446 break;
447 }
448 else if (c2 == EOF)
449 {
450 STRCPY(IObuff, "second file is shorter");
451 break;
452 }
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200453 else
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200454 {
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200455 line1[lineidx] = c1;
456 line2[lineidx] = c2;
457 ++lineidx;
458 if (c1 != c2)
459 {
460 vim_snprintf((char *)IObuff, IOSIZE,
461 "difference at byte %ld, line %ld",
462 count, linecount);
463 break;
464 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200465 }
466 ++count;
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200467 if (c1 == NL)
468 {
469 ++linecount;
470 lineidx = 0;
471 }
472 else if (lineidx + 2 == (int)sizeof(line1))
473 {
474 mch_memmove(line1, line1 + 100, lineidx - 100);
475 mch_memmove(line2, line2 + 100, lineidx - 100);
476 lineidx -= 100;
477 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200478 }
479 fclose(fd1);
480 fclose(fd2);
481 }
482 }
483 if (IObuff[0] != NUL)
484 {
485 prepare_assert_error(&ga);
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200486 if (argvars[2].v_type != VAR_UNKNOWN)
487 {
488 char_u numbuf[NUMBUFLEN];
489 char_u *tofree;
490
491 ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0));
492 vim_free(tofree);
493 ga_concat(&ga, (char_u *)": ");
494 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200495 ga_concat(&ga, IObuff);
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200496 if (lineidx > 0)
497 {
498 line1[lineidx] = NUL;
499 line2[lineidx] = NUL;
500 ga_concat(&ga, (char_u *)" after \"");
501 ga_concat(&ga, (char_u *)line1);
502 if (STRCMP(line1, line2) != 0)
503 {
504 ga_concat(&ga, (char_u *)"\" vs \"");
505 ga_concat(&ga, (char_u *)line2);
506 }
507 ga_concat(&ga, (char_u *)"\"");
508 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200509 assert_error(&ga);
510 ga_clear(&ga);
511 return 1;
512 }
513 return 0;
514}
515
516/*
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200517 * "assert_equalfile(fname-one, fname-two[, msg])" function
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200518 */
519 void
520f_assert_equalfile(typval_T *argvars, typval_T *rettv)
521{
522 rettv->vval.v_number = assert_equalfile(argvars);
523}
524
525/*
526 * "assert_notequal(expected, actual[, msg])" function
527 */
528 void
529f_assert_notequal(typval_T *argvars, typval_T *rettv)
530{
531 rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
532}
533
534/*
535 * "assert_exception(string[, msg])" function
536 */
537 void
538f_assert_exception(typval_T *argvars, typval_T *rettv)
539{
540 garray_T ga;
541 char_u *error = tv_get_string_chk(&argvars[0]);
542
543 if (*get_vim_var_str(VV_EXCEPTION) == NUL)
544 {
545 prepare_assert_error(&ga);
546 ga_concat(&ga, (char_u *)"v:exception is not set");
547 assert_error(&ga);
548 ga_clear(&ga);
549 rettv->vval.v_number = 1;
550 }
551 else if (error != NULL
552 && strstr((char *)get_vim_var_str(VV_EXCEPTION), (char *)error) == NULL)
553 {
554 prepare_assert_error(&ga);
555 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
556 get_vim_var_tv(VV_EXCEPTION), ASSERT_OTHER);
557 assert_error(&ga);
558 ga_clear(&ga);
559 rettv->vval.v_number = 1;
560 }
561}
562
563/*
564 * "assert_fails(cmd [, error[, msg]])" function
565 */
566 void
567f_assert_fails(typval_T *argvars, typval_T *rettv)
568{
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200569 char_u *cmd;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200570 garray_T ga;
571 int save_trylevel = trylevel;
Bram Moolenaar53989552019-12-23 22:59:18 +0100572 int called_emsg_before = called_emsg;
Bram Moolenaar44d66522020-09-06 22:26:57 +0200573 char *wrong_arg_msg = NULL;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200574
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200575 if (check_for_string_or_number_arg(argvars, 0) == FAIL
576 || check_for_opt_string_or_list_arg(argvars, 1) == FAIL
577 || (argvars[1].v_type != VAR_UNKNOWN
578 && (argvars[2].v_type != VAR_UNKNOWN
579 && (check_for_opt_number_arg(argvars, 3) == FAIL
580 || (argvars[3].v_type != VAR_UNKNOWN
581 && check_for_opt_string_arg(argvars, 4) == FAIL)))))
582 return;
583
584 cmd = tv_get_string_chk(&argvars[0]);
585
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200586 // trylevel must be zero for a ":throw" command to be considered failed
587 trylevel = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200588 suppress_errthrow = TRUE;
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100589 in_assert_fails = TRUE;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200590
591 do_cmdline_cmd(cmd);
Bram Moolenaar53989552019-12-23 22:59:18 +0100592 if (called_emsg == called_emsg_before)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200593 {
594 prepare_assert_error(&ga);
595 ga_concat(&ga, (char_u *)"command did not fail: ");
596 assert_append_cmd_or_arg(&ga, argvars, cmd);
597 assert_error(&ga);
598 ga_clear(&ga);
599 rettv->vval.v_number = 1;
600 }
601 else if (argvars[1].v_type != VAR_UNKNOWN)
602 {
603 char_u buf[NUMBUFLEN];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200604 char_u *expected;
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100605 char_u *expected_str = NULL;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200606 int error_found = FALSE;
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200607 int error_found_index = 1;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200608 char_u *actual = emsg_assert_fails_msg == NULL ? (char_u *)"[unknown]"
609 : emsg_assert_fails_msg;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200610
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200611 if (argvars[1].v_type == VAR_STRING)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200612 {
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200613 expected = tv_get_string_buf_chk(&argvars[1], buf);
614 error_found = expected == NULL
615 || strstr((char *)actual, (char *)expected) == NULL;
616 }
617 else if (argvars[1].v_type == VAR_LIST)
618 {
619 list_T *list = argvars[1].vval.v_list;
620 typval_T *tv;
621
622 if (list == NULL || list->lv_len < 1 || list->lv_len > 2)
623 {
Bram Moolenaar44d66522020-09-06 22:26:57 +0200624 wrong_arg_msg = e_assert_fails_second_arg;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200625 goto theend;
626 }
627 CHECK_LIST_MATERIALIZE(list);
628 tv = &list->lv_first->li_tv;
629 expected = tv_get_string_buf_chk(tv, buf);
630 if (!pattern_match(expected, actual, FALSE))
631 {
632 error_found = TRUE;
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100633 expected_str = expected;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200634 }
635 else if (list->lv_len == 2)
636 {
637 tv = &list->lv_u.mat.lv_last->li_tv;
638 actual = get_vim_var_str(VV_ERRMSG);
639 expected = tv_get_string_buf_chk(tv, buf);
640 if (!pattern_match(expected, actual, FALSE))
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100641 {
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200642 error_found = TRUE;
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100643 expected_str = expected;
644 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200645 }
646 }
647 else
648 {
Bram Moolenaar44d66522020-09-06 22:26:57 +0200649 wrong_arg_msg = e_assert_fails_second_arg;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200650 goto theend;
651 }
652
Bram Moolenaar9b02d642020-08-18 23:24:13 +0200653 if (!error_found && argvars[2].v_type != VAR_UNKNOWN
Bram Moolenaar44d66522020-09-06 22:26:57 +0200654 && argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar1d634542020-08-18 13:41:50 +0200655 {
Bram Moolenaar44d66522020-09-06 22:26:57 +0200656 if (argvars[3].v_type != VAR_NUMBER)
657 {
658 wrong_arg_msg = e_assert_fails_fourth_argument;
659 goto theend;
660 }
661 else if (argvars[3].vval.v_number >= 0
662 && argvars[3].vval.v_number != emsg_assert_fails_lnum)
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200663 {
664 error_found = TRUE;
665 error_found_index = 3;
666 }
Bram Moolenaar44d66522020-09-06 22:26:57 +0200667 if (!error_found && argvars[4].v_type != VAR_UNKNOWN)
668 {
669 if (argvars[4].v_type != VAR_STRING)
670 {
671 wrong_arg_msg = e_assert_fails_fifth_argument;
672 goto theend;
673 }
674 else if (argvars[4].vval.v_string != NULL
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200675 && !pattern_match(argvars[4].vval.v_string,
676 emsg_assert_fails_context, FALSE))
Bram Moolenaar44d66522020-09-06 22:26:57 +0200677 {
678 error_found = TRUE;
679 error_found_index = 4;
680 }
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200681 }
Bram Moolenaar1d634542020-08-18 13:41:50 +0200682 }
683
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200684 if (error_found)
685 {
686 typval_T actual_tv;
687
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200688 prepare_assert_error(&ga);
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200689 if (error_found_index == 3)
Bram Moolenaar1d634542020-08-18 13:41:50 +0200690 {
691 actual_tv.v_type = VAR_NUMBER;
692 actual_tv.vval.v_number = emsg_assert_fails_lnum;
693 }
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200694 else if (error_found_index == 4)
695 {
696 actual_tv.v_type = VAR_STRING;
697 actual_tv.vval.v_string = emsg_assert_fails_context;
698 }
Bram Moolenaar1d634542020-08-18 13:41:50 +0200699 else
700 {
701 actual_tv.v_type = VAR_STRING;
702 actual_tv.vval.v_string = actual;
703 }
Bram Moolenaar631e8f92020-11-04 15:07:16 +0100704 fill_assert_error(&ga, &argvars[2], expected_str,
Bram Moolenaar9bd5d872020-09-06 21:47:48 +0200705 &argvars[error_found_index], &actual_tv, ASSERT_OTHER);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200706 ga_concat(&ga, (char_u *)": ");
707 assert_append_cmd_or_arg(&ga, argvars, cmd);
708 assert_error(&ga);
709 ga_clear(&ga);
710 rettv->vval.v_number = 1;
711 }
712 }
713
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200714theend:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200715 trylevel = save_trylevel;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200716 suppress_errthrow = FALSE;
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100717 in_assert_fails = FALSE;
718 did_emsg = FALSE;
719 msg_col = 0;
720 need_wait_return = FALSE;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200721 emsg_on_display = FALSE;
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100722 msg_scrolled = 0;
723 lines_left = Rows;
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200724 VIM_CLEAR(emsg_assert_fails_msg);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200725 set_vim_var_string(VV_ERRMSG, NULL, 0);
Bram Moolenaar44d66522020-09-06 22:26:57 +0200726 if (wrong_arg_msg != NULL)
727 emsg(_(wrong_arg_msg));
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200728}
729
730/*
731 * "assert_false(actual[, msg])" function
732 */
733 void
734f_assert_false(typval_T *argvars, typval_T *rettv)
735{
736 rettv->vval.v_number = assert_bool(argvars, FALSE);
737}
738
739 static int
740assert_inrange(typval_T *argvars)
741{
742 garray_T ga;
743 int error = FALSE;
744 char_u *tofree;
745 char msg[200];
746 char_u numbuf[NUMBUFLEN];
747
748#ifdef FEAT_FLOAT
749 if (argvars[0].v_type == VAR_FLOAT
750 || argvars[1].v_type == VAR_FLOAT
751 || argvars[2].v_type == VAR_FLOAT)
752 {
753 float_T flower = tv_get_float(&argvars[0]);
754 float_T fupper = tv_get_float(&argvars[1]);
755 float_T factual = tv_get_float(&argvars[2]);
756
757 if (factual < flower || factual > fupper)
758 {
759 prepare_assert_error(&ga);
760 if (argvars[3].v_type != VAR_UNKNOWN)
761 {
762 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
763 vim_free(tofree);
764 }
765 else
766 {
767 vim_snprintf(msg, 200, "Expected range %g - %g, but got %g",
768 flower, fupper, factual);
769 ga_concat(&ga, (char_u *)msg);
770 }
771 assert_error(&ga);
772 ga_clear(&ga);
773 return 1;
774 }
775 }
776 else
777#endif
778 {
779 varnumber_T lower = tv_get_number_chk(&argvars[0], &error);
780 varnumber_T upper = tv_get_number_chk(&argvars[1], &error);
781 varnumber_T actual = tv_get_number_chk(&argvars[2], &error);
782
783 if (error)
784 return 0;
785 if (actual < lower || actual > upper)
786 {
787 prepare_assert_error(&ga);
788 if (argvars[3].v_type != VAR_UNKNOWN)
789 {
790 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
791 vim_free(tofree);
792 }
793 else
794 {
795 vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
796 (long)lower, (long)upper, (long)actual);
797 ga_concat(&ga, (char_u *)msg);
798 }
799 assert_error(&ga);
800 ga_clear(&ga);
801 return 1;
802 }
803 }
804 return 0;
805}
806
807/*
808 * "assert_inrange(lower, upper[, msg])" function
809 */
810 void
811f_assert_inrange(typval_T *argvars, typval_T *rettv)
812{
Yegappan Lakshmanana764e732021-07-25 15:57:32 +0200813 if (check_for_float_or_nr_arg(argvars, 0) == FAIL
814 || check_for_float_or_nr_arg(argvars, 1) == FAIL
815 || check_for_float_or_nr_arg(argvars, 2) == FAIL
816 || check_for_opt_string_arg(argvars, 3) == FAIL)
817 return;
818
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200819 rettv->vval.v_number = assert_inrange(argvars);
820}
821
822/*
823 * "assert_match(pattern, actual[, msg])" function
824 */
825 void
826f_assert_match(typval_T *argvars, typval_T *rettv)
827{
828 rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH);
829}
830
831/*
832 * "assert_notmatch(pattern, actual[, msg])" function
833 */
834 void
835f_assert_notmatch(typval_T *argvars, typval_T *rettv)
836{
837 rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
838}
839
840/*
841 * "assert_report(msg)" function
842 */
843 void
844f_assert_report(typval_T *argvars, typval_T *rettv)
845{
846 garray_T ga;
847
Yegappan Lakshmananc72bdd22021-07-11 19:44:18 +0200848 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
849 return;
850
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200851 prepare_assert_error(&ga);
852 ga_concat(&ga, tv_get_string(&argvars[0]));
853 assert_error(&ga);
854 ga_clear(&ga);
855 rettv->vval.v_number = 1;
856}
857
858/*
859 * "assert_true(actual[, msg])" function
860 */
861 void
862f_assert_true(typval_T *argvars, typval_T *rettv)
863{
864 rettv->vval.v_number = assert_bool(argvars, TRUE);
865}
866
867/*
868 * "test_alloc_fail(id, countdown, repeat)" function
869 */
870 void
871f_test_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED)
872{
873 if (argvars[0].v_type != VAR_NUMBER
874 || argvars[0].vval.v_number <= 0
875 || argvars[1].v_type != VAR_NUMBER
876 || argvars[1].vval.v_number < 0
877 || argvars[2].v_type != VAR_NUMBER)
878 emsg(_(e_invarg));
879 else
880 {
881 alloc_fail_id = argvars[0].vval.v_number;
882 if (alloc_fail_id >= aid_last)
883 emsg(_(e_invarg));
884 alloc_fail_countdown = argvars[1].vval.v_number;
885 alloc_fail_repeat = argvars[2].vval.v_number;
886 did_outofmem_msg = FALSE;
887 }
888}
889
890/*
891 * "test_autochdir()"
892 */
893 void
894f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
895{
896#if defined(FEAT_AUTOCHDIR)
897 test_autochdir = TRUE;
898#endif
899}
900
901/*
902 * "test_feedinput()"
903 */
904 void
905f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED)
906{
907#ifdef USE_INPUT_BUF
908 char_u *val = tv_get_string_chk(&argvars[0]);
909
Bram Moolenaar272ca952020-01-28 20:49:11 +0100910# ifdef VIMDLL
911 // this doesn't work in the console
912 if (!gui.in_use)
913 return;
914# endif
915
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200916 if (val != NULL)
917 {
918 trash_input_buf();
919 add_to_input_buf_csi(val, (int)STRLEN(val));
920 }
921#endif
922}
923
924/*
925 * "test_getvalue({name})" function
926 */
927 void
928f_test_getvalue(typval_T *argvars, typval_T *rettv)
929{
930 if (argvars[0].v_type != VAR_STRING)
931 emsg(_(e_invarg));
932 else
933 {
934 char_u *name = tv_get_string(&argvars[0]);
935
936 if (STRCMP(name, (char_u *)"need_fileinfo") == 0)
937 rettv->vval.v_number = need_fileinfo;
938 else
939 semsg(_(e_invarg2), name);
940 }
941}
942
943/*
944 * "test_option_not_set({name})" function
945 */
946 void
947f_test_option_not_set(typval_T *argvars, typval_T *rettv UNUSED)
948{
949 char_u *name = (char_u *)"";
950
951 if (argvars[0].v_type != VAR_STRING)
952 emsg(_(e_invarg));
953 else
954 {
955 name = tv_get_string(&argvars[0]);
956 if (reset_option_was_set(name) == FAIL)
957 semsg(_(e_invarg2), name);
958 }
959}
960
961/*
962 * "test_override({name}, {val})" function
963 */
964 void
965f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
966{
967 char_u *name = (char_u *)"";
968 int val;
969 static int save_starting = -1;
970
Yegappan Lakshmanan1a71d312021-07-15 12:49:58 +0200971 if (in_vim9script()
972 && (check_for_string_arg(argvars, 0) == FAIL
973 || check_for_number_arg(argvars, 1) == FAIL))
974 return;
975
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200976 if (argvars[0].v_type != VAR_STRING
977 || (argvars[1].v_type) != VAR_NUMBER)
978 emsg(_(e_invarg));
979 else
980 {
981 name = tv_get_string(&argvars[0]);
982 val = (int)tv_get_number(&argvars[1]);
983
984 if (STRCMP(name, (char_u *)"redraw") == 0)
985 disable_redraw_for_testing = val;
986 else if (STRCMP(name, (char_u *)"redraw_flag") == 0)
987 ignore_redraw_flag_for_testing = val;
988 else if (STRCMP(name, (char_u *)"char_avail") == 0)
989 disable_char_avail_for_testing = val;
990 else if (STRCMP(name, (char_u *)"starting") == 0)
991 {
992 if (val)
993 {
994 if (save_starting < 0)
995 save_starting = starting;
996 starting = 0;
997 }
998 else
999 {
1000 starting = save_starting;
1001 save_starting = -1;
1002 }
1003 }
1004 else if (STRCMP(name, (char_u *)"nfa_fail") == 0)
1005 nfa_fail_for_testing = val;
1006 else if (STRCMP(name, (char_u *)"no_query_mouse") == 0)
1007 no_query_mouse_for_testing = val;
1008 else if (STRCMP(name, (char_u *)"no_wait_return") == 0)
1009 no_wait_return = val;
Bram Moolenaarb340bae2020-06-15 19:51:56 +02001010 else if (STRCMP(name, (char_u *)"ui_delay") == 0)
1011 ui_delay_for_testing = val;
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001012 else if (STRCMP(name, (char_u *)"term_props") == 0)
1013 reset_term_props_on_termresponse = val;
Bram Moolenaarf52f0602021-03-10 21:26:37 +01001014 else if (STRCMP(name, (char_u *)"uptime") == 0)
1015 override_sysinfo_uptime = val;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001016 else if (STRCMP(name, (char_u *)"ALL") == 0)
1017 {
1018 disable_char_avail_for_testing = FALSE;
1019 disable_redraw_for_testing = FALSE;
1020 ignore_redraw_flag_for_testing = FALSE;
1021 nfa_fail_for_testing = FALSE;
1022 no_query_mouse_for_testing = FALSE;
Bram Moolenaarb340bae2020-06-15 19:51:56 +02001023 ui_delay_for_testing = 0;
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001024 reset_term_props_on_termresponse = FALSE;
Bram Moolenaarf52f0602021-03-10 21:26:37 +01001025 override_sysinfo_uptime = -1;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001026 if (save_starting >= 0)
1027 {
1028 starting = save_starting;
1029 save_starting = -1;
1030 }
1031 }
1032 else
1033 semsg(_(e_invarg2), name);
1034 }
1035}
1036
1037/*
1038 * "test_refcount({expr})" function
1039 */
1040 void
1041f_test_refcount(typval_T *argvars, typval_T *rettv)
1042{
1043 int retval = -1;
1044
1045 switch (argvars[0].v_type)
1046 {
1047 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001048 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001049 case VAR_VOID:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001050 case VAR_NUMBER:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001051 case VAR_BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001052 case VAR_FLOAT:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001053 case VAR_SPECIAL:
1054 case VAR_STRING:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001055 case VAR_INSTR:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001056 break;
1057 case VAR_JOB:
1058#ifdef FEAT_JOB_CHANNEL
1059 if (argvars[0].vval.v_job != NULL)
1060 retval = argvars[0].vval.v_job->jv_refcount - 1;
1061#endif
1062 break;
1063 case VAR_CHANNEL:
1064#ifdef FEAT_JOB_CHANNEL
1065 if (argvars[0].vval.v_channel != NULL)
1066 retval = argvars[0].vval.v_channel->ch_refcount - 1;
1067#endif
1068 break;
1069 case VAR_FUNC:
1070 if (argvars[0].vval.v_string != NULL)
1071 {
1072 ufunc_T *fp;
1073
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02001074 fp = find_func(argvars[0].vval.v_string, FALSE, NULL);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001075 if (fp != NULL)
1076 retval = fp->uf_refcount;
1077 }
1078 break;
1079 case VAR_PARTIAL:
1080 if (argvars[0].vval.v_partial != NULL)
1081 retval = argvars[0].vval.v_partial->pt_refcount - 1;
1082 break;
1083 case VAR_BLOB:
1084 if (argvars[0].vval.v_blob != NULL)
1085 retval = argvars[0].vval.v_blob->bv_refcount - 1;
1086 break;
1087 case VAR_LIST:
1088 if (argvars[0].vval.v_list != NULL)
1089 retval = argvars[0].vval.v_list->lv_refcount - 1;
1090 break;
1091 case VAR_DICT:
1092 if (argvars[0].vval.v_dict != NULL)
1093 retval = argvars[0].vval.v_dict->dv_refcount - 1;
1094 break;
1095 }
1096
1097 rettv->v_type = VAR_NUMBER;
1098 rettv->vval.v_number = retval;
1099
1100}
1101
1102/*
1103 * "test_garbagecollect_now()" function
1104 */
1105 void
1106f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1107{
Bram Moolenaar0d6f5d92019-12-05 21:33:15 +01001108 // This is dangerous, any Lists and Dicts used internally may be freed
1109 // while still in use.
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001110 garbage_collect(TRUE);
1111}
1112
1113/*
1114 * "test_garbagecollect_soon()" function
1115 */
1116 void
1117f_test_garbagecollect_soon(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1118{
1119 may_garbage_collect = TRUE;
1120}
1121
1122/*
1123 * "test_ignore_error()" function
1124 */
1125 void
1126f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED)
1127{
Yegappan Lakshmanan5b739922021-07-10 13:15:41 +02001128 if (argvars[0].v_type != VAR_STRING)
1129 emsg(_(e_invarg));
1130 else
1131 ignore_error_for_testing(tv_get_string(&argvars[0]));
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001132}
1133
1134 void
1135f_test_null_blob(typval_T *argvars UNUSED, typval_T *rettv)
1136{
1137 rettv->v_type = VAR_BLOB;
1138 rettv->vval.v_blob = NULL;
1139}
1140
1141#ifdef FEAT_JOB_CHANNEL
1142 void
1143f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv)
1144{
1145 rettv->v_type = VAR_CHANNEL;
1146 rettv->vval.v_channel = NULL;
1147}
1148#endif
1149
1150 void
1151f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv)
1152{
1153 rettv_dict_set(rettv, NULL);
1154}
1155
1156#ifdef FEAT_JOB_CHANNEL
1157 void
1158f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv)
1159{
1160 rettv->v_type = VAR_JOB;
1161 rettv->vval.v_job = NULL;
1162}
1163#endif
1164
1165 void
1166f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv)
1167{
1168 rettv_list_set(rettv, NULL);
1169}
1170
1171 void
Bram Moolenaare69f6d02020-04-01 22:11:01 +02001172f_test_null_function(typval_T *argvars UNUSED, typval_T *rettv)
1173{
1174 rettv->v_type = VAR_FUNC;
1175 rettv->vval.v_string = NULL;
1176}
1177
1178 void
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001179f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv)
1180{
1181 rettv->v_type = VAR_PARTIAL;
1182 rettv->vval.v_partial = NULL;
1183}
1184
1185 void
1186f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv)
1187{
1188 rettv->v_type = VAR_STRING;
1189 rettv->vval.v_string = NULL;
1190}
1191
Bram Moolenaar8ed04582020-02-22 19:07:28 +01001192 void
1193f_test_unknown(typval_T *argvars UNUSED, typval_T *rettv)
1194{
1195 rettv->v_type = VAR_UNKNOWN;
1196}
1197
1198 void
1199f_test_void(typval_T *argvars UNUSED, typval_T *rettv)
1200{
1201 rettv->v_type = VAR_VOID;
1202}
1203
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001204#ifdef FEAT_GUI
1205 void
1206f_test_scrollbar(typval_T *argvars, typval_T *rettv UNUSED)
1207{
1208 char_u *which;
1209 long value;
1210 int dragging;
1211 scrollbar_T *sb = NULL;
1212
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001213 if (check_for_string_arg(argvars, 0) == FAIL
1214 || check_for_number_arg(argvars, 1) == FAIL
1215 || check_for_number_arg(argvars, 2) == FAIL)
1216 return;
1217
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001218 if (argvars[0].v_type != VAR_STRING
1219 || (argvars[1].v_type) != VAR_NUMBER
1220 || (argvars[2].v_type) != VAR_NUMBER)
1221 {
1222 emsg(_(e_invarg));
1223 return;
1224 }
1225 which = tv_get_string(&argvars[0]);
1226 value = tv_get_number(&argvars[1]);
1227 dragging = tv_get_number(&argvars[2]);
1228
1229 if (STRCMP(which, "left") == 0)
1230 sb = &curwin->w_scrollbars[SBAR_LEFT];
1231 else if (STRCMP(which, "right") == 0)
1232 sb = &curwin->w_scrollbars[SBAR_RIGHT];
1233 else if (STRCMP(which, "hor") == 0)
1234 sb = &gui.bottom_sbar;
1235 if (sb == NULL)
1236 {
1237 semsg(_(e_invarg2), which);
1238 return;
1239 }
1240 gui_drag_scrollbar(sb, value, dragging);
1241# ifndef USE_ON_FLY_SCROLL
1242 // need to loop through normal_cmd() to handle the scroll events
1243 exec_normal(FALSE, TRUE, FALSE);
1244# endif
1245}
1246#endif
1247
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001248 void
1249f_test_setmouse(typval_T *argvars, typval_T *rettv UNUSED)
1250{
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001251 if (argvars[0].v_type != VAR_NUMBER || (argvars[1].v_type) != VAR_NUMBER)
1252 {
1253 emsg(_(e_invarg));
1254 return;
1255 }
1256
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001257 mouse_row = (time_t)tv_get_number(&argvars[0]) - 1;
1258 mouse_col = (time_t)tv_get_number(&argvars[1]) - 1;
1259}
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001260
1261 void
Yegappan Lakshmananf1e74492021-06-21 18:44:26 +02001262f_test_gui_mouse_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1263{
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001264# ifdef FEAT_GUI
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001265 int button;
1266 int row;
1267 int col;
1268 int repeated_click;
1269 int_u mods;
1270
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02001271 if (check_for_number_arg(argvars, 0) == FAIL
1272 || check_for_number_arg(argvars, 1) == FAIL
1273 || check_for_number_arg(argvars, 2) == FAIL
1274 || check_for_number_arg(argvars, 3) == FAIL
1275 || check_for_number_arg(argvars, 4) == FAIL)
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001276 return;
Yegappan Lakshmanan7237cab2021-06-22 19:52:27 +02001277
1278 button = tv_get_number(&argvars[0]);
1279 row = tv_get_number(&argvars[1]);
1280 col = tv_get_number(&argvars[2]);
1281 repeated_click = tv_get_number(&argvars[3]);
1282 mods = tv_get_number(&argvars[4]);
Yegappan Lakshmananf1e74492021-06-21 18:44:26 +02001283
1284 gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), repeated_click, mods);
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001285# endif
Yegappan Lakshmananf1e74492021-06-21 18:44:26 +02001286}
1287
1288 void
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001289f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
1290{
1291 time_for_testing = (time_t)tv_get_number(&argvars[0]);
1292}
1293
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001294 void
1295f_test_gui_drop_files(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1296{
Bram Moolenaar1d1ce612021-06-27 19:02:52 +02001297#if defined(HAVE_DROP_FILE)
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001298 int row;
1299 int col;
1300 int_u mods;
1301 char_u **fnames;
1302 int count = 0;
1303 list_T *l;
1304 listitem_T *li;
1305
Yegappan Lakshmanan5bca9062021-07-24 21:33:26 +02001306 if (check_for_list_arg(argvars, 0) == FAIL
1307 || check_for_number_arg(argvars, 1) == FAIL
1308 || check_for_number_arg(argvars, 2) == FAIL
1309 || check_for_number_arg(argvars, 3) == FAIL)
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001310 return;
Yegappan Lakshmanan18d46582021-06-23 20:46:52 +02001311
1312 row = tv_get_number(&argvars[1]);
1313 col = tv_get_number(&argvars[2]);
1314 mods = tv_get_number(&argvars[3]);
1315
1316 l = argvars[0].vval.v_list;
1317 if (list_len(l) == 0)
1318 return;
1319
1320 fnames = ALLOC_MULT(char_u *, list_len(l));
1321 if (fnames == NULL)
1322 return;
1323
1324 FOR_ALL_LIST_ITEMS(l, li)
1325 {
1326 // ignore non-string items
1327 if (li->li_tv.v_type != VAR_STRING)
1328 continue;
1329
1330 fnames[count] = vim_strsave(li->li_tv.vval.v_string);
1331 if (fnames[count] == NULL)
1332 {
1333 while (--count >= 0)
1334 vim_free(fnames[count]);
1335 vim_free(fnames);
1336 return;
1337 }
1338 count++;
1339 }
1340
1341 if (count > 0)
1342 gui_handle_drop(TEXT_X(col - 1), TEXT_Y(row - 1), mods, fnames, count);
1343 else
1344 vim_free(fnames);
1345# endif
1346}
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001347
1348#endif // defined(FEAT_EVAL)