blob: fa8cc42418648815aea6e889768cc05c72979246 [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];
25 char_u *sname = estack_sfile();
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:
69 if (*p < ' ')
70 {
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,
134 typval_T *exp_tv,
135 typval_T *got_tv,
136 assert_type_T atype)
137{
138 char_u numbuf[NUMBUFLEN];
139 char_u *tofree;
140
141 if (opt_msg_tv->v_type != VAR_UNKNOWN)
142 {
143 ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0));
144 vim_free(tofree);
145 ga_concat(gap, (char_u *)": ");
146 }
147
148 if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH)
149 ga_concat(gap, (char_u *)"Pattern ");
150 else if (atype == ASSERT_NOTEQUAL)
151 ga_concat(gap, (char_u *)"Expected not equal to ");
152 else
153 ga_concat(gap, (char_u *)"Expected ");
154 if (exp_str == NULL)
155 {
156 ga_concat_shorten_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0));
157 vim_free(tofree);
158 }
159 else
160 ga_concat_shorten_esc(gap, exp_str);
161 if (atype != ASSERT_NOTEQUAL)
162 {
163 if (atype == ASSERT_MATCH)
164 ga_concat(gap, (char_u *)" does not match ");
165 else if (atype == ASSERT_NOTMATCH)
166 ga_concat(gap, (char_u *)" does match ");
167 else
168 ga_concat(gap, (char_u *)" but got ");
169 ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
170 vim_free(tofree);
171 }
172}
173
174 static int
175assert_equal_common(typval_T *argvars, assert_type_T atype)
176{
177 garray_T ga;
178
179 if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)
180 != (atype == ASSERT_EQUAL))
181 {
182 prepare_assert_error(&ga);
183 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
184 atype);
185 assert_error(&ga);
186 ga_clear(&ga);
187 return 1;
188 }
189 return 0;
190}
191
192 static int
193assert_match_common(typval_T *argvars, assert_type_T atype)
194{
195 garray_T ga;
196 char_u buf1[NUMBUFLEN];
197 char_u buf2[NUMBUFLEN];
198 char_u *pat = tv_get_string_buf_chk(&argvars[0], buf1);
199 char_u *text = tv_get_string_buf_chk(&argvars[1], buf2);
200
201 if (pat == NULL || text == NULL)
202 emsg(_(e_invarg));
203 else if (pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH))
204 {
205 prepare_assert_error(&ga);
206 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
207 atype);
208 assert_error(&ga);
209 ga_clear(&ga);
210 return 1;
211 }
212 return 0;
213}
214
215/*
216 * Common for assert_true() and assert_false().
217 * Return non-zero for failure.
218 */
219 static int
220assert_bool(typval_T *argvars, int isTrue)
221{
222 int error = FALSE;
223 garray_T ga;
224
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100225 if (argvars[0].v_type == VAR_BOOL
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200226 && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE))
227 return 0;
228 if (argvars[0].v_type != VAR_NUMBER
229 || (tv_get_number_chk(&argvars[0], &error) == 0) == isTrue
230 || error)
231 {
232 prepare_assert_error(&ga);
233 fill_assert_error(&ga, &argvars[1],
234 (char_u *)(isTrue ? "True" : "False"),
235 NULL, &argvars[0], ASSERT_OTHER);
236 assert_error(&ga);
237 ga_clear(&ga);
238 return 1;
239 }
240 return 0;
241}
242
243 static void
244assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, char_u *cmd)
245{
246 char_u *tofree;
247 char_u numbuf[NUMBUFLEN];
248
249 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
250 {
251 ga_concat(gap, echo_string(&argvars[2], &tofree, numbuf, 0));
252 vim_free(tofree);
253 }
254 else
255 ga_concat(gap, cmd);
256}
257
258 static int
259assert_beeps(typval_T *argvars)
260{
261 char_u *cmd = tv_get_string_chk(&argvars[0]);
262 garray_T ga;
263 int ret = 0;
264
265 called_vim_beep = FALSE;
266 suppress_errthrow = TRUE;
267 emsg_silent = FALSE;
268 do_cmdline_cmd(cmd);
269 if (!called_vim_beep)
270 {
271 prepare_assert_error(&ga);
272 ga_concat(&ga, (char_u *)"command did not beep: ");
273 ga_concat(&ga, cmd);
274 assert_error(&ga);
275 ga_clear(&ga);
276 ret = 1;
277 }
278
279 suppress_errthrow = FALSE;
280 emsg_on_display = FALSE;
281 return ret;
282}
283
284/*
285 * "assert_beeps(cmd [, error])" function
286 */
287 void
288f_assert_beeps(typval_T *argvars, typval_T *rettv)
289{
290 rettv->vval.v_number = assert_beeps(argvars);
291}
292
293/*
294 * "assert_equal(expected, actual[, msg])" function
295 */
296 void
297f_assert_equal(typval_T *argvars, typval_T *rettv)
298{
299 rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
300}
301
302 static int
303assert_equalfile(typval_T *argvars)
304{
305 char_u buf1[NUMBUFLEN];
306 char_u buf2[NUMBUFLEN];
307 char_u *fname1 = tv_get_string_buf_chk(&argvars[0], buf1);
308 char_u *fname2 = tv_get_string_buf_chk(&argvars[1], buf2);
309 garray_T ga;
310 FILE *fd1;
311 FILE *fd2;
312
313 if (fname1 == NULL || fname2 == NULL)
314 return 0;
315
316 IObuff[0] = NUL;
317 fd1 = mch_fopen((char *)fname1, READBIN);
318 if (fd1 == NULL)
319 {
320 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1);
321 }
322 else
323 {
324 fd2 = mch_fopen((char *)fname2, READBIN);
325 if (fd2 == NULL)
326 {
327 fclose(fd1);
328 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2);
329 }
330 else
331 {
332 int c1, c2;
333 long count = 0;
334
335 for (;;)
336 {
337 c1 = fgetc(fd1);
338 c2 = fgetc(fd2);
339 if (c1 == EOF)
340 {
341 if (c2 != EOF)
342 STRCPY(IObuff, "first file is shorter");
343 break;
344 }
345 else if (c2 == EOF)
346 {
347 STRCPY(IObuff, "second file is shorter");
348 break;
349 }
350 else if (c1 != c2)
351 {
352 vim_snprintf((char *)IObuff, IOSIZE,
353 "difference at byte %ld", count);
354 break;
355 }
356 ++count;
357 }
358 fclose(fd1);
359 fclose(fd2);
360 }
361 }
362 if (IObuff[0] != NUL)
363 {
364 prepare_assert_error(&ga);
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200365 if (argvars[2].v_type != VAR_UNKNOWN)
366 {
367 char_u numbuf[NUMBUFLEN];
368 char_u *tofree;
369
370 ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0));
371 vim_free(tofree);
372 ga_concat(&ga, (char_u *)": ");
373 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200374 ga_concat(&ga, IObuff);
375 assert_error(&ga);
376 ga_clear(&ga);
377 return 1;
378 }
379 return 0;
380}
381
382/*
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200383 * "assert_equalfile(fname-one, fname-two[, msg])" function
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200384 */
385 void
386f_assert_equalfile(typval_T *argvars, typval_T *rettv)
387{
388 rettv->vval.v_number = assert_equalfile(argvars);
389}
390
391/*
392 * "assert_notequal(expected, actual[, msg])" function
393 */
394 void
395f_assert_notequal(typval_T *argvars, typval_T *rettv)
396{
397 rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
398}
399
400/*
401 * "assert_exception(string[, msg])" function
402 */
403 void
404f_assert_exception(typval_T *argvars, typval_T *rettv)
405{
406 garray_T ga;
407 char_u *error = tv_get_string_chk(&argvars[0]);
408
409 if (*get_vim_var_str(VV_EXCEPTION) == NUL)
410 {
411 prepare_assert_error(&ga);
412 ga_concat(&ga, (char_u *)"v:exception is not set");
413 assert_error(&ga);
414 ga_clear(&ga);
415 rettv->vval.v_number = 1;
416 }
417 else if (error != NULL
418 && strstr((char *)get_vim_var_str(VV_EXCEPTION), (char *)error) == NULL)
419 {
420 prepare_assert_error(&ga);
421 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
422 get_vim_var_tv(VV_EXCEPTION), ASSERT_OTHER);
423 assert_error(&ga);
424 ga_clear(&ga);
425 rettv->vval.v_number = 1;
426 }
427}
428
429/*
430 * "assert_fails(cmd [, error[, msg]])" function
431 */
432 void
433f_assert_fails(typval_T *argvars, typval_T *rettv)
434{
435 char_u *cmd = tv_get_string_chk(&argvars[0]);
436 garray_T ga;
437 int save_trylevel = trylevel;
Bram Moolenaar53989552019-12-23 22:59:18 +0100438 int called_emsg_before = called_emsg;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200439
440 // trylevel must be zero for a ":throw" command to be considered failed
441 trylevel = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200442 suppress_errthrow = TRUE;
443 emsg_silent = TRUE;
444
445 do_cmdline_cmd(cmd);
Bram Moolenaar53989552019-12-23 22:59:18 +0100446 if (called_emsg == called_emsg_before)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200447 {
448 prepare_assert_error(&ga);
449 ga_concat(&ga, (char_u *)"command did not fail: ");
450 assert_append_cmd_or_arg(&ga, argvars, cmd);
451 assert_error(&ga);
452 ga_clear(&ga);
453 rettv->vval.v_number = 1;
454 }
455 else if (argvars[1].v_type != VAR_UNKNOWN)
456 {
457 char_u buf[NUMBUFLEN];
458 char *error = (char *)tv_get_string_buf_chk(&argvars[1], buf);
459
460 if (error == NULL
461 || strstr((char *)get_vim_var_str(VV_ERRMSG), error) == NULL)
462 {
463 prepare_assert_error(&ga);
464 fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
465 get_vim_var_tv(VV_ERRMSG), ASSERT_OTHER);
466 ga_concat(&ga, (char_u *)": ");
467 assert_append_cmd_or_arg(&ga, argvars, cmd);
468 assert_error(&ga);
469 ga_clear(&ga);
470 rettv->vval.v_number = 1;
471 }
472 }
473
474 trylevel = save_trylevel;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200475 suppress_errthrow = FALSE;
476 emsg_silent = FALSE;
477 emsg_on_display = FALSE;
478 set_vim_var_string(VV_ERRMSG, NULL, 0);
479}
480
481/*
482 * "assert_false(actual[, msg])" function
483 */
484 void
485f_assert_false(typval_T *argvars, typval_T *rettv)
486{
487 rettv->vval.v_number = assert_bool(argvars, FALSE);
488}
489
490 static int
491assert_inrange(typval_T *argvars)
492{
493 garray_T ga;
494 int error = FALSE;
495 char_u *tofree;
496 char msg[200];
497 char_u numbuf[NUMBUFLEN];
498
499#ifdef FEAT_FLOAT
500 if (argvars[0].v_type == VAR_FLOAT
501 || argvars[1].v_type == VAR_FLOAT
502 || argvars[2].v_type == VAR_FLOAT)
503 {
504 float_T flower = tv_get_float(&argvars[0]);
505 float_T fupper = tv_get_float(&argvars[1]);
506 float_T factual = tv_get_float(&argvars[2]);
507
508 if (factual < flower || factual > fupper)
509 {
510 prepare_assert_error(&ga);
511 if (argvars[3].v_type != VAR_UNKNOWN)
512 {
513 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
514 vim_free(tofree);
515 }
516 else
517 {
518 vim_snprintf(msg, 200, "Expected range %g - %g, but got %g",
519 flower, fupper, factual);
520 ga_concat(&ga, (char_u *)msg);
521 }
522 assert_error(&ga);
523 ga_clear(&ga);
524 return 1;
525 }
526 }
527 else
528#endif
529 {
530 varnumber_T lower = tv_get_number_chk(&argvars[0], &error);
531 varnumber_T upper = tv_get_number_chk(&argvars[1], &error);
532 varnumber_T actual = tv_get_number_chk(&argvars[2], &error);
533
534 if (error)
535 return 0;
536 if (actual < lower || actual > upper)
537 {
538 prepare_assert_error(&ga);
539 if (argvars[3].v_type != VAR_UNKNOWN)
540 {
541 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
542 vim_free(tofree);
543 }
544 else
545 {
546 vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
547 (long)lower, (long)upper, (long)actual);
548 ga_concat(&ga, (char_u *)msg);
549 }
550 assert_error(&ga);
551 ga_clear(&ga);
552 return 1;
553 }
554 }
555 return 0;
556}
557
558/*
559 * "assert_inrange(lower, upper[, msg])" function
560 */
561 void
562f_assert_inrange(typval_T *argvars, typval_T *rettv)
563{
564 rettv->vval.v_number = assert_inrange(argvars);
565}
566
567/*
568 * "assert_match(pattern, actual[, msg])" function
569 */
570 void
571f_assert_match(typval_T *argvars, typval_T *rettv)
572{
573 rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH);
574}
575
576/*
577 * "assert_notmatch(pattern, actual[, msg])" function
578 */
579 void
580f_assert_notmatch(typval_T *argvars, typval_T *rettv)
581{
582 rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
583}
584
585/*
586 * "assert_report(msg)" function
587 */
588 void
589f_assert_report(typval_T *argvars, typval_T *rettv)
590{
591 garray_T ga;
592
593 prepare_assert_error(&ga);
594 ga_concat(&ga, tv_get_string(&argvars[0]));
595 assert_error(&ga);
596 ga_clear(&ga);
597 rettv->vval.v_number = 1;
598}
599
600/*
601 * "assert_true(actual[, msg])" function
602 */
603 void
604f_assert_true(typval_T *argvars, typval_T *rettv)
605{
606 rettv->vval.v_number = assert_bool(argvars, TRUE);
607}
608
609/*
610 * "test_alloc_fail(id, countdown, repeat)" function
611 */
612 void
613f_test_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED)
614{
615 if (argvars[0].v_type != VAR_NUMBER
616 || argvars[0].vval.v_number <= 0
617 || argvars[1].v_type != VAR_NUMBER
618 || argvars[1].vval.v_number < 0
619 || argvars[2].v_type != VAR_NUMBER)
620 emsg(_(e_invarg));
621 else
622 {
623 alloc_fail_id = argvars[0].vval.v_number;
624 if (alloc_fail_id >= aid_last)
625 emsg(_(e_invarg));
626 alloc_fail_countdown = argvars[1].vval.v_number;
627 alloc_fail_repeat = argvars[2].vval.v_number;
628 did_outofmem_msg = FALSE;
629 }
630}
631
632/*
633 * "test_autochdir()"
634 */
635 void
636f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
637{
638#if defined(FEAT_AUTOCHDIR)
639 test_autochdir = TRUE;
640#endif
641}
642
643/*
644 * "test_feedinput()"
645 */
646 void
647f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED)
648{
649#ifdef USE_INPUT_BUF
650 char_u *val = tv_get_string_chk(&argvars[0]);
651
Bram Moolenaar272ca952020-01-28 20:49:11 +0100652# ifdef VIMDLL
653 // this doesn't work in the console
654 if (!gui.in_use)
655 return;
656# endif
657
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200658 if (val != NULL)
659 {
660 trash_input_buf();
661 add_to_input_buf_csi(val, (int)STRLEN(val));
662 }
663#endif
664}
665
666/*
667 * "test_getvalue({name})" function
668 */
669 void
670f_test_getvalue(typval_T *argvars, typval_T *rettv)
671{
672 if (argvars[0].v_type != VAR_STRING)
673 emsg(_(e_invarg));
674 else
675 {
676 char_u *name = tv_get_string(&argvars[0]);
677
678 if (STRCMP(name, (char_u *)"need_fileinfo") == 0)
679 rettv->vval.v_number = need_fileinfo;
680 else
681 semsg(_(e_invarg2), name);
682 }
683}
684
685/*
686 * "test_option_not_set({name})" function
687 */
688 void
689f_test_option_not_set(typval_T *argvars, typval_T *rettv UNUSED)
690{
691 char_u *name = (char_u *)"";
692
693 if (argvars[0].v_type != VAR_STRING)
694 emsg(_(e_invarg));
695 else
696 {
697 name = tv_get_string(&argvars[0]);
698 if (reset_option_was_set(name) == FAIL)
699 semsg(_(e_invarg2), name);
700 }
701}
702
703/*
704 * "test_override({name}, {val})" function
705 */
706 void
707f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
708{
709 char_u *name = (char_u *)"";
710 int val;
711 static int save_starting = -1;
712
713 if (argvars[0].v_type != VAR_STRING
714 || (argvars[1].v_type) != VAR_NUMBER)
715 emsg(_(e_invarg));
716 else
717 {
718 name = tv_get_string(&argvars[0]);
719 val = (int)tv_get_number(&argvars[1]);
720
721 if (STRCMP(name, (char_u *)"redraw") == 0)
722 disable_redraw_for_testing = val;
723 else if (STRCMP(name, (char_u *)"redraw_flag") == 0)
724 ignore_redraw_flag_for_testing = val;
725 else if (STRCMP(name, (char_u *)"char_avail") == 0)
726 disable_char_avail_for_testing = val;
727 else if (STRCMP(name, (char_u *)"starting") == 0)
728 {
729 if (val)
730 {
731 if (save_starting < 0)
732 save_starting = starting;
733 starting = 0;
734 }
735 else
736 {
737 starting = save_starting;
738 save_starting = -1;
739 }
740 }
741 else if (STRCMP(name, (char_u *)"nfa_fail") == 0)
742 nfa_fail_for_testing = val;
743 else if (STRCMP(name, (char_u *)"no_query_mouse") == 0)
744 no_query_mouse_for_testing = val;
745 else if (STRCMP(name, (char_u *)"no_wait_return") == 0)
746 no_wait_return = val;
747 else if (STRCMP(name, (char_u *)"ALL") == 0)
748 {
749 disable_char_avail_for_testing = FALSE;
750 disable_redraw_for_testing = FALSE;
751 ignore_redraw_flag_for_testing = FALSE;
752 nfa_fail_for_testing = FALSE;
753 no_query_mouse_for_testing = FALSE;
754 if (save_starting >= 0)
755 {
756 starting = save_starting;
757 save_starting = -1;
758 }
759 }
760 else
761 semsg(_(e_invarg2), name);
762 }
763}
764
765/*
766 * "test_refcount({expr})" function
767 */
768 void
769f_test_refcount(typval_T *argvars, typval_T *rettv)
770{
771 int retval = -1;
772
773 switch (argvars[0].v_type)
774 {
775 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +0200776 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 case VAR_VOID:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200778 case VAR_NUMBER:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100779 case VAR_BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100780 case VAR_FLOAT:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200781 case VAR_SPECIAL:
782 case VAR_STRING:
783 break;
784 case VAR_JOB:
785#ifdef FEAT_JOB_CHANNEL
786 if (argvars[0].vval.v_job != NULL)
787 retval = argvars[0].vval.v_job->jv_refcount - 1;
788#endif
789 break;
790 case VAR_CHANNEL:
791#ifdef FEAT_JOB_CHANNEL
792 if (argvars[0].vval.v_channel != NULL)
793 retval = argvars[0].vval.v_channel->ch_refcount - 1;
794#endif
795 break;
796 case VAR_FUNC:
797 if (argvars[0].vval.v_string != NULL)
798 {
799 ufunc_T *fp;
800
Bram Moolenaar4c17ad92020-04-27 22:47:51 +0200801 fp = find_func(argvars[0].vval.v_string, FALSE, NULL);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200802 if (fp != NULL)
803 retval = fp->uf_refcount;
804 }
805 break;
806 case VAR_PARTIAL:
807 if (argvars[0].vval.v_partial != NULL)
808 retval = argvars[0].vval.v_partial->pt_refcount - 1;
809 break;
810 case VAR_BLOB:
811 if (argvars[0].vval.v_blob != NULL)
812 retval = argvars[0].vval.v_blob->bv_refcount - 1;
813 break;
814 case VAR_LIST:
815 if (argvars[0].vval.v_list != NULL)
816 retval = argvars[0].vval.v_list->lv_refcount - 1;
817 break;
818 case VAR_DICT:
819 if (argvars[0].vval.v_dict != NULL)
820 retval = argvars[0].vval.v_dict->dv_refcount - 1;
821 break;
822 }
823
824 rettv->v_type = VAR_NUMBER;
825 rettv->vval.v_number = retval;
826
827}
828
829/*
830 * "test_garbagecollect_now()" function
831 */
832 void
833f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
834{
Bram Moolenaar0d6f5d92019-12-05 21:33:15 +0100835 // This is dangerous, any Lists and Dicts used internally may be freed
836 // while still in use.
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200837 garbage_collect(TRUE);
838}
839
840/*
841 * "test_garbagecollect_soon()" function
842 */
843 void
844f_test_garbagecollect_soon(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
845{
846 may_garbage_collect = TRUE;
847}
848
849/*
850 * "test_ignore_error()" function
851 */
852 void
853f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED)
854{
855 ignore_error_for_testing(tv_get_string(&argvars[0]));
856}
857
858 void
859f_test_null_blob(typval_T *argvars UNUSED, typval_T *rettv)
860{
861 rettv->v_type = VAR_BLOB;
862 rettv->vval.v_blob = NULL;
863}
864
865#ifdef FEAT_JOB_CHANNEL
866 void
867f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv)
868{
869 rettv->v_type = VAR_CHANNEL;
870 rettv->vval.v_channel = NULL;
871}
872#endif
873
874 void
875f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv)
876{
877 rettv_dict_set(rettv, NULL);
878}
879
880#ifdef FEAT_JOB_CHANNEL
881 void
882f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv)
883{
884 rettv->v_type = VAR_JOB;
885 rettv->vval.v_job = NULL;
886}
887#endif
888
889 void
890f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv)
891{
892 rettv_list_set(rettv, NULL);
893}
894
895 void
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200896f_test_null_function(typval_T *argvars UNUSED, typval_T *rettv)
897{
898 rettv->v_type = VAR_FUNC;
899 rettv->vval.v_string = NULL;
900}
901
902 void
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200903f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv)
904{
905 rettv->v_type = VAR_PARTIAL;
906 rettv->vval.v_partial = NULL;
907}
908
909 void
910f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv)
911{
912 rettv->v_type = VAR_STRING;
913 rettv->vval.v_string = NULL;
914}
915
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100916 void
917f_test_unknown(typval_T *argvars UNUSED, typval_T *rettv)
918{
919 rettv->v_type = VAR_UNKNOWN;
920}
921
922 void
923f_test_void(typval_T *argvars UNUSED, typval_T *rettv)
924{
925 rettv->v_type = VAR_VOID;
926}
927
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200928#ifdef FEAT_GUI
929 void
930f_test_scrollbar(typval_T *argvars, typval_T *rettv UNUSED)
931{
932 char_u *which;
933 long value;
934 int dragging;
935 scrollbar_T *sb = NULL;
936
937 if (argvars[0].v_type != VAR_STRING
938 || (argvars[1].v_type) != VAR_NUMBER
939 || (argvars[2].v_type) != VAR_NUMBER)
940 {
941 emsg(_(e_invarg));
942 return;
943 }
944 which = tv_get_string(&argvars[0]);
945 value = tv_get_number(&argvars[1]);
946 dragging = tv_get_number(&argvars[2]);
947
948 if (STRCMP(which, "left") == 0)
949 sb = &curwin->w_scrollbars[SBAR_LEFT];
950 else if (STRCMP(which, "right") == 0)
951 sb = &curwin->w_scrollbars[SBAR_RIGHT];
952 else if (STRCMP(which, "hor") == 0)
953 sb = &gui.bottom_sbar;
954 if (sb == NULL)
955 {
956 semsg(_(e_invarg2), which);
957 return;
958 }
959 gui_drag_scrollbar(sb, value, dragging);
960# ifndef USE_ON_FLY_SCROLL
961 // need to loop through normal_cmd() to handle the scroll events
962 exec_normal(FALSE, TRUE, FALSE);
963# endif
964}
965#endif
966
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200967 void
968f_test_setmouse(typval_T *argvars, typval_T *rettv UNUSED)
969{
970 mouse_row = (time_t)tv_get_number(&argvars[0]) - 1;
971 mouse_col = (time_t)tv_get_number(&argvars[1]) - 1;
972}
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200973
974 void
975f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
976{
977 time_for_testing = (time_t)tv_get_number(&argvars[0]);
978}
979
980
981#endif // defined(FEAT_EVAL)