| /* vi:set ts=8 sts=4 sw=4 noet: |
| * |
| * VIM - Vi IMproved by Bram Moolenaar |
| * |
| * Do ":help uganda" in Vim to read copying and usage conditions. |
| * Do ":help credits" in Vim to see a list of people who contributed. |
| * See README.txt for an overview of the Vim source code. |
| */ |
| |
| /* |
| * testing.c: Support for tests. |
| */ |
| |
| #include "vim.h" |
| |
| #if defined(FEAT_EVAL) || defined(PROTO) |
| |
| /* |
| * Prepare "gap" for an assert error and add the sourcing position. |
| */ |
| static void |
| prepare_assert_error(garray_T *gap) |
| { |
| char buf[NUMBUFLEN]; |
| char_u *sname = estack_sfile(ESTACK_NONE); |
| |
| ga_init2(gap, 1, 100); |
| if (sname != NULL) |
| { |
| ga_concat(gap, sname); |
| if (SOURCING_LNUM > 0) |
| ga_concat(gap, (char_u *)" "); |
| } |
| if (SOURCING_LNUM > 0) |
| { |
| sprintf(buf, "line %ld", (long)SOURCING_LNUM); |
| ga_concat(gap, (char_u *)buf); |
| } |
| if (sname != NULL || SOURCING_LNUM > 0) |
| ga_concat(gap, (char_u *)": "); |
| vim_free(sname); |
| } |
| |
| /* |
| * Append "p[clen]" to "gap", escaping unprintable characters. |
| * Changes NL to \n, CR to \r, etc. |
| */ |
| static void |
| ga_concat_esc(garray_T *gap, char_u *p, int clen) |
| { |
| char_u buf[NUMBUFLEN]; |
| |
| if (clen > 1) |
| { |
| mch_memmove(buf, p, clen); |
| buf[clen] = NUL; |
| ga_concat(gap, buf); |
| return; |
| } |
| |
| switch (*p) |
| { |
| case BS: ga_concat(gap, (char_u *)"\\b"); break; |
| case ESC: ga_concat(gap, (char_u *)"\\e"); break; |
| case FF: ga_concat(gap, (char_u *)"\\f"); break; |
| case NL: ga_concat(gap, (char_u *)"\\n"); break; |
| case TAB: ga_concat(gap, (char_u *)"\\t"); break; |
| case CAR: ga_concat(gap, (char_u *)"\\r"); break; |
| case '\\': ga_concat(gap, (char_u *)"\\\\"); break; |
| default: |
| if (*p < ' ' || *p == 0x7f) |
| { |
| vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p); |
| ga_concat(gap, buf); |
| } |
| else |
| ga_append(gap, *p); |
| break; |
| } |
| } |
| |
| /* |
| * Append "str" to "gap", escaping unprintable characters. |
| * Changes NL to \n, CR to \r, etc. |
| */ |
| static void |
| ga_concat_shorten_esc(garray_T *gap, char_u *str) |
| { |
| char_u *p; |
| char_u *s; |
| int c; |
| int clen; |
| char_u buf[NUMBUFLEN]; |
| int same_len; |
| |
| if (str == NULL) |
| { |
| ga_concat(gap, (char_u *)"NULL"); |
| return; |
| } |
| |
| for (p = str; *p != NUL; ++p) |
| { |
| same_len = 1; |
| s = p; |
| c = mb_cptr2char_adv(&s); |
| clen = s - p; |
| while (*s != NUL && c == mb_ptr2char(s)) |
| { |
| ++same_len; |
| s += clen; |
| } |
| if (same_len > 20) |
| { |
| ga_concat(gap, (char_u *)"\\["); |
| ga_concat_esc(gap, p, clen); |
| ga_concat(gap, (char_u *)" occurs "); |
| vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len); |
| ga_concat(gap, buf); |
| ga_concat(gap, (char_u *)" times]"); |
| p = s - 1; |
| } |
| else |
| ga_concat_esc(gap, p, clen); |
| } |
| } |
| |
| /* |
| * Fill "gap" with information about an assert error. |
| */ |
| static void |
| fill_assert_error( |
| garray_T *gap, |
| typval_T *opt_msg_tv, |
| char_u *exp_str, |
| typval_T *exp_tv_arg, |
| typval_T *got_tv_arg, |
| assert_type_T atype) |
| { |
| char_u numbuf[NUMBUFLEN]; |
| char_u *tofree; |
| typval_T *exp_tv = exp_tv_arg; |
| typval_T *got_tv = got_tv_arg; |
| int did_copy = FALSE; |
| int omitted = 0; |
| |
| if (opt_msg_tv->v_type != VAR_UNKNOWN |
| && !(opt_msg_tv->v_type == VAR_STRING |
| && (opt_msg_tv->vval.v_string == NULL |
| || *opt_msg_tv->vval.v_string == NUL))) |
| { |
| ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0)); |
| vim_free(tofree); |
| ga_concat(gap, (char_u *)": "); |
| } |
| |
| if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) |
| ga_concat(gap, (char_u *)"Pattern "); |
| else if (atype == ASSERT_NOTEQUAL) |
| ga_concat(gap, (char_u *)"Expected not equal to "); |
| else |
| ga_concat(gap, (char_u *)"Expected "); |
| if (exp_str == NULL) |
| { |
| // When comparing dictionaries, drop the items that are equal, so that |
| // it's a lot easier to see what differs. |
| if (atype != ASSERT_NOTEQUAL |
| && exp_tv->v_type == VAR_DICT && got_tv->v_type == VAR_DICT |
| && exp_tv->vval.v_dict != NULL && got_tv->vval.v_dict != NULL) |
| { |
| dict_T *exp_d = exp_tv->vval.v_dict; |
| dict_T *got_d = got_tv->vval.v_dict; |
| hashitem_T *hi; |
| dictitem_T *item2; |
| int todo; |
| |
| did_copy = TRUE; |
| exp_tv->vval.v_dict = dict_alloc(); |
| got_tv->vval.v_dict = dict_alloc(); |
| if (exp_tv->vval.v_dict == NULL || got_tv->vval.v_dict == NULL) |
| return; |
| |
| todo = (int)exp_d->dv_hashtab.ht_used; |
| FOR_ALL_HASHTAB_ITEMS(&exp_d->dv_hashtab, hi, todo) |
| { |
| if (!HASHITEM_EMPTY(hi)) |
| { |
| item2 = dict_find(got_d, hi->hi_key, -1); |
| if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv, |
| &item2->di_tv, FALSE)) |
| { |
| // item of exp_d not present in got_d or values differ. |
| dict_add_tv(exp_tv->vval.v_dict, |
| (char *)hi->hi_key, &HI2DI(hi)->di_tv); |
| if (item2 != NULL) |
| dict_add_tv(got_tv->vval.v_dict, |
| (char *)hi->hi_key, &item2->di_tv); |
| } |
| else |
| ++omitted; |
| --todo; |
| } |
| } |
| |
| // Add items only present in got_d. |
| todo = (int)got_d->dv_hashtab.ht_used; |
| FOR_ALL_HASHTAB_ITEMS(&got_d->dv_hashtab, hi, todo) |
| { |
| if (!HASHITEM_EMPTY(hi)) |
| { |
| item2 = dict_find(exp_d, hi->hi_key, -1); |
| if (item2 == NULL) |
| // item of got_d not present in exp_d |
| dict_add_tv(got_tv->vval.v_dict, |
| (char *)hi->hi_key, &HI2DI(hi)->di_tv); |
| --todo; |
| } |
| } |
| } |
| |
| ga_concat_shorten_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); |
| vim_free(tofree); |
| } |
| else |
| { |
| if (atype == ASSERT_FAILS) |
| ga_concat(gap, (char_u *)"'"); |
| ga_concat_shorten_esc(gap, exp_str); |
| if (atype == ASSERT_FAILS) |
| ga_concat(gap, (char_u *)"'"); |
| } |
| if (atype != ASSERT_NOTEQUAL) |
| { |
| if (atype == ASSERT_MATCH) |
| ga_concat(gap, (char_u *)" does not match "); |
| else if (atype == ASSERT_NOTMATCH) |
| ga_concat(gap, (char_u *)" does match "); |
| else |
| ga_concat(gap, (char_u *)" but got "); |
| ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); |
| vim_free(tofree); |
| |
| if (omitted != 0) |
| { |
| char buf[100]; |
| |
| vim_snprintf(buf, 100, " - %d equal item%s omitted", |
| omitted, omitted == 1 ? "" : "s"); |
| ga_concat(gap, (char_u *)buf); |
| } |
| } |
| |
| if (did_copy) |
| { |
| clear_tv(exp_tv); |
| clear_tv(got_tv); |
| } |
| } |
| |
| static int |
| assert_equal_common(typval_T *argvars, assert_type_T atype) |
| { |
| garray_T ga; |
| |
| if (tv_equal(&argvars[0], &argvars[1], FALSE) |
| != (atype == ASSERT_EQUAL)) |
| { |
| prepare_assert_error(&ga); |
| fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], |
| atype); |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int |
| assert_match_common(typval_T *argvars, assert_type_T atype) |
| { |
| garray_T ga; |
| char_u buf1[NUMBUFLEN]; |
| char_u buf2[NUMBUFLEN]; |
| |
| if (in_vim9script() |
| && (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_string_arg(argvars, 1) == FAIL |
| || check_for_opt_string_arg(argvars, 2) == FAIL)) |
| return 1; |
| |
| char_u *pat = tv_get_string_buf_chk(&argvars[0], buf1); |
| char_u *text = tv_get_string_buf_chk(&argvars[1], buf2); |
| if (pat != NULL && text != NULL |
| && pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH)) |
| { |
| prepare_assert_error(&ga); |
| fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], |
| atype); |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| return 0; |
| } |
| |
| /* |
| * Common for assert_true() and assert_false(). |
| * Return non-zero for failure. |
| */ |
| static int |
| assert_bool(typval_T *argvars, int isTrue) |
| { |
| int error = FALSE; |
| garray_T ga; |
| |
| if (argvars[0].v_type == VAR_BOOL |
| && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE)) |
| return 0; |
| if (argvars[0].v_type != VAR_NUMBER |
| || (tv_get_number_chk(&argvars[0], &error) == 0) == isTrue |
| || error) |
| { |
| prepare_assert_error(&ga); |
| fill_assert_error(&ga, &argvars[1], |
| (char_u *)(isTrue ? "True" : "False"), |
| NULL, &argvars[0], ASSERT_OTHER); |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static void |
| assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, char_u *cmd) |
| { |
| char_u *tofree; |
| char_u numbuf[NUMBUFLEN]; |
| |
| if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) |
| { |
| ga_concat(gap, echo_string(&argvars[2], &tofree, numbuf, 0)); |
| vim_free(tofree); |
| } |
| else |
| ga_concat(gap, cmd); |
| } |
| |
| static int |
| assert_beeps(typval_T *argvars, int no_beep) |
| { |
| char_u *cmd; |
| garray_T ga; |
| int ret = 0; |
| |
| if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) |
| return 0; |
| |
| cmd = tv_get_string_chk(&argvars[0]); |
| called_vim_beep = FALSE; |
| suppress_errthrow = TRUE; |
| emsg_silent = FALSE; |
| do_cmdline_cmd(cmd); |
| if (no_beep ? called_vim_beep : !called_vim_beep) |
| { |
| prepare_assert_error(&ga); |
| if (no_beep) |
| ga_concat(&ga, (char_u *)"command did beep: "); |
| else |
| ga_concat(&ga, (char_u *)"command did not beep: "); |
| ga_concat(&ga, cmd); |
| assert_error(&ga); |
| ga_clear(&ga); |
| ret = 1; |
| } |
| |
| suppress_errthrow = FALSE; |
| emsg_on_display = FALSE; |
| return ret; |
| } |
| |
| /* |
| * "assert_beeps(cmd)" function |
| */ |
| void |
| f_assert_beeps(typval_T *argvars, typval_T *rettv) |
| { |
| if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| rettv->vval.v_number = assert_beeps(argvars, FALSE); |
| } |
| |
| /* |
| * "assert_nobeep(cmd)" function |
| */ |
| void |
| f_assert_nobeep(typval_T *argvars, typval_T *rettv) |
| { |
| if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| rettv->vval.v_number = assert_beeps(argvars, TRUE); |
| } |
| |
| /* |
| * "assert_equal(expected, actual[, msg])" function |
| */ |
| void |
| f_assert_equal(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL); |
| } |
| |
| static int |
| assert_equalfile(typval_T *argvars) |
| { |
| char_u buf1[NUMBUFLEN]; |
| char_u buf2[NUMBUFLEN]; |
| char_u *fname1 = tv_get_string_buf_chk(&argvars[0], buf1); |
| char_u *fname2 = tv_get_string_buf_chk(&argvars[1], buf2); |
| FILE *fd1; |
| FILE *fd2; |
| char line1[200]; |
| char line2[200]; |
| int lineidx = 0; |
| |
| if (fname1 == NULL || fname2 == NULL) |
| return 0; |
| |
| IObuff[0] = NUL; |
| fd1 = mch_fopen((char *)fname1, READBIN); |
| if (fd1 == NULL) |
| { |
| vim_snprintf((char *)IObuff, IOSIZE, (char *)e_cant_read_file_str, |
| fname1); |
| } |
| else |
| { |
| fd2 = mch_fopen((char *)fname2, READBIN); |
| if (fd2 == NULL) |
| { |
| fclose(fd1); |
| vim_snprintf((char *)IObuff, IOSIZE, (char *)e_cant_read_file_str, |
| fname2); |
| } |
| else |
| { |
| int c1, c2; |
| long count = 0; |
| long linecount = 1; |
| |
| for (;;) |
| { |
| c1 = fgetc(fd1); |
| c2 = fgetc(fd2); |
| if (c1 == EOF) |
| { |
| if (c2 != EOF) |
| STRCPY(IObuff, "first file is shorter"); |
| break; |
| } |
| else if (c2 == EOF) |
| { |
| STRCPY(IObuff, "second file is shorter"); |
| break; |
| } |
| else |
| { |
| line1[lineidx] = c1; |
| line2[lineidx] = c2; |
| ++lineidx; |
| if (c1 != c2) |
| { |
| vim_snprintf((char *)IObuff, IOSIZE, |
| "difference at byte %ld, line %ld", |
| count, linecount); |
| break; |
| } |
| } |
| ++count; |
| if (c1 == NL) |
| { |
| ++linecount; |
| lineidx = 0; |
| } |
| else if (lineidx + 2 == (int)sizeof(line1)) |
| { |
| mch_memmove(line1, line1 + 100, lineidx - 100); |
| mch_memmove(line2, line2 + 100, lineidx - 100); |
| lineidx -= 100; |
| } |
| } |
| fclose(fd1); |
| fclose(fd2); |
| } |
| } |
| |
| if (IObuff[0] != NUL) |
| { |
| garray_T ga; |
| prepare_assert_error(&ga); |
| if (argvars[2].v_type != VAR_UNKNOWN) |
| { |
| char_u numbuf[NUMBUFLEN]; |
| char_u *tofree; |
| |
| ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0)); |
| vim_free(tofree); |
| ga_concat(&ga, (char_u *)": "); |
| } |
| ga_concat(&ga, IObuff); |
| if (lineidx > 0) |
| { |
| line1[lineidx] = NUL; |
| line2[lineidx] = NUL; |
| ga_concat(&ga, (char_u *)" after \""); |
| ga_concat(&ga, (char_u *)line1); |
| if (STRCMP(line1, line2) != 0) |
| { |
| ga_concat(&ga, (char_u *)"\" vs \""); |
| ga_concat(&ga, (char_u *)line2); |
| } |
| ga_concat(&ga, (char_u *)"\""); |
| } |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| * "assert_equalfile(fname-one, fname-two[, msg])" function |
| */ |
| void |
| f_assert_equalfile(typval_T *argvars, typval_T *rettv) |
| { |
| if (in_vim9script() |
| && (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_string_arg(argvars, 1) == FAIL |
| || check_for_opt_string_arg(argvars, 2) == FAIL)) |
| return; |
| |
| rettv->vval.v_number = assert_equalfile(argvars); |
| } |
| |
| /* |
| * "assert_notequal(expected, actual[, msg])" function |
| */ |
| void |
| f_assert_notequal(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL); |
| } |
| |
| /* |
| * "assert_exception(string[, msg])" function |
| */ |
| void |
| f_assert_exception(typval_T *argvars, typval_T *rettv) |
| { |
| garray_T ga; |
| char_u *error; |
| |
| if (in_vim9script() |
| && (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_opt_string_arg(argvars, 1) == FAIL)) |
| return; |
| |
| error = tv_get_string_chk(&argvars[0]); |
| if (*get_vim_var_str(VV_EXCEPTION) == NUL) |
| { |
| prepare_assert_error(&ga); |
| ga_concat(&ga, (char_u *)"v:exception is not set"); |
| assert_error(&ga); |
| ga_clear(&ga); |
| rettv->vval.v_number = 1; |
| } |
| else if (error != NULL |
| && strstr((char *)get_vim_var_str(VV_EXCEPTION), (char *)error) == NULL) |
| { |
| prepare_assert_error(&ga); |
| fill_assert_error(&ga, &argvars[1], NULL, &argvars[0], |
| get_vim_var_tv(VV_EXCEPTION), ASSERT_OTHER); |
| assert_error(&ga); |
| ga_clear(&ga); |
| rettv->vval.v_number = 1; |
| } |
| } |
| |
| /* |
| * "assert_fails(cmd [, error[, msg]])" function |
| */ |
| void |
| f_assert_fails(typval_T *argvars, typval_T *rettv) |
| { |
| garray_T ga; |
| int save_trylevel = trylevel; |
| int called_emsg_before = called_emsg; |
| char *wrong_arg_msg = NULL; |
| char_u *tofree = NULL; |
| |
| if (check_for_string_or_number_arg(argvars, 0) == FAIL |
| || check_for_opt_string_or_list_arg(argvars, 1) == FAIL |
| || (argvars[1].v_type != VAR_UNKNOWN |
| && (argvars[2].v_type != VAR_UNKNOWN |
| && (check_for_opt_number_arg(argvars, 3) == FAIL |
| || (argvars[3].v_type != VAR_UNKNOWN |
| && check_for_opt_string_arg(argvars, 4) == FAIL))))) |
| return; |
| |
| // trylevel must be zero for a ":throw" command to be considered failed |
| trylevel = 0; |
| suppress_errthrow = TRUE; |
| in_assert_fails = TRUE; |
| ++no_wait_return; |
| |
| char_u *cmd = tv_get_string_chk(&argvars[0]); |
| do_cmdline_cmd(cmd); |
| |
| // reset here for any errors reported below |
| trylevel = save_trylevel; |
| suppress_errthrow = FALSE; |
| |
| if (called_emsg == called_emsg_before) |
| { |
| prepare_assert_error(&ga); |
| ga_concat(&ga, (char_u *)"command did not fail: "); |
| assert_append_cmd_or_arg(&ga, argvars, cmd); |
| assert_error(&ga); |
| ga_clear(&ga); |
| rettv->vval.v_number = 1; |
| } |
| else if (argvars[1].v_type != VAR_UNKNOWN) |
| { |
| char_u buf[NUMBUFLEN]; |
| char_u *expected; |
| char_u *expected_str = NULL; |
| int error_found = FALSE; |
| int error_found_index = 1; |
| char_u *actual = emsg_assert_fails_msg == NULL ? (char_u *)"[unknown]" |
| : emsg_assert_fails_msg; |
| |
| if (argvars[1].v_type == VAR_STRING) |
| { |
| expected = tv_get_string_buf_chk(&argvars[1], buf); |
| error_found = expected == NULL |
| || strstr((char *)actual, (char *)expected) == NULL; |
| } |
| else if (argvars[1].v_type == VAR_LIST) |
| { |
| list_T *list = argvars[1].vval.v_list; |
| typval_T *tv; |
| |
| if (list == NULL || list->lv_len < 1 || list->lv_len > 2) |
| { |
| wrong_arg_msg = e_assert_fails_second_arg; |
| goto theend; |
| } |
| CHECK_LIST_MATERIALIZE(list); |
| tv = &list->lv_first->li_tv; |
| expected = tv_get_string_buf_chk(tv, buf); |
| if (expected == NULL) |
| goto theend; |
| if (!pattern_match(expected, actual, FALSE)) |
| { |
| error_found = TRUE; |
| expected_str = expected; |
| } |
| else if (list->lv_len == 2) |
| { |
| // make a copy, an error in pattern_match() may free it |
| tofree = actual = vim_strsave(get_vim_var_str(VV_ERRMSG)); |
| if (actual != NULL) |
| { |
| tv = &list->lv_u.mat.lv_last->li_tv; |
| expected = tv_get_string_buf_chk(tv, buf); |
| if (expected == NULL) |
| goto theend; |
| if (!pattern_match(expected, actual, FALSE)) |
| { |
| error_found = TRUE; |
| expected_str = expected; |
| } |
| } |
| } |
| } |
| else |
| { |
| wrong_arg_msg = e_assert_fails_second_arg; |
| goto theend; |
| } |
| |
| if (!error_found && argvars[2].v_type != VAR_UNKNOWN |
| && argvars[3].v_type != VAR_UNKNOWN) |
| { |
| if (argvars[3].v_type != VAR_NUMBER) |
| { |
| wrong_arg_msg = e_assert_fails_fourth_argument; |
| goto theend; |
| } |
| else if (argvars[3].vval.v_number >= 0 |
| && argvars[3].vval.v_number != emsg_assert_fails_lnum) |
| { |
| error_found = TRUE; |
| error_found_index = 3; |
| } |
| if (!error_found && argvars[4].v_type != VAR_UNKNOWN) |
| { |
| if (argvars[4].v_type != VAR_STRING) |
| { |
| wrong_arg_msg = e_assert_fails_fifth_argument; |
| goto theend; |
| } |
| else if (argvars[4].vval.v_string != NULL |
| && !pattern_match(argvars[4].vval.v_string, |
| emsg_assert_fails_context, FALSE)) |
| { |
| error_found = TRUE; |
| error_found_index = 4; |
| } |
| } |
| } |
| |
| if (error_found) |
| { |
| typval_T actual_tv; |
| |
| prepare_assert_error(&ga); |
| if (error_found_index == 3) |
| { |
| actual_tv.v_type = VAR_NUMBER; |
| actual_tv.vval.v_number = emsg_assert_fails_lnum; |
| } |
| else if (error_found_index == 4) |
| { |
| actual_tv.v_type = VAR_STRING; |
| actual_tv.vval.v_string = emsg_assert_fails_context; |
| } |
| else |
| { |
| actual_tv.v_type = VAR_STRING; |
| actual_tv.vval.v_string = actual; |
| } |
| fill_assert_error(&ga, &argvars[2], expected_str, |
| &argvars[error_found_index], &actual_tv, ASSERT_FAILS); |
| ga_concat(&ga, (char_u *)": "); |
| assert_append_cmd_or_arg(&ga, argvars, cmd); |
| assert_error(&ga); |
| ga_clear(&ga); |
| rettv->vval.v_number = 1; |
| } |
| } |
| |
| theend: |
| trylevel = save_trylevel; |
| suppress_errthrow = FALSE; |
| in_assert_fails = FALSE; |
| did_emsg = FALSE; |
| got_int = FALSE; |
| msg_col = 0; |
| --no_wait_return; |
| need_wait_return = FALSE; |
| emsg_on_display = FALSE; |
| msg_scrolled = 0; |
| lines_left = Rows; |
| VIM_CLEAR(emsg_assert_fails_msg); |
| vim_free(tofree); |
| set_vim_var_string(VV_ERRMSG, NULL, 0); |
| if (wrong_arg_msg != NULL) |
| emsg(_(wrong_arg_msg)); |
| } |
| |
| /* |
| * "assert_false(actual[, msg])" function |
| */ |
| void |
| f_assert_false(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_bool(argvars, FALSE); |
| } |
| |
| static int |
| assert_inrange(typval_T *argvars) |
| { |
| garray_T ga; |
| int error = FALSE; |
| char_u expected_str[200]; |
| |
| if (argvars[0].v_type == VAR_FLOAT |
| || argvars[1].v_type == VAR_FLOAT |
| || argvars[2].v_type == VAR_FLOAT) |
| { |
| float_T flower = tv_get_float(&argvars[0]); |
| float_T fupper = tv_get_float(&argvars[1]); |
| float_T factual = tv_get_float(&argvars[2]); |
| |
| if (factual < flower || factual > fupper) |
| { |
| prepare_assert_error(&ga); |
| vim_snprintf((char *)expected_str, 200, "range %g - %g,", |
| flower, fupper); |
| fill_assert_error(&ga, &argvars[3], expected_str, NULL, |
| &argvars[2], ASSERT_OTHER); |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| } |
| else |
| { |
| varnumber_T lower = tv_get_number_chk(&argvars[0], &error); |
| varnumber_T upper = tv_get_number_chk(&argvars[1], &error); |
| varnumber_T actual = tv_get_number_chk(&argvars[2], &error); |
| |
| if (error) |
| return 0; |
| if (actual < lower || actual > upper) |
| { |
| prepare_assert_error(&ga); |
| vim_snprintf((char *)expected_str, 200, "range %ld - %ld,", |
| (long)lower, (long)upper); |
| fill_assert_error(&ga, &argvars[3], expected_str, NULL, |
| &argvars[2], ASSERT_OTHER); |
| assert_error(&ga); |
| ga_clear(&ga); |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| /* |
| * "assert_inrange(lower, upper[, msg])" function |
| */ |
| void |
| f_assert_inrange(typval_T *argvars, typval_T *rettv) |
| { |
| if (check_for_float_or_nr_arg(argvars, 0) == FAIL |
| || check_for_float_or_nr_arg(argvars, 1) == FAIL |
| || check_for_float_or_nr_arg(argvars, 2) == FAIL |
| || check_for_opt_string_arg(argvars, 3) == FAIL) |
| return; |
| |
| rettv->vval.v_number = assert_inrange(argvars); |
| } |
| |
| /* |
| * "assert_match(pattern, actual[, msg])" function |
| */ |
| void |
| f_assert_match(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH); |
| } |
| |
| /* |
| * "assert_notmatch(pattern, actual[, msg])" function |
| */ |
| void |
| f_assert_notmatch(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH); |
| } |
| |
| /* |
| * "assert_report(msg)" function |
| */ |
| void |
| f_assert_report(typval_T *argvars, typval_T *rettv) |
| { |
| garray_T ga; |
| |
| if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| prepare_assert_error(&ga); |
| ga_concat(&ga, tv_get_string(&argvars[0])); |
| assert_error(&ga); |
| ga_clear(&ga); |
| rettv->vval.v_number = 1; |
| } |
| |
| /* |
| * "assert_true(actual[, msg])" function |
| */ |
| void |
| f_assert_true(typval_T *argvars, typval_T *rettv) |
| { |
| rettv->vval.v_number = assert_bool(argvars, TRUE); |
| } |
| |
| /* |
| * "test_alloc_fail(id, countdown, repeat)" function |
| */ |
| void |
| f_test_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| if (in_vim9script() |
| && (check_for_number_arg(argvars, 0) == FAIL |
| || check_for_number_arg(argvars, 1) == FAIL |
| || check_for_number_arg(argvars, 2) == FAIL)) |
| return; |
| |
| if (argvars[0].v_type != VAR_NUMBER |
| || argvars[0].vval.v_number <= 0 |
| || argvars[1].v_type != VAR_NUMBER |
| || argvars[1].vval.v_number < 0 |
| || argvars[2].v_type != VAR_NUMBER) |
| emsg(_(e_invalid_argument)); |
| else |
| { |
| alloc_fail_id = argvars[0].vval.v_number; |
| if (alloc_fail_id >= aid_last) |
| emsg(_(e_invalid_argument)); |
| alloc_fail_countdown = argvars[1].vval.v_number; |
| alloc_fail_repeat = argvars[2].vval.v_number; |
| did_outofmem_msg = FALSE; |
| } |
| } |
| |
| /* |
| * "test_autochdir()" |
| */ |
| void |
| f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED) |
| { |
| #if defined(FEAT_AUTOCHDIR) |
| test_autochdir = TRUE; |
| #endif |
| } |
| |
| /* |
| * "test_feedinput()" |
| */ |
| void |
| f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| #ifdef USE_INPUT_BUF |
| char_u *val; |
| |
| if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| val = tv_get_string_chk(&argvars[0]); |
| # ifdef VIMDLL |
| // this doesn't work in the console |
| if (!gui.in_use) |
| return; |
| # endif |
| |
| if (val != NULL) |
| { |
| trash_input_buf(); |
| add_to_input_buf_csi(val, (int)STRLEN(val)); |
| } |
| #endif |
| } |
| |
| /* |
| * "test_getvalue({name})" function |
| */ |
| void |
| f_test_getvalue(typval_T *argvars, typval_T *rettv) |
| { |
| char_u *name; |
| |
| if (check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| name = tv_get_string(&argvars[0]); |
| |
| if (STRCMP(name, (char_u *)"need_fileinfo") == 0) |
| rettv->vval.v_number = need_fileinfo; |
| else |
| semsg(_(e_invalid_argument_str), name); |
| } |
| |
| /* |
| * "test_option_not_set({name})" function |
| */ |
| void |
| f_test_option_not_set(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| char_u *name = (char_u *)""; |
| |
| if (check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| name = tv_get_string(&argvars[0]); |
| if (reset_option_was_set(name) == FAIL) |
| semsg(_(e_invalid_argument_str), name); |
| } |
| |
| /* |
| * "test_override({name}, {val})" function |
| */ |
| void |
| f_test_override(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| char_u *name = (char_u *)""; |
| int val; |
| static int save_starting = -1; |
| |
| if (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_number_arg(argvars, 1) == FAIL) |
| return; |
| |
| name = tv_get_string(&argvars[0]); |
| val = (int)tv_get_number(&argvars[1]); |
| |
| if (STRCMP(name, (char_u *)"redraw") == 0) |
| disable_redraw_for_testing = val; |
| else if (STRCMP(name, (char_u *)"redraw_flag") == 0) |
| ignore_redraw_flag_for_testing = val; |
| else if (STRCMP(name, (char_u *)"char_avail") == 0) |
| disable_char_avail_for_testing = val; |
| else if (STRCMP(name, (char_u *)"starting") == 0) |
| { |
| if (val) |
| { |
| if (save_starting < 0) |
| save_starting = starting; |
| starting = 0; |
| } |
| else |
| { |
| starting = save_starting; |
| save_starting = -1; |
| } |
| } |
| else if (STRCMP(name, (char_u *)"nfa_fail") == 0) |
| nfa_fail_for_testing = val; |
| else if (STRCMP(name, (char_u *)"no_query_mouse") == 0) |
| no_query_mouse_for_testing = val; |
| else if (STRCMP(name, (char_u *)"no_wait_return") == 0) |
| no_wait_return = val; |
| else if (STRCMP(name, (char_u *)"ui_delay") == 0) |
| ui_delay_for_testing = val; |
| else if (STRCMP(name, (char_u *)"unreachable") == 0) |
| ignore_unreachable_code_for_testing = val; |
| else if (STRCMP(name, (char_u *)"term_props") == 0) |
| reset_term_props_on_termresponse = val; |
| else if (STRCMP(name, (char_u *)"vterm_title") == 0) |
| disable_vterm_title_for_testing = val; |
| else if (STRCMP(name, (char_u *)"uptime") == 0) |
| override_sysinfo_uptime = val; |
| else if (STRCMP(name, (char_u *)"alloc_lines") == 0) |
| ml_get_alloc_lines = val; |
| else if (STRCMP(name, (char_u *)"autoload") == 0) |
| override_autoload = val; |
| else if (STRCMP(name, (char_u *)"defcompile") == 0) |
| override_defcompile = val; |
| else if (STRCMP(name, (char_u *)"ALL") == 0) |
| { |
| disable_char_avail_for_testing = FALSE; |
| disable_redraw_for_testing = FALSE; |
| ignore_redraw_flag_for_testing = FALSE; |
| nfa_fail_for_testing = FALSE; |
| no_query_mouse_for_testing = FALSE; |
| ui_delay_for_testing = 0; |
| reset_term_props_on_termresponse = FALSE; |
| override_sysinfo_uptime = -1; |
| // ml_get_alloc_lines is not reset by "ALL" |
| if (save_starting >= 0) |
| { |
| starting = save_starting; |
| save_starting = -1; |
| } |
| } |
| else |
| semsg(_(e_invalid_argument_str), name); |
| } |
| |
| /* |
| * "test_refcount({expr})" function |
| */ |
| void |
| f_test_refcount(typval_T *argvars, typval_T *rettv) |
| { |
| int retval = -1; |
| |
| switch (argvars[0].v_type) |
| { |
| case VAR_UNKNOWN: |
| case VAR_ANY: |
| case VAR_VOID: |
| case VAR_NUMBER: |
| case VAR_BOOL: |
| case VAR_FLOAT: |
| case VAR_SPECIAL: |
| case VAR_STRING: |
| case VAR_INSTR: |
| break; |
| |
| case VAR_JOB: |
| #ifdef FEAT_JOB_CHANNEL |
| if (argvars[0].vval.v_job != NULL) |
| retval = argvars[0].vval.v_job->jv_refcount - 1; |
| #endif |
| break; |
| case VAR_CHANNEL: |
| #ifdef FEAT_JOB_CHANNEL |
| if (argvars[0].vval.v_channel != NULL) |
| retval = argvars[0].vval.v_channel->ch_refcount - 1; |
| #endif |
| break; |
| case VAR_FUNC: |
| if (argvars[0].vval.v_string != NULL) |
| { |
| ufunc_T *fp; |
| |
| fp = find_func(argvars[0].vval.v_string, FALSE); |
| if (fp != NULL) |
| retval = fp->uf_refcount; |
| } |
| break; |
| case VAR_PARTIAL: |
| if (argvars[0].vval.v_partial != NULL) |
| retval = argvars[0].vval.v_partial->pt_refcount - 1; |
| break; |
| case VAR_BLOB: |
| if (argvars[0].vval.v_blob != NULL) |
| retval = argvars[0].vval.v_blob->bv_refcount - 1; |
| break; |
| case VAR_LIST: |
| if (argvars[0].vval.v_list != NULL) |
| retval = argvars[0].vval.v_list->lv_refcount - 1; |
| break; |
| case VAR_DICT: |
| if (argvars[0].vval.v_dict != NULL) |
| retval = argvars[0].vval.v_dict->dv_refcount - 1; |
| break; |
| case VAR_CLASS: |
| if (argvars[0].vval.v_class != NULL) |
| retval = argvars[0].vval.v_class->class_refcount - 1; |
| break; |
| case VAR_OBJECT: |
| if (argvars[0].vval.v_object != NULL) |
| retval = argvars[0].vval.v_object->obj_refcount - 1; |
| break; |
| case VAR_TYPEALIAS: |
| if (argvars[0].vval.v_typealias != NULL) |
| retval = argvars[0].vval.v_typealias->ta_refcount - 1; |
| break; |
| } |
| |
| rettv->v_type = VAR_NUMBER; |
| rettv->vval.v_number = retval; |
| |
| } |
| |
| /* |
| * "test_garbagecollect_now()" function |
| */ |
| void |
| f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED) |
| { |
| // This is dangerous, any Lists and Dicts used internally may be freed |
| // while still in use. |
| if (!get_vim_var_nr(VV_TESTING)) |
| emsg(_(e_calling_test_garbagecollect_now_while_v_testing_is_not_set)); |
| else |
| garbage_collect(TRUE); |
| } |
| |
| /* |
| * "test_garbagecollect_soon()" function |
| */ |
| void |
| f_test_garbagecollect_soon(typval_T *argvars UNUSED, typval_T *rettv UNUSED) |
| { |
| may_garbage_collect = TRUE; |
| } |
| |
| /* |
| * "test_ignore_error()" function |
| */ |
| void |
| f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| if (check_for_string_arg(argvars, 0) == FAIL) |
| return; |
| |
| ignore_error_for_testing(tv_get_string(&argvars[0])); |
| } |
| |
| void |
| f_test_null_blob(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_BLOB; |
| rettv->vval.v_blob = NULL; |
| } |
| |
| #ifdef FEAT_JOB_CHANNEL |
| void |
| f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_CHANNEL; |
| rettv->vval.v_channel = NULL; |
| } |
| #endif |
| |
| void |
| f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv_dict_set(rettv, NULL); |
| } |
| |
| #ifdef FEAT_JOB_CHANNEL |
| void |
| f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_JOB; |
| rettv->vval.v_job = NULL; |
| } |
| #endif |
| |
| void |
| f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv_list_set(rettv, NULL); |
| } |
| |
| void |
| f_test_null_function(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_FUNC; |
| rettv->vval.v_string = NULL; |
| } |
| |
| void |
| f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_PARTIAL; |
| rettv->vval.v_partial = NULL; |
| } |
| |
| void |
| f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_STRING; |
| rettv->vval.v_string = NULL; |
| } |
| |
| void |
| f_test_unknown(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_UNKNOWN; |
| } |
| |
| void |
| f_test_void(typval_T *argvars UNUSED, typval_T *rettv) |
| { |
| rettv->v_type = VAR_VOID; |
| } |
| |
| void |
| f_test_setmouse(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| if (in_vim9script() |
| && (check_for_number_arg(argvars, 0) == FAIL |
| || check_for_number_arg(argvars, 1) == FAIL)) |
| return; |
| |
| if (argvars[0].v_type != VAR_NUMBER || argvars[1].v_type != VAR_NUMBER) |
| { |
| emsg(_(e_invalid_argument)); |
| return; |
| } |
| |
| mouse_row = (time_t)tv_get_number(&argvars[0]) - 1; |
| mouse_col = (time_t)tv_get_number(&argvars[1]) - 1; |
| } |
| |
| # ifdef FEAT_GUI |
| static int |
| test_gui_drop_files(dict_T *args UNUSED) |
| { |
| # if defined(HAVE_DROP_FILE) |
| int row; |
| int col; |
| int_u mods; |
| char_u **fnames; |
| int count = 0; |
| typval_T t; |
| list_T *l; |
| listitem_T *li; |
| |
| if (!dict_has_key(args, "files") |
| || !dict_has_key(args, "row") |
| || !dict_has_key(args, "col") |
| || !dict_has_key(args, "modifiers")) |
| return FALSE; |
| |
| (void)dict_get_tv(args, "files", &t); |
| row = (int)dict_get_number(args, "row"); |
| col = (int)dict_get_number(args, "col"); |
| mods = (int)dict_get_number(args, "modifiers"); |
| |
| if (t.v_type != VAR_LIST || list_len(t.vval.v_list) == 0) |
| return FALSE; |
| |
| l = t.vval.v_list; |
| fnames = ALLOC_MULT(char_u *, list_len(l)); |
| if (fnames == NULL) |
| return FALSE; |
| |
| FOR_ALL_LIST_ITEMS(l, li) |
| { |
| // ignore non-string items |
| if (li->li_tv.v_type != VAR_STRING |
| || li->li_tv.vval.v_string == NULL) |
| continue; |
| |
| fnames[count] = vim_strsave(li->li_tv.vval.v_string); |
| if (fnames[count] == NULL) |
| { |
| while (--count >= 0) |
| vim_free(fnames[count]); |
| vim_free(fnames); |
| return FALSE; |
| } |
| count++; |
| } |
| |
| if (count > 0) |
| gui_handle_drop(TEXT_X(col - 1), TEXT_Y(row - 1), mods, fnames, count); |
| else |
| vim_free(fnames); |
| # endif |
| |
| return TRUE; |
| } |
| |
| #if defined(FIND_REPLACE_DIALOG) |
| static int |
| test_gui_find_repl(dict_T *args) |
| { |
| int flags; |
| char_u *find_text; |
| char_u *repl_text; |
| int forward; |
| int retval; |
| |
| if (!dict_has_key(args, "find_text") |
| || !dict_has_key(args, "repl_text") |
| || !dict_has_key(args, "flags") |
| || !dict_has_key(args, "forward")) |
| return FALSE; |
| |
| find_text = dict_get_string(args, "find_text", TRUE); |
| repl_text = dict_get_string(args, "repl_text", TRUE); |
| flags = (int)dict_get_number(args, "flags"); |
| forward = (int)dict_get_number(args, "forward"); |
| |
| retval = gui_do_findrepl(flags, find_text, repl_text, forward); |
| vim_free(find_text); |
| vim_free(repl_text); |
| |
| return retval; |
| } |
| #endif |
| |
| static int |
| test_gui_mouse_event(dict_T *args) |
| { |
| int button; |
| int row; |
| int col; |
| int repeated_click; |
| int_u mods; |
| int move; |
| |
| if (!dict_has_key(args, "row") |
| || !dict_has_key(args, "col")) |
| return FALSE; |
| |
| // Note: "move" is optional, requires fewer arguments |
| move = (int)dict_get_bool(args, "move", FALSE); |
| |
| if (!move && (!dict_has_key(args, "button") |
| || !dict_has_key(args, "multiclick") |
| || !dict_has_key(args, "modifiers"))) |
| return FALSE; |
| |
| row = (int)dict_get_number(args, "row"); |
| col = (int)dict_get_number(args, "col"); |
| |
| if (move) |
| { |
| int pY = row; |
| int pX = col; |
| // the "move" argument expects row and col coordnates to be in pixels, |
| // unless "cell" is specified and is TRUE. |
| if (dict_get_bool(args, "cell", FALSE)) |
| { |
| // calculate the middle of the character cell |
| // Note: Cell coordinates are 1-based from vimscript |
| pY = (row - 1) * gui.char_height + gui.char_height / 2; |
| pX = (col - 1) * gui.char_width + gui.char_width / 2; |
| } |
| gui_mouse_moved(pX, pY); |
| } |
| else |
| { |
| button = (int)dict_get_number(args, "button"); |
| repeated_click = (int)dict_get_number(args, "multiclick"); |
| mods = (int)dict_get_number(args, "modifiers"); |
| |
| // Reset the scroll values to known values. |
| // XXX: Remove this when/if the scroll step is made configurable. |
| mouse_set_hor_scroll_step(6); |
| mouse_set_vert_scroll_step(3); |
| |
| gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), |
| repeated_click, mods); |
| } |
| |
| return TRUE; |
| } |
| |
| static int |
| test_gui_scrollbar(dict_T *args) |
| { |
| char_u *which; |
| long value; |
| int dragging; |
| scrollbar_T *sb = NULL; |
| |
| if (!dict_has_key(args, "which") |
| || !dict_has_key(args, "value") |
| || !dict_has_key(args, "dragging")) |
| return FALSE; |
| |
| which = dict_get_string(args, "which", FALSE); |
| value = (long)dict_get_number(args, "value"); |
| dragging = (int)dict_get_number(args, "dragging"); |
| |
| if (STRCMP(which, "left") == 0) |
| sb = &curwin->w_scrollbars[SBAR_LEFT]; |
| else if (STRCMP(which, "right") == 0) |
| sb = &curwin->w_scrollbars[SBAR_RIGHT]; |
| else if (STRCMP(which, "hor") == 0) |
| sb = &gui.bottom_sbar; |
| if (sb == NULL) |
| { |
| semsg(_(e_invalid_argument_str), which); |
| return FALSE; |
| } |
| gui_drag_scrollbar(sb, value, dragging); |
| # ifndef USE_ON_FLY_SCROLL |
| // need to loop through normal_cmd() to handle the scroll events |
| exec_normal(FALSE, TRUE, FALSE); |
| # endif |
| |
| return TRUE; |
| } |
| |
| static int |
| test_gui_tabline_event(dict_T *args UNUSED) |
| { |
| # ifdef FEAT_GUI_TABLINE |
| int tabnr; |
| |
| if (!dict_has_key(args, "tabnr")) |
| return FALSE; |
| |
| tabnr = (int)dict_get_number(args, "tabnr"); |
| |
| return send_tabline_event(tabnr); |
| # else |
| return FALSE; |
| # endif |
| } |
| |
| static int |
| test_gui_tabmenu_event(dict_T *args UNUSED) |
| { |
| # ifdef FEAT_GUI_TABLINE |
| int tabnr; |
| int item; |
| |
| if (!dict_has_key(args, "tabnr") |
| || !dict_has_key(args, "item")) |
| return FALSE; |
| |
| tabnr = (int)dict_get_number(args, "tabnr"); |
| item = (int)dict_get_number(args, "item"); |
| |
| send_tabline_menu_event(tabnr, item); |
| # endif |
| return TRUE; |
| } |
| # endif |
| |
| void |
| f_test_mswin_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED) |
| { |
| # ifdef MSWIN |
| rettv->v_type = VAR_BOOL; |
| rettv->vval.v_number = FALSE; |
| |
| if (sandbox != 0) |
| { |
| emsg(_(e_not_allowed_in_sandbox)); |
| return; |
| } |
| |
| if (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_dict_arg(argvars, 1) == FAIL |
| || argvars[1].vval.v_dict == NULL) |
| return; |
| |
| char_u *event = tv_get_string(&argvars[0]); |
| rettv->vval.v_number = test_mswin_event(event, argvars[1].vval.v_dict); |
| |
| # endif |
| } |
| |
| void |
| f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED) |
| { |
| # ifdef FEAT_GUI |
| char_u *event; |
| |
| rettv->v_type = VAR_BOOL; |
| rettv->vval.v_number = FALSE; |
| |
| if (sandbox != 0) |
| { |
| emsg(_(e_not_allowed_in_sandbox)); |
| return; |
| } |
| |
| if (check_for_string_arg(argvars, 0) == FAIL |
| || check_for_dict_arg(argvars, 1) == FAIL |
| || argvars[1].vval.v_dict == NULL) |
| return; |
| |
| event = tv_get_string(&argvars[0]); |
| if (STRCMP(event, "dropfiles") == 0) |
| rettv->vval.v_number = test_gui_drop_files(argvars[1].vval.v_dict); |
| # if defined(FIND_REPLACE_DIALOG) |
| else if (STRCMP(event, "findrepl") == 0) |
| rettv->vval.v_number = test_gui_find_repl(argvars[1].vval.v_dict); |
| # endif |
| # ifdef MSWIN |
| else if (STRCMP(event, "key") == 0 || STRCMP(event, "mouse") == 0 || STRCMP(event, "set_keycode_trans_strategy") == 0) |
| rettv->vval.v_number = test_mswin_event(event, argvars[1].vval.v_dict); |
| # endif |
| else if (STRCMP(event, "mouse") == 0) |
| rettv->vval.v_number = test_gui_mouse_event(argvars[1].vval.v_dict); |
| else if (STRCMP(event, "scrollbar") == 0) |
| rettv->vval.v_number = test_gui_scrollbar(argvars[1].vval.v_dict); |
| else if (STRCMP(event, "tabline") == 0) |
| rettv->vval.v_number = test_gui_tabline_event(argvars[1].vval.v_dict); |
| else if (STRCMP(event, "tabmenu") == 0) |
| rettv->vval.v_number = test_gui_tabmenu_event(argvars[1].vval.v_dict); |
| else |
| { |
| semsg(_(e_invalid_argument_str), event); |
| return; |
| } |
| # endif |
| } |
| |
| void |
| f_test_settime(typval_T *argvars, typval_T *rettv UNUSED) |
| { |
| if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) |
| return; |
| |
| time_for_testing = (time_t)tv_get_number(&argvars[0]); |
| } |
| |
| #endif // defined(FEAT_EVAL) |