package org.gridkit.jvmtool.stacktrace.analytics; import java.lang.Thread.State; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.gridkit.jvmtool.stacktrace.CounterCollection; import org.gridkit.jvmtool.stacktrace.StackFrame; import org.gridkit.jvmtool.stacktrace.StackFrameArray; import org.gridkit.jvmtool.stacktrace.StackFrameList; import org.gridkit.jvmtool.stacktrace.ThreadSnapshot; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class FilterParserMatchingTest { static class Trace { String name; List<StackFrame> frame = new ArrayList<StackFrame>(); public Trace(String name) { this.name = name; } public Trace t(String trace) { if (trace.indexOf('(') > 0) { frame.add(StackFrame.parseFrame(trace)); } else { frame.add(StackFrame.parseFrame(trace + "(X.java)")); } return this; } public StackFrameList frameList() { ArrayList<StackFrame> list = new ArrayList<StackFrame>(frame); Collections.reverse(list); StackFrame[] array = list.toArray(new StackFrame[0]); return new StackFrameArray(array); } public String toString() { return name; } } private static List<Object[]> cases = new ArrayList<Object[]>(); public static final Trace TRACE_A = new Trace("TRACE_A") .t("com.acme.MyClass") .t("test.MyBean.init(MyBean.java:100)") .t("com.acme.MyClass$1"); public static final Trace TRACE_B1 = new Trace("TRACE_B1") .t("test.server.Handler.run") .t("test.server.Handler.process(X.java:123)") .t("test.myapp.security.Filter.process") .t("test.framework.Rederer.execute") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.doChecks"); public static final Trace TRACE_B2 = new Trace("TRACE_B2") .t("test.server.Handler.run") .t("test.server.Handler.process(X.java:123)") .t("test.myapp.security.Filter.process") .t("test.framework.Rederer.execute") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff"); public static final Trace TRACE_B3 = new Trace("TRACE_B3") .t("test.server.Handler.run") .t("test.server.Handler.process(X.java:123)") .t("test.myapp.security.Filter.process") .t("test.framework.Rederer.execute") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.doChecks") .t("javax.jdbc.Something"); public static final Trace TRACE_B4 = new Trace("TRACE_B4") .t("test.server.Handler.run") .t("test.server.Handler.process(X.java:123)") .t("test.myapp.security.Filter.process") .t("test.framework.Rederer.execute") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff") .t("test.framework.Syncjector.invoke") .t("test.framework.Syncjector.doChecks"); public static final Trace TRACE_B5 = new Trace("TRACE_B5") .t("test.server.Handler.run") .t("test.server.Handler.process(X.java:128)") // differnt line number .t("test.myapp.security.Filter.process") .t("test.framework.Rederer.execute") .t("test.framework.Bijector.invoke") .t("test.framework.Bijector.proceed") .t("test.myapp.app.MyBean.doStuff") .t("test.framework.Syncjector.invoke") .t("test.framework.Syncjector.doChecks"); @Parameters(name = "\"{0}\" {1} {2}") public static List<Object[]> getExpressions() { caseMatch (TRACE_A, "**.acme.**"); caseMatch (TRACE_A, "garbage, garbage,**.acme.**"); caseMatch (TRACE_A, "**.acme.**,garbage, garbage"); caseMatch (TRACE_A, "garbage,**.acme.**,garbage"); caseMatch (TRACE_A, "**.acme.*"); caseMatch (TRACE_A, "**.MyCla"); caseMatch (TRACE_A, "**.MyClass$1"); caseMatch (TRACE_A, "**.*$1"); caseNonMatch(TRACE_A, "*.MyClass"); caseNonMatch(TRACE_A, "MyClass"); caseMatch (TRACE_A, "**.MyBean.init*.java:100"); caseMatch (TRACE_A, "**.MyBean.init**:100"); caseMatch (TRACE_A, "**.MyBean.init*:100"); // special case caseNonMatch(TRACE_A, "**.MyBean*:100"); // special case caseMatch (TRACE_A, "**.MyBean**:100"); String smartMatch = "(**.Handler.process*.java:123)!(javax.jdbc,test.jbbc)+(**.Bijector.invoke,**.Syncjector.invoke/!(**.proceed))"; caseMatch (TRACE_B1, smartMatch); caseNonMatch(TRACE_B2, smartMatch); caseNonMatch(TRACE_B3, smartMatch); caseMatch (TRACE_B4, smartMatch); caseNonMatch(TRACE_B5, smartMatch); return cases; } private static void caseMatch(Trace trace, String filter) { cases.add(new Object[]{filter, trace, true}); } private static void caseNonMatch(Trace trace, String filter) { cases.add(new Object[]{filter, trace, false}); } private String expression; private Trace trace; private boolean match; public FilterParserMatchingTest(String expression, Trace trace, boolean match) { this.expression = expression; this.trace = trace; this.match = match; } @Test public void match() { ThreadSnapshotFilter f = TraceFilterPredicateParser.parseFilter(expression, new BasicFilterFactory()); if (match) { Assert.assertTrue("Should match", f.evaluate(trace())); } else { Assert.assertFalse("Should not match", f.evaluate(trace())); } } private ThreadSnapshot trace() { return new ThreadSnapshot() { @Override public long timestamp() { return 0; } @Override public State threadState() { return null; } @Override public String threadName() { return null; } @Override public long threadId() { return 0; } @Override public StackFrameList stackTrace() { return trace.frameList(); } @Override public CounterCollection counters() { return null; } }; } }