From aece3ffa7dca546bd5c358478dfb9f423519e211 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 8 Jul 2016 13:32:25 -0400 Subject: [PATCH 1/4] vim-patch:7.4.1663 Problem: In tests it's often useful to check if a pattern matches. Solution: Add assert_match(). https://github.com/vim/vim/commit/ea6553bec340920d8a09c7210cdc2d218e25ace2 --- runtime/doc/eval.txt | 23 +++++++- src/nvim/eval.c | 77 +++++++++++++++++++------- src/nvim/version.c | 1 + test/functional/legacy/assert_spec.lua | 19 +++++++ 4 files changed, 98 insertions(+), 22 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index efb8da0cfa..7b6a330e94 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -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()|. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a43a389478..7a2ac65ce1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -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(®match, 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(®match, 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) { diff --git a/src/nvim/version.c b/src/nvim/version.c index 527ef3b9ad..ff6f93042b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -91,6 +91,7 @@ static int included_patches[] = { 1716, 1712, 1695, + 1663, 1654, 1652, 1649, diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 8da6ee45d7..cf1dcf6686 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -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) From f1d912c584c10f92fe0710e3a907c3d519fbe7d8 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 8 Jul 2016 14:30:16 -0400 Subject: [PATCH 2/4] vim-patch:7.4.1682 Problem: Coverity: no check for NULL. Solution: Add check for invalid argument to assert_match(). https://github.com/vim/vim/commit/72188e9aae26e6191c68ff673ef145104b17c64f --- src/nvim/eval.c | 4 +++- src/nvim/version.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7a2ac65ce1..967485af1a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7770,7 +7770,9 @@ static void f_assert_match(typval_T *argvars, typval_T *rettv) 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)) { + if (pat == NULL || text == NULL) { + EMSG(_(e_invarg)); + } else 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); diff --git a/src/nvim/version.c b/src/nvim/version.c index ff6f93042b..16fdb5f09f 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -91,6 +91,7 @@ static int included_patches[] = { 1716, 1712, 1695, + 1682, 1663, 1654, 1652, From 452707e0b0bb6927350d2a68485a5453c214610b Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 8 Jul 2016 14:09:10 -0400 Subject: [PATCH 3/4] vim-patch:7.4.1703 Problem: Can't assert for not equal and not matching. Solution: Add assert_notmatch() and assert_notequal(). https://github.com/vim/vim/commit/b50e5f56861deb867478997397f7c784a7043233 --- runtime/doc/eval.txt | 14 ++++++- src/nvim/eval.c | 57 +++++++++++++++++++------- src/nvim/eval_defs.h | 10 +++++ src/nvim/version.c | 1 + test/functional/legacy/assert_spec.lua | 28 +++++++++++++ 5 files changed, 95 insertions(+), 15 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 7b6a330e94..ba38a140d1 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1784,11 +1784,13 @@ argidx() Number current index in the argument list arglistid([{winnr} [, {tabnr}]]) Number argument list id argv({nr}) String {nr} entry of the argument list argv() List the argument list -assert_equal({exp}, {act} [, {msg}]) none assert {exp} equals {act} +assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {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_notequal( {exp}, {act} [, {msg}]) none assert {exp} is not equal {act} +assert_notmatch( {pat}, {text} [, {msg}]) none assert {pat} not 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} @@ -2302,6 +2304,16 @@ assert_match({pattern}, {actual} [, {msg}]) < Will result in a string to be added to |v:errors|: test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~ + *assert_notequal()* +assert_notequal({expected}, {actual} [, {msg}]) + The opposite of `assert_equal()`: add an error message to + |v:errors| when {expected} and {actual} are equal. + + *assert_notmatch()* +assert_notmatch({pattern}, {actual} [, {msg}]) + The opposite of `assert_match()`: add an error message to + |v:errors| when {pattern} matches {actual}. + 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/nvim/eval.c b/src/nvim/eval.c index 967485af1a..4374d66e4b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6707,6 +6707,8 @@ static struct fst { { "assert_fails", 1, 2, f_assert_fails }, { "assert_false", 1, 2, f_assert_false }, { "assert_match", 2, 3, f_assert_match }, + { "assert_notequal", 2, 3, f_assert_notequal }, + { "assert_notmatch", 2, 3, f_assert_notmatch }, { "assert_true", 1, 2, f_assert_true }, { "atan", 1, 1, f_atan }, { "atan2", 2, 2, f_atan2 }, @@ -7616,7 +7618,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, bool is_match) + typval_T *got_tv, assert_type_T atype) { char_u *tofree; @@ -7625,7 +7627,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, ga_concat(gap, tofree); xfree(tofree); } else { - if (is_match) { + if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) { ga_concat(gap, (char_u *)"Pattern "); } else { ga_concat(gap, (char_u *)"Expected "); @@ -7638,8 +7640,12 @@ 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); - if (is_match) { + 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 if (atype == ASSERT_NOTEQUAL) { + ga_concat(gap, (char_u *)" differs from "); } else { ga_concat(gap, (char_u *)" but got "); } @@ -7661,20 +7667,32 @@ static void assert_error(garray_T *gap) gap->ga_data, gap->ga_len); } -// "assert_equal(expected, actual[, msg])" function -static void f_assert_equal(typval_T *argvars, typval_T *rettv) +static void assert_equal_common(typval_T *argvars, assert_type_T atype) { garray_T ga; - if (!tv_equal(&argvars[0], &argvars[1], false, false)) { + if (tv_equal(&argvars[0], &argvars[1], false, false) + != (atype == ASSERT_EQUAL)) { prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, - &argvars[0], &argvars[1], false); + &argvars[0], &argvars[1], atype); assert_error(&ga); ga_clear(&ga); } } +// "assert_equal(expected, actual[, msg])" function +static void f_assert_equal(typval_T *argvars, typval_T *rettv) +{ + assert_equal_common(argvars, ASSERT_EQUAL); +} + +// "assert_notequal(expected, actual[, msg])" function +static void f_assert_notequal(typval_T *argvars, typval_T *rettv) +{ + assert_equal_common(argvars, ASSERT_NOTEQUAL); +} + /// "assert_exception(string[, msg])" function static void f_assert_exception(typval_T *argvars, typval_T *rettv) { @@ -7690,7 +7708,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, false); + &vimvars[VV_EXCEPTION].vv_tv, ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -7720,7 +7738,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, false); + &vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -7750,7 +7768,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], false); + NULL, &argvars[0], ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -7762,8 +7780,7 @@ 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) +static void assert_match_common(typval_T *argvars, assert_type_T atype) { char_u buf1[NUMBUFLEN]; char_u buf2[NUMBUFLEN]; @@ -7772,15 +7789,27 @@ static void f_assert_match(typval_T *argvars, typval_T *rettv) if (pat == NULL || text == NULL) { EMSG(_(e_invarg)); - } else if (!pattern_match(pat, text, false)) { + } else if (pattern_match(pat, text, false) != (atype == ASSERT_MATCH)) { garray_T ga; prepare_assert_error(&ga); - fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], true); + fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], atype); assert_error(&ga); ga_clear(&ga); } } +/// "assert_match(pattern, actual[, msg])" function +static void f_assert_match(typval_T *argvars, typval_T *rettv) +{ + assert_match_common(argvars, ASSERT_MATCH); +} + +/// "assert_notmatch(pattern, actual[, msg])" function +static void f_assert_notmatch(typval_T *argvars, typval_T *rettv) +{ + assert_match_common(argvars, ASSERT_NOTMATCH); +} + // "assert_true(actual[, msg])" function static void f_assert_true(typval_T *argvars, typval_T *rettv) { diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h index d5c9b2c1ec..884c987f10 100644 --- a/src/nvim/eval_defs.h +++ b/src/nvim/eval_defs.h @@ -162,4 +162,14 @@ typedef struct list_stack_S { /// Convert a hashitem pointer to a dictitem pointer #define HI2DI(hi) HIKEY2DI((hi)->hi_key) +/// Type of assert_* check being performed +typedef enum +{ + ASSERT_EQUAL, + ASSERT_NOTEQUAL, + ASSERT_MATCH, + ASSERT_NOTMATCH, + ASSERT_OTHER, +} assert_type_T; + #endif // NVIM_EVAL_DEFS_H diff --git a/src/nvim/version.c b/src/nvim/version.c index 16fdb5f09f..921491db75 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -90,6 +90,7 @@ static int included_patches[] = { 1728, 1716, 1712, + 1703, 1695, 1682, 1663, diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index cf1dcf6686..42dd25023a 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -64,6 +64,20 @@ describe('assert function:', function() end) end) + -- assert_notequal({expected}, {actual}[, {msg}]) + describe('assert_notequal', function() + it('should not change v:errors when expected differs from actual', function() + call('assert_notequal', 'foo', 4) + call('assert_notequal', {1, 2, 3}, 'foo') + expected_empty() + end) + + it('should change v:errors when expected is equal to actual', function() + call('assert_notequal', 'foo', 'foo') + expected_errors({"Expected 'foo' differs from 'foo'"}) + end) + end) + -- assert_false({actual}, [, {msg}]) describe('assert_false', function() it('should not change v:errors when actual is false', function() @@ -173,6 +187,20 @@ describe('assert function:', function() end) end) + -- assert_notmatch({pat}, {text}[, {msg}]) + describe('assert_notmatch', function() + it('should not change v:errors when pat does not match text', function() + call('assert_notmatch', 'foo', 'bar') + call('assert_notmatch', '^foobar$', 'foobars') + expected_empty() + end) + + it('should change v:errors when pat matches text', function() + call('assert_notmatch', 'foo', 'foobar') + expected_errors({"Pattern 'foo' does match 'foobar'"}) + end) + end) + -- assert_fails({cmd}, [, {error}]) describe('assert_fails', function() it('should change v:errors when error does not match v:errmsg', function() From a4987bac3ea8cf6d1e7a9677e5cbdf52d618dced Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 8 Jul 2016 14:33:51 -0400 Subject: [PATCH 4/4] lint --- src/nvim/eval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 4374d66e4b..7fb7969783 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7639,7 +7639,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, } else { ga_concat(gap, exp_str); } - tofree = (char_u *) encode_tv2string(got_tv, NULL); + tofree = (char_u *)encode_tv2string(got_tv, NULL); if (atype == ASSERT_MATCH) { ga_concat(gap, (char_u *)" does not match "); } else if (atype == ASSERT_NOTMATCH) {