LimitedRegexCharSequence implements CharSequence { public char charAt(int index) { accessCount++; if (stopwatch.elapsed(TimeUnit.MILLISECONDS) > timeoutMillis) { throw new RegexTimeoutException("Timeout occurred after " + timeoutMillis + "ms"); } return inner.charAt(index); } LimitedRegexCharSequence(CharSequence inner, int timeoutMillis);   LimitedRegexCharSequence(CharSequence inner, int timeoutMillis, Ticker ticker); char charAt(int index); int length(); CharSequence subSequence(int start, int end); @Override @NotNull String toString();  }
@Test public void testCharAt() { LimitedRegexCharSequence lrcs = new LimitedRegexCharSequence(simpleString, 1000); Assert.assertEquals(lrcs.charAt(18), 'i'); Assert.assertEquals(lrcs.charAt(3), 's'); }
@Test(expected = LimitedRegexCharSequence.RegexTimeoutException.class) public void testAccessDoesTimeout() { TestTicker ticker = new TestTicker(); LimitedRegexCharSequence lrcs = new LimitedRegexCharSequence(simpleString, 100, ticker); ticker.setElapsed(TimeUnit.NANOSECONDS.convert(101, TimeUnit.MILLISECONDS)); lrcs.charAt(0); }