RegExpTests.cs 4.7 KB

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