blob: 0eee72a832702a29834d7c218d35ad39783bf7e6 [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;
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200312 char line1[200];
313 char line2[200];
314 int lineidx = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200315
316 if (fname1 == NULL || fname2 == NULL)
317 return 0;
318
319 IObuff[0] = NUL;
320 fd1 = mch_fopen((char *)fname1, READBIN);
321 if (fd1 == NULL)
322 {
323 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1);
324 }
325 else
326 {
327 fd2 = mch_fopen((char *)fname2, READBIN);
328 if (fd2 == NULL)
329 {
330 fclose(fd1);
331 vim_snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2);
332 }
333 else
334 {
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200335 int c1, c2;
336 long count = 0;
337 long linecount = 1;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200338
339 for (;;)
340 {
341 c1 = fgetc(fd1);
342 c2 = fgetc(fd2);
343 if (c1 == EOF)
344 {
345 if (c2 != EOF)
346 STRCPY(IObuff, "first file is shorter");
347 break;
348 }
349 else if (c2 == EOF)
350 {
351 STRCPY(IObuff, "second file is shorter");
352 break;
353 }
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200354 else
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200355 {
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200356 line1[lineidx] = c1;
357 line2[lineidx] = c2;
358 ++lineidx;
359 if (c1 != c2)
360 {
361 vim_snprintf((char *)IObuff, IOSIZE,
362 "difference at byte %ld, line %ld",
363 count, linecount);
364 break;
365 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200366 }
367 ++count;
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200368 if (c1 == NL)
369 {
370 ++linecount;
371 lineidx = 0;
372 }
373 else if (lineidx + 2 == (int)sizeof(line1))
374 {
375 mch_memmove(line1, line1 + 100, lineidx - 100);
376 mch_memmove(line2, line2 + 100, lineidx - 100);
377 lineidx -= 100;
378 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200379 }
380 fclose(fd1);
381 fclose(fd2);
382 }
383 }
384 if (IObuff[0] != NUL)
385 {
386 prepare_assert_error(&ga);
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200387 if (argvars[2].v_type != VAR_UNKNOWN)
388 {
389 char_u numbuf[NUMBUFLEN];
390 char_u *tofree;
391
392 ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0));
393 vim_free(tofree);
394 ga_concat(&ga, (char_u *)": ");
395 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200396 ga_concat(&ga, IObuff);
Bram Moolenaar30cc44a2020-06-04 16:52:40 +0200397 if (lineidx > 0)
398 {
399 line1[lineidx] = NUL;
400 line2[lineidx] = NUL;
401 ga_concat(&ga, (char_u *)" after \"");
402 ga_concat(&ga, (char_u *)line1);
403 if (STRCMP(line1, line2) != 0)
404 {
405 ga_concat(&ga, (char_u *)"\" vs \"");
406 ga_concat(&ga, (char_u *)line2);
407 }
408 ga_concat(&ga, (char_u *)"\"");
409 }
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200410 assert_error(&ga);
411 ga_clear(&ga);
412 return 1;
413 }
414 return 0;
415}
416
417/*
Bram Moolenaarfb517ba2020-06-03 19:55:35 +0200418 * "assert_equalfile(fname-one, fname-two[, msg])" function
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200419 */
420 void
421f_assert_equalfile(typval_T *argvars, typval_T *rettv)
422{
423 rettv->vval.v_number = assert_equalfile(argvars);
424}
425
426/*
427 * "assert_notequal(expected, actual[, msg])" function
428 */
429 void
430f_assert_notequal(typval_T *argvars, typval_T *rettv)
431{
432 rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
433}
434
435/*
436 * "assert_exception(string[, msg])" function
437 */
438 void
439f_assert_exception(typval_T *argvars, typval_T *rettv)
440{
441 garray_T ga;
442 char_u *error = tv_get_string_chk(&argvars[0]);
443
444 if (*get_vim_var_str(VV_EXCEPTION) == NUL)
445 {
446 prepare_assert_error(&ga);
447 ga_concat(&ga, (char_u *)"v:exception is not set");
448 assert_error(&ga);
449 ga_clear(&ga);
450 rettv->vval.v_number = 1;
451 }
452 else if (error != NULL
453 && strstr((char *)get_vim_var_str(VV_EXCEPTION), (char *)error) == NULL)
454 {
455 prepare_assert_error(&ga);
456 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
457 get_vim_var_tv(VV_EXCEPTION), ASSERT_OTHER);
458 assert_error(&ga);
459 ga_clear(&ga);
460 rettv->vval.v_number = 1;
461 }
462}
463
464/*
465 * "assert_fails(cmd [, error[, msg]])" function
466 */
467 void
468f_assert_fails(typval_T *argvars, typval_T *rettv)
469{
470 char_u *cmd = tv_get_string_chk(&argvars[0]);
471 garray_T ga;
472 int save_trylevel = trylevel;
Bram Moolenaar53989552019-12-23 22:59:18 +0100473 int called_emsg_before = called_emsg;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200474
475 // trylevel must be zero for a ":throw" command to be considered failed
476 trylevel = 0;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200477 suppress_errthrow = TRUE;
478 emsg_silent = TRUE;
479
480 do_cmdline_cmd(cmd);
Bram Moolenaar53989552019-12-23 22:59:18 +0100481 if (called_emsg == called_emsg_before)
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200482 {
483 prepare_assert_error(&ga);
484 ga_concat(&ga, (char_u *)"command did not fail: ");
485 assert_append_cmd_or_arg(&ga, argvars, cmd);
486 assert_error(&ga);
487 ga_clear(&ga);
488 rettv->vval.v_number = 1;
489 }
490 else if (argvars[1].v_type != VAR_UNKNOWN)
491 {
492 char_u buf[NUMBUFLEN];
493 char *error = (char *)tv_get_string_buf_chk(&argvars[1], buf);
494
495 if (error == NULL
496 || strstr((char *)get_vim_var_str(VV_ERRMSG), error) == NULL)
497 {
498 prepare_assert_error(&ga);
499 fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
500 get_vim_var_tv(VV_ERRMSG), ASSERT_OTHER);
501 ga_concat(&ga, (char_u *)": ");
502 assert_append_cmd_or_arg(&ga, argvars, cmd);
503 assert_error(&ga);
504 ga_clear(&ga);
505 rettv->vval.v_number = 1;
506 }
507 }
508
509 trylevel = save_trylevel;
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200510 suppress_errthrow = FALSE;
511 emsg_silent = FALSE;
512 emsg_on_display = FALSE;
513 set_vim_var_string(VV_ERRMSG, NULL, 0);
514}
515
516/*
517 * "assert_false(actual[, msg])" function
518 */
519 void
520f_assert_false(typval_T *argvars, typval_T *rettv)
521{
522 rettv->vval.v_number = assert_bool(argvars, FALSE);
523}
524
525 static int
526assert_inrange(typval_T *argvars)
527{
528 garray_T ga;
529 int error = FALSE;
530 char_u *tofree;
531 char msg[200];
532 char_u numbuf[NUMBUFLEN];
533
534#ifdef FEAT_FLOAT
535 if (argvars[0].v_type == VAR_FLOAT
536 || argvars[1].v_type == VAR_FLOAT
537 || argvars[2].v_type == VAR_FLOAT)
538 {
539 float_T flower = tv_get_float(&argvars[0]);
540 float_T fupper = tv_get_float(&argvars[1]);
541 float_T factual = tv_get_float(&argvars[2]);
542
543 if (factual < flower || factual > fupper)
544 {
545 prepare_assert_error(&ga);
546 if (argvars[3].v_type != VAR_UNKNOWN)
547 {
548 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
549 vim_free(tofree);
550 }
551 else
552 {
553 vim_snprintf(msg, 200, "Expected range %g - %g, but got %g",
554 flower, fupper, factual);
555 ga_concat(&ga, (char_u *)msg);
556 }
557 assert_error(&ga);
558 ga_clear(&ga);
559 return 1;
560 }
561 }
562 else
563#endif
564 {
565 varnumber_T lower = tv_get_number_chk(&argvars[0], &error);
566 varnumber_T upper = tv_get_number_chk(&argvars[1], &error);
567 varnumber_T actual = tv_get_number_chk(&argvars[2], &error);
568
569 if (error)
570 return 0;
571 if (actual < lower || actual > upper)
572 {
573 prepare_assert_error(&ga);
574 if (argvars[3].v_type != VAR_UNKNOWN)
575 {
576 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
577 vim_free(tofree);
578 }
579 else
580 {
581 vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
582 (long)lower, (long)upper, (long)actual);
583 ga_concat(&ga, (char_u *)msg);
584 }
585 assert_error(&ga);
586 ga_clear(&ga);
587 return 1;
588 }
589 }
590 return 0;
591}
592
593/*
594 * "assert_inrange(lower, upper[, msg])" function
595 */
596 void
597f_assert_inrange(typval_T *argvars, typval_T *rettv)
598{
599 rettv->vval.v_number = assert_inrange(argvars);
600}
601
602/*
603 * "assert_match(pattern, actual[, msg])" function
604 */
605 void
606f_assert_match(typval_T *argvars, typval_T *rettv)
607{
608 rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH);
609}
610
611/*
612 * "assert_notmatch(pattern, actual[, msg])" function
613 */
614 void
615f_assert_notmatch(typval_T *argvars, typval_T *rettv)
616{
617 rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
618}
619
620/*
621 * "assert_report(msg)" function
622 */
623 void
624f_assert_report(typval_T *argvars, typval_T *rettv)
625{
626 garray_T ga;
627
628 prepare_assert_error(&ga);
629 ga_concat(&ga, tv_get_string(&argvars[0]));
630 assert_error(&ga);
631 ga_clear(&ga);
632 rettv->vval.v_number = 1;
633}
634
635/*
636 * "assert_true(actual[, msg])" function
637 */
638 void
639f_assert_true(typval_T *argvars, typval_T *rettv)
640{
641 rettv->vval.v_number = assert_bool(argvars, TRUE);
642}
643
644/*
645 * "test_alloc_fail(id, countdown, repeat)" function
646 */
647 void
648f_test_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED)
649{
650 if (argvars[0].v_type != VAR_NUMBER
651 || argvars[0].vval.v_number <= 0
652 || argvars[1].v_type != VAR_NUMBER
653 || argvars[1].vval.v_number < 0
654 || argvars[2].v_type != VAR_NUMBER)
655 emsg(_(e_invarg));
656 else
657 {
658 alloc_fail_id = argvars[0].vval.v_number;
659 if (alloc_fail_id >= aid_last)
660 emsg(_(e_invarg));
661 alloc_fail_countdown = argvars[1].vval.v_number;
662 alloc_fail_repeat = argvars[2].vval.v_number;
663 did_outofmem_msg = FALSE;
664 }
665}
666
667/*
668 * "test_autochdir()"
669 */
670 void
671f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
672{
673#if defined(FEAT_AUTOCHDIR)
674 test_autochdir = TRUE;
675#endif
676}
677
678/*
679 * "test_feedinput()"
680 */
681 void
682f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED)
683{
684#ifdef USE_INPUT_BUF
685 char_u *val = tv_get_string_chk(&argvars[0]);
686
Bram Moolenaar272ca952020-01-28 20:49:11 +0100687# ifdef VIMDLL
688 // this doesn't work in the console
689 if (!gui.in_use)
690 return;
691# endif
692
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200693 if (val != NULL)
694 {
695 trash_input_buf();
696 add_to_input_buf_csi(val, (int)STRLEN(val));
697 }
698#endif
699}
700
701/*
702 * "test_getvalue({name})" function
703 */
704 void
705f_test_getvalue(typval_T *argvars, typval_T *rettv)
706{
707 if (argvars[0].v_type != VAR_STRING)
708 emsg(_(e_invarg));
709 else
710 {
711 char_u *name = tv_get_string(&argvars[0]);
712
713 if (STRCMP(name, (char_u *)"need_fileinfo") == 0)
714 rettv->vval.v_number = need_fileinfo;
715 else
716 semsg(_(e_invarg2), name);
717 }
718}
719
720/*
721 * "test_option_not_set({name})" function
722 */
723 void
724f_test_option_not_set(typval_T *argvars, typval_T *rettv UNUSED)
725{
726 char_u *name = (char_u *)"";
727
728 if (argvars[0].v_type != VAR_STRING)
729 emsg(_(e_invarg));
730 else
731 {
732 name = tv_get_string(&argvars[0]);
733 if (reset_option_was_set(name) == FAIL)
734 semsg(_(e_invarg2), name);
735 }
736}
737
738/*
739 * "test_override({name}, {val})" function
740 */
741 void
742f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
743{
744 char_u *name = (char_u *)"";
745 int val;
746 static int save_starting = -1;
747
748 if (argvars[0].v_type != VAR_STRING
749 || (argvars[1].v_type) != VAR_NUMBER)
750 emsg(_(e_invarg));
751 else
752 {
753 name = tv_get_string(&argvars[0]);
754 val = (int)tv_get_number(&argvars[1]);
755
756 if (STRCMP(name, (char_u *)"redraw") == 0)
757 disable_redraw_for_testing = val;
758 else if (STRCMP(name, (char_u *)"redraw_flag") == 0)
759 ignore_redraw_flag_for_testing = val;
760 else if (STRCMP(name, (char_u *)"char_avail") == 0)
761 disable_char_avail_for_testing = val;
762 else if (STRCMP(name, (char_u *)"starting") == 0)
763 {
764 if (val)
765 {
766 if (save_starting < 0)
767 save_starting = starting;
768 starting = 0;
769 }
770 else
771 {
772 starting = save_starting;
773 save_starting = -1;
774 }
775 }
776 else if (STRCMP(name, (char_u *)"nfa_fail") == 0)
777 nfa_fail_for_testing = val;
778 else if (STRCMP(name, (char_u *)"no_query_mouse") == 0)
779 no_query_mouse_for_testing = val;
780 else if (STRCMP(name, (char_u *)"no_wait_return") == 0)
781 no_wait_return = val;
782 else if (STRCMP(name, (char_u *)"ALL") == 0)
783 {
784 disable_char_avail_for_testing = FALSE;
785 disable_redraw_for_testing = FALSE;
786 ignore_redraw_flag_for_testing = FALSE;
787 nfa_fail_for_testing = FALSE;
788 no_query_mouse_for_testing = FALSE;
789 if (save_starting >= 0)
790 {
791 starting = save_starting;
792 save_starting = -1;
793 }
794 }
795 else
796 semsg(_(e_invarg2), name);
797 }
798}
799
800/*
801 * "test_refcount({expr})" function
802 */
803 void
804f_test_refcount(typval_T *argvars, typval_T *rettv)
805{
806 int retval = -1;
807
808 switch (argvars[0].v_type)
809 {
810 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +0200811 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 case VAR_VOID:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200813 case VAR_NUMBER:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100814 case VAR_BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100815 case VAR_FLOAT:
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200816 case VAR_SPECIAL:
817 case VAR_STRING:
818 break;
819 case VAR_JOB:
820#ifdef FEAT_JOB_CHANNEL
821 if (argvars[0].vval.v_job != NULL)
822 retval = argvars[0].vval.v_job->jv_refcount - 1;
823#endif
824 break;
825 case VAR_CHANNEL:
826#ifdef FEAT_JOB_CHANNEL
827 if (argvars[0].vval.v_channel != NULL)
828 retval = argvars[0].vval.v_channel->ch_refcount - 1;
829#endif
830 break;
831 case VAR_FUNC:
832 if (argvars[0].vval.v_string != NULL)
833 {
834 ufunc_T *fp;
835
Bram Moolenaar4c17ad92020-04-27 22:47:51 +0200836 fp = find_func(argvars[0].vval.v_string, FALSE, NULL);
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200837 if (fp != NULL)
838 retval = fp->uf_refcount;
839 }
840 break;
841 case VAR_PARTIAL:
842 if (argvars[0].vval.v_partial != NULL)
843 retval = argvars[0].vval.v_partial->pt_refcount - 1;
844 break;
845 case VAR_BLOB:
846 if (argvars[0].vval.v_blob != NULL)
847 retval = argvars[0].vval.v_blob->bv_refcount - 1;
848 break;
849 case VAR_LIST:
850 if (argvars[0].vval.v_list != NULL)
851 retval = argvars[0].vval.v_list->lv_refcount - 1;
852 break;
853 case VAR_DICT:
854 if (argvars[0].vval.v_dict != NULL)
855 retval = argvars[0].vval.v_dict->dv_refcount - 1;
856 break;
857 }
858
859 rettv->v_type = VAR_NUMBER;
860 rettv->vval.v_number = retval;
861
862}
863
864/*
865 * "test_garbagecollect_now()" function
866 */
867 void
868f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
869{
Bram Moolenaar0d6f5d92019-12-05 21:33:15 +0100870 // This is dangerous, any Lists and Dicts used internally may be freed
871 // while still in use.
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200872 garbage_collect(TRUE);
873}
874
875/*
876 * "test_garbagecollect_soon()" function
877 */
878 void
879f_test_garbagecollect_soon(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
880{
881 may_garbage_collect = TRUE;
882}
883
884/*
885 * "test_ignore_error()" function
886 */
887 void
888f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED)
889{
890 ignore_error_for_testing(tv_get_string(&argvars[0]));
891}
892
893 void
894f_test_null_blob(typval_T *argvars UNUSED, typval_T *rettv)
895{
896 rettv->v_type = VAR_BLOB;
897 rettv->vval.v_blob = NULL;
898}
899
900#ifdef FEAT_JOB_CHANNEL
901 void
902f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv)
903{
904 rettv->v_type = VAR_CHANNEL;
905 rettv->vval.v_channel = NULL;
906}
907#endif
908
909 void
910f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv)
911{
912 rettv_dict_set(rettv, NULL);
913}
914
915#ifdef FEAT_JOB_CHANNEL
916 void
917f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv)
918{
919 rettv->v_type = VAR_JOB;
920 rettv->vval.v_job = NULL;
921}
922#endif
923
924 void
925f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv)
926{
927 rettv_list_set(rettv, NULL);
928}
929
930 void
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200931f_test_null_function(typval_T *argvars UNUSED, typval_T *rettv)
932{
933 rettv->v_type = VAR_FUNC;
934 rettv->vval.v_string = NULL;
935}
936
937 void
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200938f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv)
939{
940 rettv->v_type = VAR_PARTIAL;
941 rettv->vval.v_partial = NULL;
942}
943
944 void
945f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv)
946{
947 rettv->v_type = VAR_STRING;
948 rettv->vval.v_string = NULL;
949}
950
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100951 void
952f_test_unknown(typval_T *argvars UNUSED, typval_T *rettv)
953{
954 rettv->v_type = VAR_UNKNOWN;
955}
956
957 void
958f_test_void(typval_T *argvars UNUSED, typval_T *rettv)
959{
960 rettv->v_type = VAR_VOID;
961}
962
Bram Moolenaarecaa70e2019-07-14 14:55:39 +0200963#ifdef FEAT_GUI
964 void
965f_test_scrollbar(typval_T *argvars, typval_T *rettv UNUSED)
966{
967 char_u *which;
968 long value;
969 int dragging;
970 scrollbar_T *sb = NULL;
971
972 if (argvars[0].v_type != VAR_STRING
973 || (argvars[1].v_type) != VAR_NUMBER
974 || (argvars[2].v_type) != VAR_NUMBER)
975 {
976 emsg(_(e_invarg));
977 return;
978 }
979 which = tv_get_string(&argvars[0]);
980 value = tv_get_number(&argvars[1]);
981 dragging = tv_get_number(&argvars[2]);
982
983 if (STRCMP(which, "left") == 0)
984 sb = &curwin->w_scrollbars[SBAR_LEFT];
985 else if (STRCMP(which, "right") == 0)
986 sb = &curwin->w_scrollbars[SBAR_RIGHT];
987 else if (STRCMP(which, "hor") == 0)
988 sb = &gui.bottom_sbar;
989 if (sb == NULL)
990 {
991 semsg(_(e_invarg2), which);
992 return;
993 }
994 gui_drag_scrollbar(sb, value, dragging);
995# ifndef USE_ON_FLY_SCROLL
996 // need to loop through normal_cmd() to handle the scroll events
997 exec_normal(FALSE, TRUE, FALSE);
998# endif
999}
1000#endif
1001
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001002 void
1003f_test_setmouse(typval_T *argvars, typval_T *rettv UNUSED)
1004{
1005 mouse_row = (time_t)tv_get_number(&argvars[0]) - 1;
1006 mouse_col = (time_t)tv_get_number(&argvars[1]) - 1;
1007}
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02001008
1009 void
1010f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
1011{
1012 time_for_testing = (time_t)tv_get_number(&argvars[0]);
1013}
1014
1015
1016#endif // defined(FEAT_EVAL)