vim-patch:7.4.1663

Problem:    In tests it's often useful to check if a pattern matches.
Solution:   Add assert_match().

ea6553bec3
This commit is contained in:
James McCoy 2016-07-08 13:32:25 -04:00
parent 8c1fb99d2d
commit aece3ffa7d
4 changed files with 98 additions and 22 deletions

View File

@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.4. Last change: 2016 Apr 12
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 27
VIM REFERENCE MANUAL by Bram Moolenaar
@ -1788,6 +1788,7 @@ assert_equal({exp}, {act} [, {msg}]) none assert {exp} equals {act}
assert_exception( {error} [, {msg}]) none assert {error} is in v:exception
assert_fails( {cmd} [, {error}]) none assert {cmd} fails
assert_false({actual} [, {msg}]) none assert {actual} is false
assert_match( {pat}, {text} [, {msg}]) none assert {pat} matches {text}
assert_true({actual} [, {msg}]) none assert {actual} is true
asin({expr}) Float arc sine of {expr}
atan({expr}) Float arc tangent of {expr}
@ -2281,6 +2282,26 @@ assert_false({actual} [, {msg}]) *assert_false()*
When {msg} is omitted an error in the form "Expected False but
got {actual}" is produced.
*assert_match()*
assert_match({pattern}, {actual} [, {msg}])
When {pattern} does not match {actual} an error message is
added to |v:errors|.
{pattern} is used as with |=~|: The matching is always done
like 'magic' was set and 'cpoptions' is empty, no matter what
the actual value of 'magic' or 'cpoptions' is.
{actual} is used as a string, automatic conversion applies.
Use "^" and "$" to match with the start and end of the text.
Use both to match the whole text.
When {msg} is omitted an error in the form "Pattern {pattern}
does not match {actual}" is produced.
Example: >
assert_match('^f.*o$', 'foobar')
< Will result in a string to be added to |v:errors|:
test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~
assert_true({actual} [, {msg}]) *assert_true()*
When {actual} is not true an error message is added to
|v:errors|, like with |assert_equal()|.

View File

@ -3297,6 +3297,26 @@ char_u *get_user_var_name(expand_T *xp, int idx)
}
/// Return TRUE if "pat" matches "text".
/// Does not use 'cpo' and always uses 'magic'.
static int pattern_match(char_u *pat, char_u *text, int ic)
{
int matches = 0;
regmatch_T regmatch;
// avoid 'l' flag in 'cpoptions'
char_u *save_cpo = p_cpo;
p_cpo = (char_u *)"";
regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = ic;
matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
vim_regfree(regmatch.regprog);
}
p_cpo = save_cpo;
return matches;
}
/*
* types for expressions.
*/
@ -3572,9 +3592,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
long n1, n2;
char_u *s1, *s2;
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
regmatch_T regmatch;
int ic;
char_u *save_cpo;
/*
* Get the first variable.
@ -3783,19 +3801,10 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
case TYPE_MATCH:
case TYPE_NOMATCH:
/* avoid 'l' flag in 'cpoptions' */
save_cpo = p_cpo;
p_cpo = (char_u *)"";
regmatch.regprog = vim_regcomp(s2,
RE_MAGIC + RE_STRING);
regmatch.rm_ic = ic;
if (regmatch.regprog != NULL) {
n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
vim_regfree(regmatch.regprog);
if (type == TYPE_NOMATCH)
n1 = !n1;
n1 = pattern_match(s2, s1, ic);
if (type == TYPE_NOMATCH) {
n1 = !n1;
}
p_cpo = save_cpo;
break;
case TYPE_UNKNOWN: break; /* avoid gcc warning */
@ -6697,6 +6706,7 @@ static struct fst {
{ "assert_exception", 1, 2, f_assert_exception },
{ "assert_fails", 1, 2, f_assert_fails },
{ "assert_false", 1, 2, f_assert_false },
{ "assert_match", 2, 3, f_assert_match },
{ "assert_true", 1, 2, f_assert_true },
{ "atan", 1, 1, f_atan },
{ "atan2", 2, 2, f_atan2 },
@ -7606,7 +7616,7 @@ static void prepare_assert_error(garray_T *gap)
// 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,
typval_T *got_tv)
typval_T *got_tv, bool is_match)
{
char_u *tofree;
@ -7615,7 +7625,11 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
ga_concat(gap, tofree);
xfree(tofree);
} else {
ga_concat(gap, (char_u *)"Expected ");
if (is_match) {
ga_concat(gap, (char_u *)"Pattern ");
} else {
ga_concat(gap, (char_u *)"Expected ");
}
if (exp_str == NULL) {
tofree = (char_u *) encode_tv2string(exp_tv, NULL);
ga_concat(gap, tofree);
@ -7624,7 +7638,11 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
ga_concat(gap, exp_str);
}
tofree = (char_u *) encode_tv2string(got_tv, NULL);
ga_concat(gap, (char_u *)" but got ");
if (is_match) {
ga_concat(gap, (char_u *)" does not match ");
} else {
ga_concat(gap, (char_u *)" but got ");
}
ga_concat(gap, tofree);
xfree(tofree);
}
@ -7651,7 +7669,7 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv)
if (!tv_equal(&argvars[0], &argvars[1], false, false)) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL,
&argvars[0], &argvars[1]);
&argvars[0], &argvars[1], false);
assert_error(&ga);
ga_clear(&ga);
}
@ -7672,7 +7690,7 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv)
&& strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
&vimvars[VV_EXCEPTION].vv_tv);
&vimvars[VV_EXCEPTION].vv_tv, false);
assert_error(&ga);
ga_clear(&ga);
}
@ -7702,7 +7720,7 @@ static void f_assert_fails(typval_T *argvars, typval_T *rettv)
|| strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
&vimvars[VV_ERRMSG].vv_tv);
&vimvars[VV_ERRMSG].vv_tv, false);
assert_error(&ga);
ga_clear(&ga);
}
@ -7732,7 +7750,7 @@ static void assert_bool(typval_T *argvars, bool is_true)
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[1],
(char_u *)(is_true ? "True" : "False"),
NULL, &argvars[0]);
NULL, &argvars[0], false);
assert_error(&ga);
ga_clear(&ga);
}
@ -7744,6 +7762,23 @@ static void f_assert_false(typval_T *argvars, typval_T *rettv)
assert_bool(argvars, false);
}
/// "assert_match(pattern, actual[, msg])" function
static void f_assert_match(typval_T *argvars, typval_T *rettv)
{
char_u buf1[NUMBUFLEN];
char_u buf2[NUMBUFLEN];
char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1);
char_u *text = get_tv_string_buf_chk(&argvars[1], buf2);
if (!pattern_match(pat, text, false)) {
garray_T ga;
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], true);
assert_error(&ga);
ga_clear(&ga);
}
}
// "assert_true(actual[, msg])" function
static void f_assert_true(typval_T *argvars, typval_T *rettv)
{

View File

@ -91,6 +91,7 @@ static int included_patches[] = {
1716,
1712,
1695,
1663,
1654,
1652,
1649,

View File

@ -155,10 +155,29 @@ describe('assert function:', function()
end)
end)
-- assert_match({pat}, {text}[, {msg}])
describe('assert_match', function()
it('should not change v:errors when pat matches text', function()
call('assert_match', '^f.*b.*r$', 'foobar')
expected_empty()
end)
it('should change v:errors when pat does not match text', function()
call('assert_match', 'bar.*foo', 'foobar')
expected_errors({"Pattern 'bar.*foo' does not match 'foobar'"})
end)
it('should set v:errors to msg when given and match fails', function()
call('assert_match', 'bar.*foo', 'foobar', 'wrong')
expected_errors({"'wrong'"})
end)
end)
-- assert_fails({cmd}, [, {error}])
describe('assert_fails', function()
it('should change v:errors when error does not match v:errmsg', function()
execute([[call assert_fails('xxx', {})]])
execute([[call assert_match("Expected {} but got 'E731:", v:errors[0])]])
expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"})
end)