|
3 | 3 |
|
4 | 4 | using System.Collections.Generic; |
5 | 5 | using System.Globalization; |
| 6 | +using System.IO; |
6 | 7 | using System.Linq; |
| 8 | +using System.Text.Json; |
7 | 9 | using System.Threading.Tasks; |
8 | 10 | using Xunit; |
9 | 11 |
|
@@ -1405,5 +1407,58 @@ public void TerminationInNonBacktrackingVsBackTracking(RegexOptions options, int |
1405 | 1407 | // NonBacktracking needs way less than 1s |
1406 | 1408 | Assert.False(re.Match(input).Success); |
1407 | 1409 | } |
| 1410 | + |
| 1411 | + // |
| 1412 | + // dotnet/runtime-assets contains a set a regular expressions sourced from |
| 1413 | + // permissively-licensed packages. Validate Regex behavior with those expressions. |
| 1414 | + // |
| 1415 | + |
| 1416 | + [Theory] |
| 1417 | + [InlineData(RegexEngine.Interpreter)] |
| 1418 | + [InlineData(RegexEngine.Compiled)] |
| 1419 | + public void PatternsDataSet_ConstructRegexForAll(RegexEngine engine) |
| 1420 | + { |
| 1421 | + Parallel.ForEach(s_patternsDataSet.Value, r => |
| 1422 | + { |
| 1423 | + try |
| 1424 | + { |
| 1425 | + RegexHelpers.GetRegexAsync(engine, r.Pattern, r.Options).GetAwaiter().GetResult(); |
| 1426 | + } |
| 1427 | + catch (Exception e) when (RegexHelpers.IsNonBacktracking(engine) && e.Message.Contains("NonBacktracking")) |
| 1428 | + { |
| 1429 | + // Some tests aren't supported with RegexOptions.NonBacktracking. |
| 1430 | + } |
| 1431 | + }); |
| 1432 | + } |
| 1433 | + |
| 1434 | + [OuterLoop("Takes many seconds")] |
| 1435 | + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "NonBacktracking isn't supported on .NET Framework")] |
| 1436 | + [Fact] |
| 1437 | + public void PatternsDataSet_ConstructRegexForAll_NonBacktracking() => |
| 1438 | + PatternsDataSet_ConstructRegexForAll(RegexEngine.NonBacktracking); |
| 1439 | + |
| 1440 | + [OuterLoop("Takes minutes to generate and compile thousands of expressions")] |
| 1441 | + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Source generator isn't supported on .NET Framework")] |
| 1442 | + [Fact] |
| 1443 | + public void PatternsDataSet_ConstructRegexForAll_SourceGenerated() => |
| 1444 | + PatternsDataSet_ConstructRegexForAll(RegexEngine.SourceGenerated); |
| 1445 | + |
| 1446 | + private static Lazy<DataSetExpression[]> s_patternsDataSet = new Lazy<DataSetExpression[]>(() => |
| 1447 | + { |
| 1448 | + using Stream json = File.OpenRead("Regex_RealWorldPatterns.json"); |
| 1449 | + return JsonSerializer.Deserialize<DataSetExpression[]>(json, new JsonSerializerOptions() { ReadCommentHandling = JsonCommentHandling.Skip }).Distinct().ToArray(); |
| 1450 | + }); |
| 1451 | + |
| 1452 | + private sealed class DataSetExpression : IEquatable<DataSetExpression> |
| 1453 | + { |
| 1454 | + public int Count { get; set; } |
| 1455 | + public RegexOptions Options { get; set; } |
| 1456 | + public string Pattern { get; set; } |
| 1457 | + |
| 1458 | + public bool Equals(DataSetExpression? other) => |
| 1459 | + other is not null && |
| 1460 | + other.Pattern == Pattern && |
| 1461 | + (Options & ~RegexOptions.Compiled) == (other.Options & ~RegexOptions.Compiled); // Compiled doesn't affect semantics, so remove it from equality for our purposes |
| 1462 | + } |
1408 | 1463 | } |
1409 | 1464 | } |
0 commit comments