Profiler { public static Parser on(Parser source, Consumer<Profile> consumer) { Map<Parser, ProfileBuilder> builders = new LinkedHashMap<>(); return Mirror.of(source).transform(parser -> { ProfileBuilder builder = new ProfileBuilder(parser); builders.put(parser, builder); return parser.callCC((continuation, context) -> { builder.start(); Result result = continuation.apply(context); builder.stop(); return result; }); }).callCC((continuation, context) -> { builders.values().forEach(ProfileBuilder::reset); Result result = continuation.apply(context); builders.values().stream().map(ProfileBuilder::build).forEach(consumer); return result; }); } private  Profiler(); static Parser on(Parser source, Consumer<Profile> consumer);  }
@Test public void testSuccessfulProfile() { List<Profiler.Profile> actual = new ArrayList<>(); Result result = Profiler.on(ExamplesTest.IDENTIFIER, actual::add).parse("ab123"); assertTrue(result.isSuccess()); assertEquals(5, actual.size()); assertEquals("FlattenParser", actual.get(0).parser.toString()); assertEquals(1, actual.get(0).activationCount); assertTrue(actual.get(0).elapsedNanoseconds > 0); assertEquals("SequenceParser", actual.get(1).parser.toString()); assertEquals(1, actual.get(1).activationCount); assertTrue(actual.get(1).elapsedNanoseconds > 0); assertEquals("PossessiveRepeatingParser[0..*]", actual.get(2).parser.toString()); assertEquals(1, actual.get(2).activationCount); assertTrue(actual.get(2).elapsedNanoseconds > 0); assertEquals("CharacterParser[letter or digit expected]", actual.get(3).parser.toString()); assertEquals(5, actual.get(3).activationCount); assertTrue(actual.get(3).elapsedNanoseconds > 0); assertEquals("CharacterParser[letter expected]", actual.get(4).parser.toString()); assertEquals(1, actual.get(4).activationCount); assertTrue(actual.get(4).elapsedNanoseconds > 0); }
@Test public void testFailingProfile() { List<Profiler.Profile> actual = new ArrayList<>(); Result result = Profiler.on(ExamplesTest.IDENTIFIER, actual::add).parse("1"); assertFalse(result.isSuccess()); assertEquals(5, actual.size()); assertEquals("FlattenParser", actual.get(0).parser.toString()); assertEquals(1, actual.get(0).activationCount); assertTrue(actual.get(0).elapsedNanoseconds > 0); assertEquals("SequenceParser", actual.get(1).parser.toString()); assertEquals(1, actual.get(1).activationCount); assertTrue(actual.get(1).elapsedNanoseconds > 0); assertEquals("PossessiveRepeatingParser[0..*]", actual.get(2).parser.toString()); assertEquals(0, actual.get(2).activationCount); assertEquals(0, actual.get(2).elapsedNanoseconds); assertEquals("CharacterParser[letter or digit expected]", actual.get(3).parser.toString()); assertEquals(0, actual.get(3).activationCount); assertEquals(0, actual.get(3).elapsedNanoseconds); assertEquals("CharacterParser[letter expected]", actual.get(4).parser.toString()); assertEquals(1, actual.get(4).activationCount); assertTrue(actual.get(4).elapsedNanoseconds > 0); }
@Test public void testProfileToString() { List<Profiler.Profile> profiles = new ArrayList<>(); Profiler.on(ExamplesTest.IDENTIFIER, profiles::add).parse("ab123"); for (Profiler.Profile profile : profiles) { String[] token = profile.toString().split("\t"); assertEquals(4, token.length); assertEquals(token[0], Integer.toString(profile.activationCount)); assertEquals(token[1], Integer.toString(profile.totalActivationCount)); assertEquals(token[2], Long.toString(profile.elapsedNanoseconds)); assertEquals(token[3], profile.parser.toString()); } }