changeset 19958:0b42b5e50344 v8.2.0535

patch 8.2.0535: regexp patterns not fully tested Commit: https://github.com/vim/vim/commit/4d23c52824dd2f4577eb980e7d91feed34052755 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Apr 9 18:42:11 2020 +0200 patch 8.2.0535: regexp patterns not fully tested Problem: Regexp patterns not fully tested. Solution: Add more regexp tests and others. (Yegappan Lakshmanan, closes #5901)
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 Apr 2020 18:45:06 +0200
parents 6538d2040eb6
children 12eb22ecf35b
files src/testdir/test_marks.vim src/testdir/test_options.vim src/testdir/test_regexp_latin.vim src/testdir/test_search.vim src/version.c
diffstat 5 files changed, 166 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_marks.vim
+++ b/src/testdir/test_marks.vim
@@ -207,6 +207,9 @@ func Test_mark_error()
   call assert_fails('mark xx', 'E488:')
   call assert_fails('mark _', 'E191:')
   call assert_beeps('normal! m~')
+
+  call setpos("'k", [0, 100, 1, 0])
+  call assert_fails("normal 'k", 'E19:')
 endfunc
 
 " Test for :lockmarks when pasting content
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -677,6 +677,15 @@ func Test_buftype()
   bwipe!
 endfunc
 
+" Test for the 'shell' option
+func Test_shell()
+  CheckUnix
+  let save_shell = &shell
+  set shell=
+  call assert_fails('shell', 'E91:')
+  let &shell = save_shell
+endfunc
+
 " Test for the 'shellquote' option
 func Test_shellquote()
   CheckUnix
--- a/src/testdir/test_regexp_latin.vim
+++ b/src/testdir/test_regexp_latin.vim
@@ -147,7 +147,10 @@ endfunc
 " Tests for regexp patterns without multi-byte support.
 func Test_regexp_single_line_pat()
   " tl is a List of Lists with:
-  "    regexp engine
+  "    regexp engines to test
+  "       0 - test with 'regexpengine' values 0 and 1
+  "       1 - test with 'regexpengine' values 0 and 2
+  "       2 - test with 'regexpengine' values 0, 1 and 2
   "    regexp pattern
   "    text to test the pattern on
   "    expected match (optional)
@@ -168,6 +171,8 @@ func Test_regexp_single_line_pat()
   call add(tl, [2, 'c*', 'abdef', ''])
   call add(tl, [2, 'bc\+', 'abccccdef', 'bcccc'])
   call add(tl, [2, 'bc\+', 'abdef']) " no match
+  " match newline character in a string
+  call add(tl, [2, 'o\nb', "foo\nbar", "o\nb"])
 
   " operator \|
   call add(tl, [2, 'a\|ab', 'cabd', 'a']) " alternation is ordered
@@ -591,6 +596,9 @@ func Test_regexp_single_line_pat()
   " Test \%V atom
   call add(tl, [2, '\%>70vGesamt', 'Jean-Michel Charlier & Victor Hubinon\Gesamtausgabe [Salleck]    Buck Danny {Jean-Michel Charlier & Victor Hubinon}\Gesamtausgabe', 'Gesamt'])
 
+  " Test for ignoring case and matching repeated characters
+  call add(tl, [2, '\cb\+', 'aAbBbBcC', 'bBbB'])
+
   " Run the tests
   for t in tl
     let re = t[0]
@@ -650,6 +658,14 @@ endfunc
 
 " Tests for multi-line regexp patterns without multi-byte support.
 func Test_regexp_multiline_pat()
+  " tl is a List of Lists with:
+  "    regexp engines to test
+  "       0 - test with 'regexpengine' values 0 and 1
+  "       1 - test with 'regexpengine' values 0 and 2
+  "       2 - test with 'regexpengine' values 0, 1 and 2
+  "    regexp pattern
+  "    List with text to test the pattern on
+  "    List with the expected match
   let tl = []
 
   " back references
@@ -659,6 +675,70 @@ func Test_regexp_multiline_pat()
   " line breaks
   call add(tl, [2, '\S.*\nx', ['abc', 'def', 'ghi', 'xjk', 'lmn'], ['abc', 'def', 'XXjk', 'lmn']])
 
+  " Any single character or end-of-line
+  call add(tl, [2, '\_.\+', ['a', 'b', 'c'], ['XX']])
+  " Any identifier or end-of-line
+  call add(tl, [2, '\_i\+', ['a', 'b', ';', '2'], ['XX;XX']])
+  " Any identifier but excluding digits or end-of-line
+  call add(tl, [2, '\_I\+', ['a', 'b', ';', '2'], ['XX;XX2XX']])
+  " Any keyword or end-of-line
+  call add(tl, [2, '\_k\+', ['a', 'b', '=', '2'], ['XX=XX']])
+  " Any keyword but excluding digits or end-of-line
+  call add(tl, [2, '\_K\+', ['a', 'b', '=', '2'], ['XX=XX2XX']])
+  " Any filename character or end-of-line
+  call add(tl, [2, '\_f\+', ['a', 'b', '.', '5'], ['XX']])
+  " Any filename character but excluding digits or end-of-line
+  call add(tl, [2, '\_F\+', ['a', 'b', '.', '5'], ['XX5XX']])
+  " Any printable character or end-of-line
+  call add(tl, [2, '\_p\+', ['a', 'b', '=', '4'], ['XX']])
+  " Any printable character excluding digits or end-of-line
+  call add(tl, [2, '\_P\+', ['a', 'b', '=', '4'], ['XX4XX']])
+  " Any whitespace character or end-of-line
+  call add(tl, [2, '\_s\+', [' ', ' ', 'a', 'b'], ['XXaXXbXX']])
+  " Any non-whitespace character or end-of-line
+  call add(tl, [2, '\_S\+', [' ', ' ', 'a', 'b'], [' XX XX']])
+  " Any decimal digit or end-of-line
+  call add(tl, [2, '\_d\+', ['1', 'a', '2', 'b', '3'], ['XXaXXbXX']])
+  " Any non-decimal digit or end-of-line
+  call add(tl, [2, '\_D\+', ['1', 'a', '2', 'b', '3'], ['1XX2XX3XX']])
+  " Any hexadecimal digit or end-of-line
+  call add(tl, [2, '\_x\+', ['1', 'a', 'g', '9', '8'], ['XXgXX']])
+  " Any non-hexadecimal digit or end-of-line
+  call add(tl, [2, '\_X\+', ['1', 'a', 'g', '9', '8'], ['1XXaXX9XX8XX']])
+  " Any octal digit or end-of-line
+  call add(tl, [2, '\_o\+', ['0', '7', '8', '9', '0'], ['XX8XX9XX']])
+  " Any non-octal digit or end-of-line
+  call add(tl, [2, '\_O\+', ['0', '7', '8', '9', '0'], ['0XX7XX0XX']])
+  " Any word character or end-of-line
+  call add(tl, [2, '\_w\+', ['A', 'B', '=', 'C', 'D'], ['XX=XX']])
+  " Any non-word character or end-of-line
+  call add(tl, [2, '\_W\+', ['A', 'B', '=', 'C', 'D'], ['AXXBXXCXXDXX']])
+  " Any head-of-word character or end-of-line
+  call add(tl, [2, '\_h\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']])
+  " Any non-head-of-word character or end-of-line
+  call add(tl, [2, '\_H\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']])
+  " Any alphabetic character or end-of-line
+  call add(tl, [2, '\_a\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']])
+  " Any non-alphabetic character or end-of-line
+  call add(tl, [2, '\_A\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']])
+  " Any lowercase character or end-of-line
+  call add(tl, [2, '\_l\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
+  " Any non-lowercase character or end-of-line
+  call add(tl, [2, '\_L\+', ['a', 'A', 'b', 'B'], ['aXXbXX']])
+  " Any uppercase character or end-of-line
+  call add(tl, [2, '\_u\+', ['a', 'A', 'b', 'B'], ['aXXbXX']])
+  " Any non-uppercase character or end-of-line
+  call add(tl, [2, '\_U\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
+  " Collection or end-of-line
+  call add(tl, [2, '\_[a-z]\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
+  " start of line anywhere in the text
+  call add(tl, [2, 'one\zs\_s*\_^\zetwo',
+        \ ['', 'one', ' two', 'one', '', 'two'],
+        \ ['', 'one', ' two', 'oneXXtwo']])
+  " end of line anywhere in the text
+  call add(tl, [2, 'one\zs\_$\_s*two',
+        \ ['', 'one', ' two', 'one', '', 'two'], ['', 'oneXX', 'oneXX']])
+
   " Check that \_[0-9] matching EOL does not break a following \>
   call add(tl, [2, '\<\(\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\.\)\{3\}\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\>', ['', 'localnet/192.168.0.1', ''], ['', 'localnet/XX', '']])
 
@@ -674,7 +754,7 @@ func Test_regexp_multiline_pat()
     let before = t[2]
     let after = t[3]
     for engine in [0, 1, 2]
-      if engine == 2 && re == 0 || engine == 1 && re ==1
+      if engine == 2 && re == 0 || engine == 1 && re == 1
         continue
       endif
       let &regexpengine = engine
@@ -722,9 +802,8 @@ func Test_lookbehind_across_line()
   bwipe!
 endfunc
 
-" Check matching Visual area
-func Test_matching_visual_area()
-  new
+" Test for the \%V atom (match inside the visual area)
+func Regex_Match_Visual_Area()
   call append(0, ['Visual:', 'thexe the thexethe', 'andaxand andaxand',
         \ 'oooxofor foroxooo', 'oooxofor foroxooo'])
   call cursor(1, 1)
@@ -733,12 +812,22 @@ func Test_matching_visual_area()
   exe "normal jfx\<C-V>fxj:s/\\%Vo/O/g\<CR>"
   call assert_equal(['Visual:', 'thexE thE thExethe', 'AndAxAnd AndAxAnd',
         \ 'oooxOfOr fOrOxooo', 'oooxOfOr fOrOxooo', ''], getline(1, '$'))
+  %d
+endfunc
+
+" Check matching Visual area
+func Test_matching_visual_area()
+  new
+  set regexpengine=1
+  call Regex_Match_Visual_Area()
+  set regexpengine=2
+  call Regex_Match_Visual_Area()
+  set regexpengine&
   bwipe!
 endfunc
 
 " Check matching marks
-func Test_matching_marks()
-  new
+func Regex_Mark()
   call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas',
         \ 'dfsadfEasdf', '', '', '', '', ''])
   call cursor(4, 1)
@@ -746,6 +835,15 @@ func Test_matching_marks()
   exe "normal jfSmsj0fEme:.-4,.+6s/.\\%>'s\\_.*\\%<'e../again/\<CR>"
   call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf',
         \ '', '', '', '', '', ''], getline(1, '$'))
+  %d
+endfunc
+
+func Test_matching_marks()
+  new
+  set regexpengine=1
+  call Regex_Mark()
+  set regexpengine=2
+  call Regex_Mark()
   bwipe!
 endfunc
 
@@ -786,8 +884,7 @@ func Test_matching_curpos()
 endfunc
 
 " Test for matching the start and end of a buffer
-func Test_start_end_of_buffer_match()
-  new
+func Regex_start_end_buffer()
   call setline(1, repeat(['vim edit'], 20))
   /\%^
   call assert_equal([0, 1, 1, 0], getpos('.'))
@@ -797,15 +894,34 @@ func Test_start_end_of_buffer_match()
   call assert_equal([0, 20, 8, 0], getpos('.'))
   exe "normal 6gg/..\\%$\<CR>"
   call assert_equal([0, 20, 7, 0], getpos('.'))
+  %d
+endfunc
+
+func Test_start_end_of_buffer_match()
+  new
+  set regexpengine=1
+  call Regex_start_end_buffer()
+  set regexpengine=2
+  call Regex_start_end_buffer()
   bwipe!
 endfunc
 
 " Check for detecting error
 func Test_regexp_error()
-  set regexpengine=2
-  call assert_fails("call matchlist('x x', ' \\ze*')", 'E888:')
-  call assert_fails("call matchlist('x x', ' \\zs*')", 'E888:')
-  set re&
+  call assert_fails("call matchlist('x x', '\\%#=1 \\zs*')", 'E888:')
+  call assert_fails("call matchlist('x x', '\\%#=1 \\ze*')", 'E888:')
+  call assert_fails("call matchlist('x x', '\\%#=2 \\zs*')", 'E888:')
+  call assert_fails("call matchlist('x x', '\\%#=2 \\ze*')", 'E888:')
+  call assert_fails('exe "normal /\\%#=1\\%[x\\%[x]]\<CR>"', 'E369:')
+endfunc
+
+" Test for using the last substitute string pattern (~)
+func Test_regexp_last_subst_string()
+  new
+  s/bar/baz/e
+  call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=1\~"), "baz")
+  call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=2\~"), "baz")
+  close!
 endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/testdir/test_search.vim
+++ b/src/testdir/test_search.vim
@@ -688,9 +688,7 @@ func Test_search_cmdline8()
 endfunc
 
 " Tests for regexp with various magic settings
-func Test_search_regexp()
-  enew!
-
+func Run_search_regexp_magic_opt()
   put ='1 a aa abb abbccc'
   exe 'normal! /a*b\{2}c\+/e' . "\<CR>"
   call assert_equal([0, 2, 17, 0], getpos('.'))
@@ -725,6 +723,18 @@ func Test_search_regexp()
   exe 'normal! /\V[ab]\(\[xy]\)\1' . "\<CR>"
   call assert_equal([0, 9, 7, 0], getpos('.'))
 
+  %d
+endfunc
+
+func Test_search_regexp()
+  enew!
+
+  set regexpengine=1
+  call Run_search_regexp_magic_opt()
+  set regexpengine=2
+  call Run_search_regexp_magic_opt()
+  set regexpengine&
+
   set undolevels=100
   put ='9 foobar'
   put =''
@@ -732,12 +742,12 @@ func Test_search_regexp()
   normal G
   exe 'normal! dv?bar?' . "\<CR>"
   call assert_equal('9 foo', getline('.'))
-  call assert_equal([0, 10, 5, 0], getpos('.'))
-  call assert_equal(10, line('$'))
+  call assert_equal([0, 2, 5, 0], getpos('.'))
+  call assert_equal(2, line('$'))
   normal u
   call assert_equal('9 foobar', getline('.'))
-  call assert_equal([0, 10, 6, 0], getpos('.'))
-  call assert_equal(11, line('$'))
+  call assert_equal([0, 2, 6, 0], getpos('.'))
+  call assert_equal(3, line('$'))
 
   set undolevels&
   enew!
@@ -1547,8 +1557,12 @@ endfunc
 func Test_invalid_regexp()
   set regexpengine=1
   call assert_fails("call search(repeat('\\(.\\)', 10))", 'E51:')
+  call assert_fails("call search('\\%(')", 'E53:')
+  call assert_fails("call search('\\(')", 'E54:')
+  call assert_fails("call search('\\)')", 'E55:')
+  call assert_fails("call search('x\\@#')", 'E59:')
+  call assert_fails('call search(''\v%(%(%(%(%(%(%(%(%(%(%(a){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}'')', 'E60:')
   call assert_fails("call search('a\\+*')", 'E61:')
-  call assert_fails("call search('x\\@#')", 'E59:')
   call assert_fails("call search('\\_m')", 'E63:')
   call assert_fails("call search('\\+')", 'E64:')
   call assert_fails("call search('\\1')", 'E65:')
@@ -1573,6 +1587,7 @@ func Test_invalid_regexp()
   call assert_fails("call search('\\)')", 'E55:')
   call assert_fails("call search('\\z\\(\\)')", 'E66:')
   call assert_fails("call search('\\%[ab')", 'E69:')
+  call assert_fails("call search('\\%[]')", 'E70:')
   call assert_fails("call search('\\%9999999999999999999999999999v')", 'E951:')
   set regexpengine&
   call assert_fails("call search('\\%#=3ab')", 'E864:')
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    535,
+/**/
     534,
 /**/
     533,