RegExpTests.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System.Text.RegularExpressions;
  2. using Jint.Native;
  3. using Jint.Native.Array;
  4. namespace Jint.Tests.Runtime;
  5. public class RegExpTests
  6. {
  7. private const string TestRegex = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w\\.-]*)*\\/?$";
  8. private const string TestedValue = "https://archiverbx.blob.core.windows.net/static/C:/Users/USR/Documents/Projects/PROJ/static/images/full/1234567890.jpg";
  9. [Fact]
  10. public void CanNotBreakEngineWithLongRunningMatch()
  11. {
  12. var engine = new Engine(e => e.RegexTimeoutInterval(TimeSpan.FromSeconds(1)));
  13. Assert.Throws<RegexMatchTimeoutException>(() =>
  14. {
  15. engine.Execute($"'{TestedValue}'.match(/{TestRegex}/)");
  16. });
  17. }
  18. [Fact]
  19. public void CanNotBreakEngineWithLongRunningRegExp()
  20. {
  21. var engine = new Engine(e => e.RegexTimeoutInterval(TimeSpan.FromSeconds(1)));
  22. Assert.Throws<RegexMatchTimeoutException>(() =>
  23. {
  24. engine.Execute($"'{TestedValue}'.match(new RegExp(/{TestRegex}/))");
  25. });
  26. }
  27. [Fact]
  28. public void PreventsInfiniteLoop()
  29. {
  30. var engine = new Engine();
  31. var result = (ArrayInstance) engine.Evaluate("'x'.match(/|/g);");
  32. Assert.Equal((uint) 2, result.Length);
  33. Assert.Equal("", result[0]);
  34. Assert.Equal("", result[1]);
  35. }
  36. [Fact]
  37. public void ToStringWithNonRegExpInstanceAndMissingProperties()
  38. {
  39. var engine = new Engine();
  40. var result = engine.Evaluate("/./['toString'].call({})").AsString();
  41. Assert.Equal("/undefined/undefined", result);
  42. }
  43. [Fact]
  44. public void ToStringWithNonRegExpInstanceAndValidProperties()
  45. {
  46. var engine = new Engine();
  47. var result = engine.Evaluate("/./['toString'].call({ source: 'a', flags: 'b' })").AsString();
  48. Assert.Equal("/a/b", result);
  49. }
  50. [Fact]
  51. public void MatchAllIteratorReturnsCorrectNumberOfElements()
  52. {
  53. var engine = new Engine();
  54. var result = engine.Evaluate("[...'one two three'.matchAll(/t/g)].length").AsInteger();
  55. Assert.Equal(2, result);
  56. }
  57. [Fact]
  58. public void ToStringWithRealRegExpInstance()
  59. {
  60. var engine = new Engine();
  61. var result = engine.Evaluate("/./['toString'].call(/test/g)").AsString();
  62. Assert.Equal("/test/g", result);
  63. }
  64. [Fact]
  65. public void ShouldNotThrowErrorOnIncompatibleRegex()
  66. {
  67. var engine = new Engine();
  68. Assert.NotNull(engine.Evaluate(@"/[^]*?(:[rp][el]a[\w-]+)[^]*/"));
  69. Assert.NotNull(engine.Evaluate("/[^]a/"));
  70. Assert.NotNull(engine.Evaluate("new RegExp('[^]a')"));
  71. Assert.NotNull(engine.Evaluate("/[]/"));
  72. Assert.NotNull(engine.Evaluate("new RegExp('[]')"));
  73. }
  74. [Fact]
  75. public void ShouldNotThrowErrorOnRegExNumericNegation()
  76. {
  77. var engine = new Engine();
  78. Assert.True(ReferenceEquals(JsNumber.DoubleNaN, engine.Evaluate("-/[]/")));
  79. }
  80. [Fact]
  81. public void ShouldProduceCorrectSourceForSlashEscapes()
  82. {
  83. var engine = new Engine();
  84. var source = engine.Evaluate(@"/\/\//.source");
  85. Assert.Equal("\\/\\/", source);
  86. }
  87. [Theory]
  88. [InlineData("", "/()/ug", new[] { "" }, new[] { 0 })]
  89. [InlineData("💩", "/()/ug", new[] { "", "" }, new[] { 0, 2 })]
  90. [InlineData("ᴜⁿᵢ𝒸ₒᵈₑ is a 💩", "/i?/ug",
  91. new[] { "", "", "", "", "", "", "", "", "i", "", "", "", "", "", "" },
  92. new[] { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16 })]
  93. public void ShouldNotMatchEmptyStringsWithinSurrogatePairsInUnicodeMode(string input, string pattern, string[] expectedCaptures, int[] expectedIndices)
  94. {
  95. var engine = new Engine();
  96. var matches = engine.Evaluate($"[...'{input}'.matchAll({pattern})]").AsArray();
  97. Assert.Equal((ulong) expectedCaptures.Length, matches.Length);
  98. Assert.Equal(expectedCaptures, matches.Select((m, i) => m.Get(0).AsString()));
  99. Assert.Equal(expectedIndices, matches.Select(m => m.Get("index").AsInteger()));
  100. }
  101. [Fact]
  102. public void ShouldAllowProblematicGroupNames()
  103. {
  104. var engine = new Engine();
  105. var match = engine.Evaluate("'abc'.match(/(?<$group>b)/)").AsArray();
  106. var groups = match.Get("groups").AsObject();
  107. Assert.Equal(new[] { "$group" }, groups.GetOwnPropertyKeys().Select(k => k.AsString()));
  108. Assert.Equal("b", groups["$group"]);
  109. var result = engine.Evaluate("'abc'.replace(/(?<$group>b)/g, '-$<$group>-')").AsString();
  110. Assert.Equal("a-b-c", result);
  111. }
  112. [Fact]
  113. public void Issue506()
  114. {
  115. var engine = new Engine();
  116. var result = engine.Evaluate("/[^]?(:[rp][el]a[\\w-]+)[^]/.test(':reagent-')").AsBoolean();
  117. Assert.True(result);
  118. }
  119. }