Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
using System;
using Xunit;

namespace Platform.RegularExpressions.Transformer.Tests
{
/// <summary>
/// <para>
/// Represents the regex engine tests.
/// </para>
/// <para></para>
/// </summary>
public class RegexEngineTests
{
/// <summary>
/// <para>
/// Tests that system regex engine creates patterns correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SystemRegexEngine_CreatePattern_Test()
{
var engine = new SystemRegexEngine();
var pattern = engine.CreatePattern(@"hello\s+world");

Assert.NotNull(pattern);
Assert.Equal(@"hello\s+world", pattern.Pattern);
Assert.Equal("System.Text.RegularExpressions", engine.Name);
Assert.True(pattern.IsMatch("hello world"));
Assert.True(pattern.IsMatch("hello world"));
Assert.False(pattern.IsMatch("helloworld"));
}

/// <summary>
/// <para>
/// Tests that PCRE regex engine creates patterns correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void PcreRegexEngine_CreatePattern_Test()
{
var engine = new PcreRegexEngine();
var pattern = engine.CreatePattern(@"hello\s+world");

Assert.NotNull(pattern);
Assert.Equal(@"hello\s+world", pattern.Pattern);
Assert.Equal("PCRE2", engine.Name);
Assert.True(pattern.IsMatch("hello world"));
Assert.True(pattern.IsMatch("hello world"));
Assert.False(pattern.IsMatch("helloworld"));
}

/// <summary>
/// <para>
/// Tests that system regex engine creates patterns with timeout correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SystemRegexEngine_CreatePatternWithTimeout_Test()
{
var engine = new SystemRegexEngine();
var timeout = TimeSpan.FromSeconds(30);
var pattern = engine.CreatePattern(@"test", timeout);

Assert.NotNull(pattern);
Assert.Equal(@"test", pattern.Pattern);
Assert.Equal(timeout, pattern.MatchTimeout);
}

/// <summary>
/// <para>
/// Tests that PCRE regex engine creates patterns with timeout correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void PcreRegexEngine_CreatePatternWithTimeout_Test()
{
var engine = new PcreRegexEngine();
var timeout = TimeSpan.FromSeconds(30);
var pattern = engine.CreatePattern(@"test", timeout);

Assert.NotNull(pattern);
Assert.Equal(@"test", pattern.Pattern);
Assert.Equal(timeout, pattern.MatchTimeout);
}

/// <summary>
/// <para>
/// Tests that regex engine factory creates engines correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void RegexEngineFactory_CreateEngine_Test()
{
var systemEngine = RegexEngineFactory.CreateEngine(RegexEngineType.SystemRegex);
var pcreEngine = RegexEngineFactory.CreateEngine(RegexEngineType.PCRE2);

Assert.IsType<SystemRegexEngine>(systemEngine);
Assert.IsType<PcreRegexEngine>(pcreEngine);
Assert.Equal("System.Text.RegularExpressions", systemEngine.Name);
Assert.Equal("PCRE2", pcreEngine.Name);
}

/// <summary>
/// <para>
/// Tests that default engine setting works correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void RegexEngineFactory_DefaultEngine_Test()
{
// Save original default
var originalDefault = RegexEngineFactory.DefaultEngine;

try
{
// Test setting PCRE2 as default
RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
Assert.IsType<PcreRegexEngine>(RegexEngineFactory.DefaultEngine);
Assert.Equal(RegexEngineType.PCRE2, RegexEngineFactory.GetDefaultEngineType());

// Test setting System as default
RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
Assert.IsType<SystemRegexEngine>(RegexEngineFactory.DefaultEngine);
Assert.Equal(RegexEngineType.SystemRegex, RegexEngineFactory.GetDefaultEngineType());
}
finally
{
// Restore original default
RegexEngineFactory.DefaultEngine = originalDefault;
}
}

/// <summary>
/// <para>
/// Tests that pattern replacement works correctly with both engines.
/// </para>
/// <para></para>
/// </summary>
[Theory]
[InlineData(typeof(SystemRegexEngine))]
[InlineData(typeof(PcreRegexEngine))]
public void RegexPattern_Replace_Test(Type engineType)
{
var engine = (IRegexEngine)Activator.CreateInstance(engineType)!;
var pattern = engine.CreatePattern(@"\b\d{4}\b");

var input = "The year 2024 was amazing, unlike 2023.";
var result = pattern.Replace(input, "XXXX");

Assert.Equal("The year XXXX was amazing, unlike XXXX.", result);
}

/// <summary>
/// <para>
/// Tests that pattern WithTimeout works correctly.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void RegexPattern_WithTimeout_Test()
{
var engine = new SystemRegexEngine();
var pattern = engine.CreatePattern(@"test");
var newTimeout = TimeSpan.FromMinutes(2);

var newPattern = pattern.WithTimeout(newTimeout);

Assert.NotEqual(pattern.MatchTimeout, newPattern.MatchTimeout);
Assert.Equal(newTimeout, newPattern.MatchTimeout);
Assert.Equal(pattern.Pattern, newPattern.Pattern);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
using System;
using System.Text.RegularExpressions;
using Xunit;

namespace Platform.RegularExpressions.Transformer.Tests
{
/// <summary>
/// <para>
/// Represents the substitution rule engine tests.
/// </para>
/// <para></para>
/// </summary>
public class SubstitutionRuleEngineTests
{
/// <summary>
/// <para>
/// Tests that SubstitutionRule works with SystemRegex engine.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SubstitutionRule_SystemRegexEngine_Test()
{
var engine = new SystemRegexEngine();
var pattern = engine.CreatePattern(@"hello");
var rule = new SubstitutionRule(pattern, "hi");

Assert.NotNull(rule.MatchPattern);
Assert.Equal("hello", rule.MatchPattern.Pattern);
Assert.Equal("hi", rule.SubstitutionPattern);
Assert.IsType<SystemRegexPattern>(rule.MatchPattern);
}

/// <summary>
/// <para>
/// Tests that SubstitutionRule works with PCRE2 engine.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SubstitutionRule_PcreEngine_Test()
{
var engine = new PcreRegexEngine();
var pattern = engine.CreatePattern(@"hello");
var rule = new SubstitutionRule(pattern, "hi");

Assert.NotNull(rule.MatchPattern);
Assert.Equal("hello", rule.MatchPattern.Pattern);
Assert.Equal("hi", rule.SubstitutionPattern);
Assert.IsType<PcreRegexPattern>(rule.MatchPattern);
}

/// <summary>
/// <para>
/// Tests that SubstitutionRule implicit conversion uses default engine.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SubstitutionRule_ImplicitConversion_UsesDefaultEngine_Test()
{
// Save original default
var originalDefault = RegexEngineFactory.DefaultEngine;

try
{
// Test with System regex as default
RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
SubstitutionRule rule1 = ("hello", "hi");
Assert.IsType<SystemRegexPattern>(rule1.MatchPattern);

// Test with PCRE2 as default
RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
SubstitutionRule rule2 = ("hello", "hi");
Assert.IsType<PcreRegexPattern>(rule2.MatchPattern);
}
finally
{
// Restore original default
RegexEngineFactory.DefaultEngine = originalDefault;
}
}

/// <summary>
/// <para>
/// Tests that legacy Regex constructor still works.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SubstitutionRule_LegacyRegexConstructor_Test()
{
var regex = new Regex("hello");
var rule = new SubstitutionRule(regex, "hi");

Assert.NotNull(rule.MatchPattern);
Assert.Equal("hello", rule.MatchPattern.Pattern);
Assert.Equal("hi", rule.SubstitutionPattern);
Assert.NotNull(rule.LegacyMatchPattern);
Assert.Equal("hello", rule.LegacyMatchPattern.ToString());
}

/// <summary>
/// <para>
/// Tests backward compatibility through LegacyMatchPattern property.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void SubstitutionRule_LegacyMatchPattern_BackwardCompatibility_Test()
{
// Test with SystemRegexPattern
var systemEngine = new SystemRegexEngine();
var systemPattern = systemEngine.CreatePattern(@"test");
var systemRule = new SubstitutionRule(systemPattern, "replacement");

Assert.NotNull(systemRule.LegacyMatchPattern);
Assert.IsType<Regex>(systemRule.LegacyMatchPattern);
Assert.Equal("test", systemRule.LegacyMatchPattern.ToString());

// Test with PcreRegexPattern
var pcreEngine = new PcreRegexEngine();
var pcrePattern = pcreEngine.CreatePattern(@"test");
var pcreRule = new SubstitutionRule(pcrePattern, "replacement");

Assert.NotNull(pcreRule.LegacyMatchPattern);
Assert.IsType<Regex>(pcreRule.LegacyMatchPattern);
Assert.Equal("test", pcreRule.LegacyMatchPattern.ToString());
}

/// <summary>
/// <para>
/// Tests that TextTransformer works with different regex engines.
/// </para>
/// <para></para>
/// </summary>
[Theory]
[InlineData(typeof(SystemRegexEngine))]
[InlineData(typeof(PcreRegexEngine))]
public void TextTransformer_WithDifferentEngines_Test(Type engineType)
{
var engine = (IRegexEngine)Activator.CreateInstance(engineType)!;
var pattern = engine.CreatePattern(@"\b\d{4}\b");
var rule = new SubstitutionRule(pattern, "YEAR");

var transformer = new TextTransformer(new[] { rule });
var input = "In 2024, we had great success.";
var result = transformer.Transform(input);

Assert.Equal("In YEAR, we had great success.", result);
}

/// <summary>
/// <para>
/// Tests that both engines produce equivalent results for common patterns.
/// </para>
/// <para></para>
/// </summary>
[Theory]
[InlineData(@"\d+", "abc123def", "XXX", "abcXXXdef")]
[InlineData(@"\s+", "hello world", "_", "hello_world")]
[InlineData(@"[A-Z]+", "Hello WORLD Test", "***", "***ello *** ***est")]
public void BothEngines_ProduceEquivalentResults_Test(string pattern, string input, string replacement, string expected)
{
var systemEngine = new SystemRegexEngine();
var pcreEngine = new PcreRegexEngine();

var systemPattern = systemEngine.CreatePattern(pattern);
var pcrePattern = pcreEngine.CreatePattern(pattern);

var systemResult = systemPattern.Replace(input, replacement);
var pcreResult = pcrePattern.Replace(input, replacement);

Assert.Equal(expected, systemResult);
Assert.Equal(expected, pcreResult);
Assert.Equal(systemResult, pcreResult);
}

/// <summary>
/// <para>
/// Tests that engine switching works correctly during runtime.
/// </para>
/// <para></para>
/// </summary>
[Fact]
public void RegexEngine_SwitchingDuringRuntime_Test()
{
// Save original default
var originalDefault = RegexEngineFactory.DefaultEngine;

try
{
// Create rules with specific engines to demonstrate both engines work
var systemEngine = new SystemRegexEngine();
var pcreEngine = new PcreRegexEngine();

var rule1 = new SubstitutionRule(systemEngine.CreatePattern(@"\d+"), "123");
var rule2 = new SubstitutionRule(pcreEngine.CreatePattern(@"[A-Z]"), "X");

var transformer = new TextTransformer(new[] { rule1, rule2 });
var result = transformer.Transform("A1B2C");

// The rules are applied sequentially, so "A1B2C" becomes:
// 1. rule1 applies: "A1B2C" -> "A123B123C" (1,2 -> 123)
// 2. rule2 applies: "A123B123C" -> "X123X123X" (A,B,C -> X)
Assert.Equal("X123X123X", result);
}
finally
{
// Restore original default
RegexEngineFactory.DefaultEngine = originalDefault;
}
}
}
}
Loading
Loading