Created
November 7, 2011 22:57
-
-
Save KevM/1346468 to your computer and use it in GitHub Desktop.
Regular Expression with a timeout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public interface IRegularExpressionEvaluator | |
| { | |
| IMatch Match(Regex expression, string stringToMatch); | |
| } | |
| public class RegularExpressionSettings : DictionaryConvertible | |
| { | |
| public readonly int DefaultTimeoutInSeconds = 30; | |
| public RegularExpressionSettings() | |
| { | |
| TimeoutInSeconds = DefaultTimeoutInSeconds; | |
| } | |
| public double TimeoutInSeconds { get; set; } | |
| } | |
| public interface IMatch | |
| { | |
| int Index { get; } | |
| bool Success { get; } | |
| } | |
| public class ExpressionMatch : IMatch | |
| { | |
| public int Index { get; set; } | |
| public bool Success { get; set; } | |
| } | |
| public class RegularExpressionEvaluator : IRegularExpressionEvaluator | |
| { | |
| private readonly RegularExpressionSettings _settings; | |
| public RegularExpressionEvaluator(RegularExpressionSettings settings) | |
| { | |
| _settings = settings; | |
| } | |
| public IMatch Match(Regex expression, string stringToMatch) | |
| { | |
| var doneEvent = new ManualResetEvent(false); | |
| Match match = null; | |
| ThreadPool.QueueUserWorkItem(s => | |
| { | |
| match = expression.Match(stringToMatch); | |
| doneEvent.Set(); | |
| }, null); | |
| if(doneEvent.WaitOne(TimeSpan.FromSeconds(_settings.TimeoutInSeconds)) == false) | |
| { | |
| throw new ApplicationException("Evaluation of regular expression '{0}' timed out after {1} seconds for this input: {2}".ToFormat(expression.ToString(),_settings.TimeoutInSeconds, stringToMatch)); | |
| } | |
| return new ExpressionMatch | |
| { | |
| Index = match.Index, | |
| Success = match.Success | |
| }; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [TestFixture] | |
| public class regular_expression_evaluator : Context<RegularExpressionEvaluator> | |
| { | |
| public override void OverrideMocks() | |
| { | |
| Override(new RegularExpressionSettings { TimeoutInSeconds = .2 }); | |
| } | |
| [Test] | |
| public void should_throw_when_expression_evaluation_exceeds_timeout() | |
| { | |
| var expression = new Regex("(x+x+)+y", RegexOptions.IgnoreCase); | |
| const string stringToMatch = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; | |
| typeof(ApplicationException).ShouldBeThrownBy(()=>_cut.Match(expression, stringToMatch)).Message.ShouldContain("timed out after"); | |
| } | |
| [Test] | |
| public void should_return_match() | |
| { | |
| var expression = new Regex("(x+x+)+y", RegexOptions.IgnoreCase); | |
| const string stringToMatch = "xxxy"; | |
| var result = _cut.Match(expression, stringToMatch); | |
| result.Success.ShouldBeTrue(); | |
| result.Index.ShouldEqual(0); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment