Skip to content

Instantly share code, notes, and snippets.

@KevM
Created November 7, 2011 22:57
Show Gist options
  • Select an option

  • Save KevM/1346468 to your computer and use it in GitHub Desktop.

Select an option

Save KevM/1346468 to your computer and use it in GitHub Desktop.
Regular Expression with a timeout
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
};
}
}
[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