# HG changeset patch # User Christian Brabandt # Date 1459084506 -7200 # Node ID 65a5a18d3acf4394db5d233e4152641fe38a5b54 # Parent b1a19a2f73f0095bfbaa5776e1e03ec5c447a2d7 commit https://github.com/vim/vim/commit/ea6553bec340920d8a09c7210cdc2d218e25ace2 Author: Bram Moolenaar Date: Sun Mar 27 15:13:38 2016 +0200 patch 7.4.1663 Problem: In tests it's often useful to check if a pattern matches. Solution: Add assert_match(). diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 Mar 26 +*eval.txt* For Vim version 7.4. Last change: 2016 Mar 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1805,6 +1805,7 @@ assert_equal( {exp}, {act} [, {msg}]) no 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} @@ -2315,6 +2316,26 @@ assert_false({actual} [, {msg}]) *ass 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()|. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -475,6 +475,7 @@ static void f_assert_equal(typval_T *arg static void f_assert_exception(typval_T *argvars, typval_T *rettv); static void f_assert_fails(typval_T *argvars, typval_T *rettv); static void f_assert_false(typval_T *argvars, typval_T *rettv); +static void f_assert_match(typval_T *argvars, typval_T *rettv); static void f_assert_true(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT static void f_asin(typval_T *argvars, typval_T *rettv); @@ -4106,6 +4107,31 @@ get_user_var_name(expand_T *xp, int idx) #endif /* FEAT_CMDL_COMPL */ /* + * 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 = FALSE; + char_u *save_cpo; + regmatch_T regmatch; + + /* avoid 'l' flag in 'cpoptions' */ + 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(®match, text, (colnr_T)0); + vim_regfree(regmatch.regprog); + } + p_cpo = save_cpo; + return matches; +} + +/* * types for expressions. */ typedef enum @@ -4403,9 +4429,7 @@ eval4(char_u **arg, typval_T *rettv, int 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. @@ -4646,20 +4670,9 @@ eval4(char_u **arg, typval_T *rettv, int 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(®match, s1, (colnr_T)0); - vim_regfree(regmatch.regprog); - if (type == TYPE_NOMATCH) - n1 = !n1; - } - p_cpo = save_cpo; + n1 = pattern_match(s2, s1, ic); + if (type == TYPE_NOMATCH) + n1 = !n1; break; case TYPE_UNKNOWN: break; /* avoid gcc warning */ @@ -8154,6 +8167,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}, #ifdef FEAT_FLOAT {"atan", 1, 1, f_atan}, @@ -9295,7 +9309,7 @@ f_argv(typval_T *argvars, typval_T *rett } static void prepare_assert_error(garray_T*gap); -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); +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, int is_match); static void assert_error(garray_T *gap); static void assert_bool(typval_T *argvars, int isTrue); @@ -9370,7 +9384,8 @@ fill_assert_error( typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, - typval_T *got_tv) + typval_T *got_tv, + int is_match) { char_u numbuf[NUMBUFLEN]; char_u *tofree; @@ -9382,7 +9397,10 @@ fill_assert_error( } 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) { ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); @@ -9390,7 +9408,10 @@ fill_assert_error( } else ga_concat_esc(gap, exp_str); - 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_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); vim_free(tofree); } @@ -9421,7 +9442,8 @@ f_assert_equal(typval_T *argvars, typval if (!tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)) { prepare_assert_error(&ga); - fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1]); + fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], + FALSE); assert_error(&ga); ga_clear(&ga); } @@ -9449,7 +9471,7 @@ f_assert_exception(typval_T *argvars, ty { 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); } @@ -9486,7 +9508,7 @@ f_assert_fails(typval_T *argvars, typval { 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); } @@ -9518,7 +9540,7 @@ assert_bool(typval_T *argvars, int isTru prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[1], (char_u *)(isTrue ? "True" : "False"), - NULL, &argvars[0]); + NULL, &argvars[0], FALSE); assert_error(&ga); ga_clear(&ga); } @@ -9534,6 +9556,28 @@ f_assert_false(typval_T *argvars, typval } /* + * "assert_match(pattern, actual[, msg])" function + */ + static void +f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) +{ + garray_T ga; + 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)) + { + 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 diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -57,14 +57,26 @@ func Test_compare_fail() call assert_equal(s:w, '') catch call assert_exception('E724:') - call assert_true(v:errors[0] =~ "Expected NULL but got ''") + call assert_match("Expected NULL but got ''", v:errors[0]) call remove(v:errors, 0) endtry endfunc +func Test_match() + call assert_match('^f.*b.*r$', 'foobar') + + call assert_match('bar.*foo', 'foobar') + call assert_match("Pattern 'bar.*foo' does not match 'foobar'", v:errors[0]) + call remove(v:errors, 0) + + call assert_match('bar.*foo', 'foobar', 'wrong') + call assert_match('wrong', v:errors[0]) + call remove(v:errors, 0) +endfunc + func Test_assert_fail_fails() call assert_fails('xxx', {}) - call assert_true(v:errors[0] =~ "Expected {} but got 'E731:") + call assert_match("Expected {} but got 'E731:", v:errors[0]) call remove(v:errors, 0) endfunc diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -154,7 +154,7 @@ func s:communicate(port) " Request command "foo bar", which fails silently. call assert_equal('ok', ch_evalexpr(handle, 'bad command')) call s:waitFor('v:errmsg =~ "E492"') - call assert_true(v:errmsg =~ 'E492:.*foo bar') + call assert_match('E492:.*foo bar', v:errmsg) call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100})) call s:waitFor('"added more" == getline("$")') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -749,6 +749,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1663, +/**/ 1662, /**/ 1661,