changeset 8749:65a5a18d3acf v7.4.1663

commit https://github.com/vim/vim/commit/ea6553bec340920d8a09c7210cdc2d218e25ace2 Author: Bram Moolenaar <Bram@vim.org> 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().
author Christian Brabandt <cb@256bit.org>
date Sun, 27 Mar 2016 15:15:06 +0200
parents b1a19a2f73f0
children 8c639c05f1b0
files runtime/doc/eval.txt src/eval.c src/testdir/test_assert.vim src/testdir/test_channel.vim src/version.c
diffstat 5 files changed, 107 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- 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()|.
--- 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(&regmatch, 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(&regmatch, 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
--- 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
 
--- 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("$")')
--- 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,