1 /* 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 22 prepare_assert_error(garray_T *gap) 23 { 24 char buf[NUMBUFLEN]; 25 char_u *sname = estack_sfile(); 26 27 ga_init2(gap, 1, 100); 28 if (sname != NULL) 29 { 30 ga_concat(gap, sname); 31 if (SOURCING_LNUM > 0) 32 ga_concat(gap, (char_u *)" "); 33 } 34 if (SOURCING_LNUM > 0) 35 { 36 sprintf(buf, "line %ld", (long)SOURCING_LNUM); 37 ga_concat(gap, (char_u *)buf); 38 } 39 if (sname != NULL || SOURCING_LNUM > 0) 40 ga_concat(gap, (char_u *)": "); 41 vim_free(sname); 42 } 43 44 /* 45 * Append "p[clen]" to "gap", escaping unprintable characters. 46 * Changes NL to \n, CR to \r, etc. 47 */ 48 static void 49 ga_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 85 ga_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 130 fill_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 175 assert_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 193 assert_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 220 assert_bool(typval_T *argvars, int isTrue) 221 { 222 int error = FALSE; 223 garray_T ga; 224 225 if (argvars[0].v_type == VAR_BOOL 226 && 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 244 assert_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 259 assert_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 288 f_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 297 f_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 303 assert_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 char line1[200]; 313 char line2[200]; 314 int lineidx = 0; 315 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 { 335 int c1, c2; 336 long count = 0; 337 long linecount = 1; 338 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 } 354 else 355 { 356 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 } 366 } 367 ++count; 368 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 } 379 } 380 fclose(fd1); 381 fclose(fd2); 382 } 383 } 384 if (IObuff[0] != NUL) 385 { 386 prepare_assert_error(&ga); 387 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 } 396 ga_concat(&ga, IObuff); 397 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 } 410 assert_error(&ga); 411 ga_clear(&ga); 412 return 1; 413 } 414 return 0; 415 } 416 417 /* 418 * "assert_equalfile(fname-one, fname-two[, msg])" function 419 */ 420 void 421 f_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 430 f_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 439 f_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 468 f_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; 473 int called_emsg_before = called_emsg; 474 475 // trylevel must be zero for a ":throw" command to be considered failed 476 trylevel = 0; 477 suppress_errthrow = TRUE; 478 emsg_silent = TRUE; 479 480 do_cmdline_cmd(cmd); 481 if (called_emsg == called_emsg_before) 482 { 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; 510 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 520 f_assert_false(typval_T *argvars, typval_T *rettv) 521 { 522 rettv->vval.v_number = assert_bool(argvars, FALSE); 523 } 524 525 static int 526 assert_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 597 f_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 606 f_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 615 f_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 624 f_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 639 f_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 648 f_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 671 f_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 682 f_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 687 # ifdef VIMDLL 688 // this doesn't work in the console 689 if (!gui.in_use) 690 return; 691 # endif 692 693 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 705 f_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 724 f_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 742 f_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 804 f_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: 811 case VAR_ANY: 812 case VAR_VOID: 813 case VAR_NUMBER: 814 case VAR_BOOL: 815 case VAR_FLOAT: 816 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 836 fp = find_func(argvars[0].vval.v_string, FALSE, NULL); 837 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 868 f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 869 { 870 // This is dangerous, any Lists and Dicts used internally may be freed 871 // while still in use. 872 garbage_collect(TRUE); 873 } 874 875 /* 876 * "test_garbagecollect_soon()" function 877 */ 878 void 879 f_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 888 f_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 894 f_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 902 f_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 910 f_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 917 f_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 925 f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv) 926 { 927 rettv_list_set(rettv, NULL); 928 } 929 930 void 931 f_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 938 f_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 945 f_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 951 void 952 f_test_unknown(typval_T *argvars UNUSED, typval_T *rettv) 953 { 954 rettv->v_type = VAR_UNKNOWN; 955 } 956 957 void 958 f_test_void(typval_T *argvars UNUSED, typval_T *rettv) 959 { 960 rettv->v_type = VAR_VOID; 961 } 962 963 #ifdef FEAT_GUI 964 void 965 f_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 1002 void 1003 f_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 } 1008 1009 void 1010 f_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) 1017