Skip to content

Commit ea6553b

Browse files
committed
patch 7.4.1663
Problem: In tests it's often useful to check if a pattern matches. Solution: Add assert_match().
1 parent 4f3f668 commit ea6553b

5 files changed

Lines changed: 107 additions & 28 deletions

File tree

runtime/doc/eval.txt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 26
1+
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1805,6 +1805,7 @@ assert_equal( {exp}, {act} [, {msg}]) none assert {exp} equals {act}
18051805
assert_exception( {error} [, {msg}]) none assert {error} is in v:exception
18061806
assert_fails( {cmd} [, {error}]) none assert {cmd} fails
18071807
assert_false( {actual} [, {msg}]) none assert {actual} is false
1808+
assert_match( {pat}, {text} [, {msg}]) none assert {pat} matches {text}
18081809
assert_true( {actual} [, {msg}]) none assert {actual} is true
18091810
asin( {expr}) Float arc sine of {expr}
18101811
atan( {expr}) Float arc tangent of {expr}
@@ -2315,6 +2316,26 @@ assert_false({actual} [, {msg}]) *assert_false()*
23152316
When {msg} is omitted an error in the form "Expected False but
23162317
got {actual}" is produced.
23172318

2319+
*assert_match()*
2320+
assert_match({pattern}, {actual} [, {msg}])
2321+
When {pattern} does not match {actual} an error message is
2322+
added to |v:errors|.
2323+
2324+
{pattern} is used as with |=~|: The matching is always done
2325+
like 'magic' was set and 'cpoptions' is empty, no matter what
2326+
the actual value of 'magic' or 'cpoptions' is.
2327+
2328+
{actual} is used as a string, automatic conversion applies.
2329+
Use "^" and "$" to match with the start and end of the text.
2330+
Use both to match the whole text.
2331+
2332+
When {msg} is omitted an error in the form "Pattern {pattern}
2333+
does not match {actual}" is produced.
2334+
Example: >
2335+
assert_match('^f.*o$', 'foobar')
2336+
< Will result in a string to be added to |v:errors|:
2337+
test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~
2338+
23182339
assert_true({actual} [, {msg}]) *assert_true()*
23192340
When {actual} is not true an error message is added to
23202341
|v:errors|, like with |assert_equal()|.

src/eval.c

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv);
475475
static void f_assert_exception(typval_T *argvars, typval_T *rettv);
476476
static void f_assert_fails(typval_T *argvars, typval_T *rettv);
477477
static void f_assert_false(typval_T *argvars, typval_T *rettv);
478+
static void f_assert_match(typval_T *argvars, typval_T *rettv);
478479
static void f_assert_true(typval_T *argvars, typval_T *rettv);
479480
#ifdef FEAT_FLOAT
480481
static void f_asin(typval_T *argvars, typval_T *rettv);
@@ -4105,6 +4106,31 @@ get_user_var_name(expand_T *xp, int idx)
41054106

41064107
#endif /* FEAT_CMDL_COMPL */
41074108

4109+
/*
4110+
* Return TRUE if "pat" matches "text".
4111+
* Does not use 'cpo' and always uses 'magic'.
4112+
*/
4113+
static int
4114+
pattern_match(char_u *pat, char_u *text, int ic)
4115+
{
4116+
int matches = FALSE;
4117+
char_u *save_cpo;
4118+
regmatch_T regmatch;
4119+
4120+
/* avoid 'l' flag in 'cpoptions' */
4121+
save_cpo = p_cpo;
4122+
p_cpo = (char_u *)"";
4123+
regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
4124+
if (regmatch.regprog != NULL)
4125+
{
4126+
regmatch.rm_ic = ic;
4127+
matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
4128+
vim_regfree(regmatch.regprog);
4129+
}
4130+
p_cpo = save_cpo;
4131+
return matches;
4132+
}
4133+
41084134
/*
41094135
* types for expressions.
41104136
*/
@@ -4403,9 +4429,7 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
44034429
long n1, n2;
44044430
char_u *s1, *s2;
44054431
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4406-
regmatch_T regmatch;
44074432
int ic;
4408-
char_u *save_cpo;
44094433

44104434
/*
44114435
* Get the first variable.
@@ -4646,20 +4670,9 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
46464670

46474671
case TYPE_MATCH:
46484672
case TYPE_NOMATCH:
4649-
/* avoid 'l' flag in 'cpoptions' */
4650-
save_cpo = p_cpo;
4651-
p_cpo = (char_u *)"";
4652-
regmatch.regprog = vim_regcomp(s2,
4653-
RE_MAGIC + RE_STRING);
4654-
regmatch.rm_ic = ic;
4655-
if (regmatch.regprog != NULL)
4656-
{
4657-
n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
4658-
vim_regfree(regmatch.regprog);
4659-
if (type == TYPE_NOMATCH)
4660-
n1 = !n1;
4661-
}
4662-
p_cpo = save_cpo;
4673+
n1 = pattern_match(s2, s1, ic);
4674+
if (type == TYPE_NOMATCH)
4675+
n1 = !n1;
46634676
break;
46644677

46654678
case TYPE_UNKNOWN: break; /* avoid gcc warning */
@@ -8154,6 +8167,7 @@ static struct fst
81548167
{"assert_exception", 1, 2, f_assert_exception},
81558168
{"assert_fails", 1, 2, f_assert_fails},
81568169
{"assert_false", 1, 2, f_assert_false},
8170+
{"assert_match", 2, 3, f_assert_match},
81578171
{"assert_true", 1, 2, f_assert_true},
81588172
#ifdef FEAT_FLOAT
81598173
{"atan", 1, 1, f_atan},
@@ -9295,7 +9309,7 @@ f_argv(typval_T *argvars, typval_T *rettv)
92959309
}
92969310

92979311
static void prepare_assert_error(garray_T*gap);
9298-
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);
9312+
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);
92999313
static void assert_error(garray_T *gap);
93009314
static void assert_bool(typval_T *argvars, int isTrue);
93019315

@@ -9370,7 +9384,8 @@ fill_assert_error(
93709384
typval_T *opt_msg_tv,
93719385
char_u *exp_str,
93729386
typval_T *exp_tv,
9373-
typval_T *got_tv)
9387+
typval_T *got_tv,
9388+
int is_match)
93749389
{
93759390
char_u numbuf[NUMBUFLEN];
93769391
char_u *tofree;
@@ -9382,15 +9397,21 @@ fill_assert_error(
93829397
}
93839398
else
93849399
{
9385-
ga_concat(gap, (char_u *)"Expected ");
9400+
if (is_match)
9401+
ga_concat(gap, (char_u *)"Pattern ");
9402+
else
9403+
ga_concat(gap, (char_u *)"Expected ");
93869404
if (exp_str == NULL)
93879405
{
93889406
ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0));
93899407
vim_free(tofree);
93909408
}
93919409
else
93929410
ga_concat_esc(gap, exp_str);
9393-
ga_concat(gap, (char_u *)" but got ");
9411+
if (is_match)
9412+
ga_concat(gap, (char_u *)" does not match ");
9413+
else
9414+
ga_concat(gap, (char_u *)" but got ");
93949415
ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
93959416
vim_free(tofree);
93969417
}
@@ -9421,7 +9442,8 @@ f_assert_equal(typval_T *argvars, typval_T *rettv UNUSED)
94219442
if (!tv_equal(&argvars[0], &argvars[1], FALSE, FALSE))
94229443
{
94239444
prepare_assert_error(&ga);
9424-
fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1]);
9445+
fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
9446+
FALSE);
94259447
assert_error(&ga);
94269448
ga_clear(&ga);
94279449
}
@@ -9449,7 +9471,7 @@ f_assert_exception(typval_T *argvars, typval_T *rettv UNUSED)
94499471
{
94509472
prepare_assert_error(&ga);
94519473
fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
9452-
&vimvars[VV_EXCEPTION].vv_tv);
9474+
&vimvars[VV_EXCEPTION].vv_tv, FALSE);
94539475
assert_error(&ga);
94549476
ga_clear(&ga);
94559477
}
@@ -9486,7 +9508,7 @@ f_assert_fails(typval_T *argvars, typval_T *rettv UNUSED)
94869508
{
94879509
prepare_assert_error(&ga);
94889510
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
9489-
&vimvars[VV_ERRMSG].vv_tv);
9511+
&vimvars[VV_ERRMSG].vv_tv, FALSE);
94909512
assert_error(&ga);
94919513
ga_clear(&ga);
94929514
}
@@ -9518,7 +9540,7 @@ assert_bool(typval_T *argvars, int isTrue)
95189540
prepare_assert_error(&ga);
95199541
fill_assert_error(&ga, &argvars[1],
95209542
(char_u *)(isTrue ? "True" : "False"),
9521-
NULL, &argvars[0]);
9543+
NULL, &argvars[0], FALSE);
95229544
assert_error(&ga);
95239545
ga_clear(&ga);
95249546
}
@@ -9533,6 +9555,28 @@ f_assert_false(typval_T *argvars, typval_T *rettv UNUSED)
95339555
assert_bool(argvars, FALSE);
95349556
}
95359557

9558+
/*
9559+
* "assert_match(pattern, actual[, msg])" function
9560+
*/
9561+
static void
9562+
f_assert_match(typval_T *argvars, typval_T *rettv UNUSED)
9563+
{
9564+
garray_T ga;
9565+
char_u buf1[NUMBUFLEN];
9566+
char_u buf2[NUMBUFLEN];
9567+
char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1);
9568+
char_u *text = get_tv_string_buf_chk(&argvars[1], buf2);
9569+
9570+
if (!pattern_match(pat, text, FALSE))
9571+
{
9572+
prepare_assert_error(&ga);
9573+
fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
9574+
TRUE);
9575+
assert_error(&ga);
9576+
ga_clear(&ga);
9577+
}
9578+
}
9579+
95369580
/*
95379581
* "assert_true(actual[, msg])" function
95389582
*/

src/testdir/test_assert.vim

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,26 @@ func Test_compare_fail()
5757
call assert_equal(s:w, '')
5858
catch
5959
call assert_exception('E724:')
60-
call assert_true(v:errors[0] =~ "Expected NULL but got ''")
60+
call assert_match("Expected NULL but got ''", v:errors[0])
6161
call remove(v:errors, 0)
6262
endtry
6363
endfunc
6464

65+
func Test_match()
66+
call assert_match('^f.*b.*r$', 'foobar')
67+
68+
call assert_match('bar.*foo', 'foobar')
69+
call assert_match("Pattern 'bar.*foo' does not match 'foobar'", v:errors[0])
70+
call remove(v:errors, 0)
71+
72+
call assert_match('bar.*foo', 'foobar', 'wrong')
73+
call assert_match('wrong', v:errors[0])
74+
call remove(v:errors, 0)
75+
endfunc
76+
6577
func Test_assert_fail_fails()
6678
call assert_fails('xxx', {})
67-
call assert_true(v:errors[0] =~ "Expected {} but got 'E731:")
79+
call assert_match("Expected {} but got 'E731:", v:errors[0])
6880
call remove(v:errors, 0)
6981
endfunc
7082

src/testdir/test_channel.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func s:communicate(port)
154154
" Request command "foo bar", which fails silently.
155155
call assert_equal('ok', ch_evalexpr(handle, 'bad command'))
156156
call s:waitFor('v:errmsg =~ "E492"')
157-
call assert_true(v:errmsg =~ 'E492:.*foo bar')
157+
call assert_match('E492:.*foo bar', v:errmsg)
158158

159159
call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100}))
160160
call s:waitFor('"added more" == getline("$")')

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,8 @@ static char *(features[]) =
748748

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1663,
751753
/**/
752754
1662,
753755
/**/

0 commit comments

Comments
 (0)