@@ -11,15 +11,11 @@ namespace System.Text.RegularExpressions.Tests
1111 public partial class RegexParserTests
1212 {
1313 [ Theory ]
14- [ InlineData ( @"[a-\-]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
15- [ InlineData ( @"[a-\-b]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
16- [ InlineData ( @"[a-\-\-b]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
17- [ InlineData ( @"[a-\-\D]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
18- [ InlineData ( @"[a-\-\-\D]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
19- [ InlineData ( @"[a -\-\b]" , RegexOptions . None , null , 5 ) ]
20- // OutOfMemoryException
14+
15+ // Avoid OutOfMemoryException
2116 [ InlineData ( "a{2147483647}" , RegexOptions . None , null ) ]
2217 [ InlineData ( "a{2147483647,}" , RegexOptions . None , null ) ]
18+
2319 [ InlineData ( @"(?(?N))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
2420 [ InlineData ( @"(?(?i))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
2521 [ InlineData ( @"(?(?I))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
@@ -30,7 +26,6 @@ public partial class RegexParserTests
3026 [ InlineData ( @"(?(?X))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
3127 [ InlineData ( @"(?(?n))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
3228 [ InlineData ( @"(?(?m))" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 5 ) ]
33- // IndexOutOfRangeException
3429 [ InlineData ( "(?<-" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
3530 [ InlineData ( "(?<-" , RegexOptions . IgnorePatternWhitespace , RegexParseError . InvalidGroupingConstruct , 3 ) ]
3631 [ InlineData ( @"^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$" , RegexOptions . None , null ) ]
@@ -90,8 +85,50 @@ public partial class RegexParserTests
9085 [ InlineData ( "a{0,2147483648}" , RegexOptions . None , RegexParseError . QuantifierOrCaptureGroupOutOfRange , 14 ) ]
9186 // Surrogate pair which is parsed as [char,char-char,char] as we operate on UTF-16 code units.
9287 [ InlineData ( "[\uD82F \uDCA0 -\uD82F \uDCA3 ]" , RegexOptions . IgnoreCase , RegexParseError . ReversedCharacterRange , 5 ) ]
88+
89+ // Following are borrowed from Rust regex tests ============
90+ // https://github.com/rust-lang/regex/blob/master/tests/noparse.rs
91+ [ InlineData ( @"*" , RegexOptions . None , RegexParseError . QuantifierAfterNothing , 1 ) ]
92+ [ InlineData ( @"[A-" , RegexOptions . None , RegexParseError . UnterminatedBracket , 3 ) ]
93+ [ InlineData ( @"[A" , RegexOptions . None , RegexParseError . UnterminatedBracket , 2 ) ]
94+ [ InlineData ( @"[\A]" , RegexOptions . None , RegexParseError . UnrecognizedEscape , 3 ) ]
95+ [ InlineData ( @"[\z]" , RegexOptions . None , RegexParseError . UnrecognizedEscape , 3 ) ]
96+ [ InlineData ( @"(" , RegexOptions . None , RegexParseError . InsufficientClosingParentheses , 1 ) ]
97+ [ InlineData ( @")" , RegexOptions . None , RegexParseError . InsufficientOpeningParentheses , 1 ) ]
98+ [ InlineData ( @"[a-Z]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 4 ) ]
99+ [ InlineData ( @"(?P<>a)" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
100+ [ InlineData ( @"(?P<na-me>)" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
101+ [ InlineData ( @"(?a)a" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
102+ [ InlineData ( @"a{2,1}" , RegexOptions . None , RegexParseError . ReversedQuantifierRange , 6 ) ]
103+ [ InlineData ( @"(?" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 2 ) ]
104+ [ InlineData ( @"\8" , RegexOptions . None , RegexParseError . UndefinedNumberedReference , 2 ) ]
105+ [ InlineData ( @"\xG0" , RegexOptions . None , RegexParseError . InsufficientOrInvalidHexDigits , 3 ) ]
106+ [ InlineData ( @"\xF" , RegexOptions . None , RegexParseError . InsufficientOrInvalidHexDigits , 2 ) ]
107+ [ InlineData ( @"\x{fffg}" , RegexOptions . None , RegexParseError . InsufficientOrInvalidHexDigits , 3 ) ]
108+ [ InlineData ( @"(?a)" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
109+ [ InlineData ( @"(?)" , RegexOptions . None , RegexParseError . QuantifierAfterNothing , 2 ) ]
110+ [ InlineData ( @"(?P<a>.)(?P<a>.)" , RegexOptions . None , RegexParseError . InvalidGroupingConstruct , 3 ) ]
111+ [ InlineData ( @"[a-\A]" , RegexOptions . None , RegexParseError . UnrecognizedEscape , 5 ) ]
112+ [ InlineData ( @"[a-\z]" , RegexOptions . None , RegexParseError . UnrecognizedEscape , 5 ) ]
113+ [ InlineData ( @"[a-\b]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
114+ [ InlineData ( @"[a-\-]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
115+ [ InlineData ( @"[a-\-b]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
116+ [ InlineData ( @"[a-\-\-b]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
117+ [ InlineData ( @"[a-\-\D]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
118+ [ InlineData ( @"[a-\-\-\D]" , RegexOptions . None , RegexParseError . ReversedCharacterRange , 5 ) ]
119+ [ InlineData ( @"[a -\-\b]" , RegexOptions . None , null ) ]
120+ [ InlineData ( @"[\b]" , RegexOptions . None , null ) ] // errors in rust: class_no_boundary
121+ [ InlineData ( @"a{10000000}" , RegexOptions . None , null ) ] // errors in rust: too_big
122+ [ InlineData ( @"a{1001" , RegexOptions . None , null ) ] // errors in rust: counted_no_close
123+ [ InlineData ( @"a{-1,1}" , RegexOptions . None , null ) ] // errors in rust: counted_nonnegative
124+ [ InlineData ( @"\\" , RegexOptions . None , null ) ] // errors in rust: unfinished_escape
125+ [ InlineData ( @"(?-i-i)" , RegexOptions . None , null ) ] // errors in rust: double_neg
126+ [ InlineData ( @"(?i-)" , RegexOptions . None , null ) ] // errors in rust: neg_empty
127+ [ InlineData ( @"[a-[:lower:]]" , RegexOptions . None , null ) ] // errors in rust: range_end_no_class
128+ // End of Rust parser tests ==============
129+
93130 [ SkipOnTargetFramework ( TargetFrameworkMonikers . NetFramework ) ]
94- public void Parse_Netcoreapp ( string pattern , RegexOptions options , object error , int offset = - 1 )
131+ public void Parse_Netcoreapp ( string pattern , RegexOptions options , RegexParseError ? error , int offset = - 1 )
95132 {
96133 Parse ( pattern , options , error , offset ) ;
97134 }
@@ -137,7 +174,7 @@ static partial void Throws(RegexParseError error, int offset, Action action)
137174 return ;
138175 }
139176
140- throw new XunitException ( $ "Expected RegexParseException with error: ( { error } ) -> Actual error: { regexParseError } )") ;
177+ throw new XunitException ( $ "Expected RegexParseException with error { error } offset { offset } -> Actual error: { regexParseError } offset { e . Offset } )") ;
141178 }
142179 catch ( Exception e )
143180 {
@@ -146,5 +183,18 @@ static partial void Throws(RegexParseError error, int offset, Action action)
146183
147184 throw new XunitException ( $ "Expected RegexParseException with error: ({ error } ) -> Actual: No exception thrown") ;
148185 }
186+
187+ /// <summary>
188+ /// Checks that action succeeds or throws either a RegexParseException or an ArgumentException depending on the
189+ // environment and the action.
190+ /// </summary>
191+ /// <param name="action">The action to invoke.</param>
192+ static partial void MayThrow ( Action action )
193+ {
194+ if ( Record . Exception ( action ) is Exception e && e is not RegexParseException )
195+ {
196+ throw new XunitException ( $ "Expected RegexParseException or no exception -> Actual: ({ e } )") ;
197+ }
198+ }
149199 }
150200}
0 commit comments