package com.insightfullogic.honest_profiler.framework.generator;
import static java.util.Arrays.asList;
import static java.util.Collections.reverse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import com.insightfullogic.honest_profiler.core.parser.Method;
import com.insightfullogic.honest_profiler.core.parser.StackFrame;
import com.insightfullogic.honest_profiler.core.parser.ThreadMeta;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile;
import com.insightfullogic.honest_profiler.core.profiles.lean.info.FrameInfo;
import com.insightfullogic.honest_profiler.core.profiles.lean.info.MethodInfo;
import com.insightfullogic.honest_profiler.core.profiles.lean.info.NumericInfo;
import com.insightfullogic.honest_profiler.core.profiles.lean.info.ThreadInfo;
import com.insightfullogic.honest_profiler.framework.LeanLogCollectorDriver;
public class LeanProfileGenerator extends LeanLogCollectorDriver
{
// Instance Properties
private LeanProfile previousProfile;
private LeanProfile currentProfile;
private int nrChanges;
// Instance Constructors
public LeanProfileGenerator()
{
reset();
}
public LeanProfileGenerator(boolean issueInitialRequest)
{
if (issueInitialRequest)
{
resetAndRequest();
}
else
{
reset();
}
}
// Instance Accessors
public LeanProfile getProfile()
{
return currentProfile;
}
public LeanNode getNode(long threadId, StackFrame... stack)
{
LeanNode current = currentProfile.getThreads().get(threadId);
List<StackFrame> frames = asList(stack);
reverse(frames);
for (StackFrame frame : frames)
{
Optional<LeanNode> child = current.getChildren().stream()
.filter(node -> node.getFrame().getMethodId() == frame.getMethodId()).findFirst();
current = child.get();
}
return current;
}
// LeanProfileListener Implementation
@Override
public void accept(LeanProfile newProfile)
{
previousProfile = currentProfile;
currentProfile = newProfile;
nrChanges++;
}
// Assertions
public void assertNothingEmitted()
{
assertNull("No profile should have been emitted.", currentProfile);
assertNull("No profile should have been emitted.", previousProfile);
assertEquals("No profile should have been emitted.", 0, nrChanges);
}
public void assertSingleEmission()
{
assertNotNull("A profile should have been emitted.", currentProfile);
assertNull("Only one profile should have been emitted.", previousProfile);
assertEquals("Exactly one profile should have been emitted.", 1, nrChanges);
}
public void assertContains(Method... methods)
{
asList(methods).forEach(method ->
{
MethodInfo info = currentProfile.getMethodInfoMap().get(method.getMethodId());
assertEquals("Method Id mismatch", method.getMethodId(), info.getMethodId());
assertEquals("Method Name mismatch", method.getMethodName(), info.getMethodName());
assertEquals("Method Class Name mismatch", method.getClassName(), info.getClassName());
assertEquals("Method File Name mismatch", method.getFileName(), info.getFileName());
});
}
public void assertContains(ThreadMeta... threads)
{
asList(threads).forEach(thread ->
{
ThreadInfo info = currentProfile.getThreadInfoMap().get(thread.getThreadId());
assertEquals("Thread Id mismatch", thread.getThreadId(), info.getId());
assertEquals("Thread Name mismatch", thread.getThreadName(), info.getName());
});
}
public void assertMethodMapSizeEquals(int size)
{
assertEquals("MethodInfoMap size wrong", size, currentProfile.getMethodInfoMap().size());
}
public void assertThreadMapSizeEquals(int size)
{
assertEquals("ThreadInfoMap size wrong", size, currentProfile.getThreadInfoMap().size());
}
public void assertProfileThreadCountEquals(int size)
{
assertEquals("Wrong Thread count in Profile", size, currentProfile.getThreads().size());
}
public void assertProfileContainsThread(long id)
{
assertNotNull("Thread not found in Profile", currentProfile.getThreads().get(id));
}
public void assertProfileContainsStack(long threadId, StackFrame... stack)
{
LeanNode current = currentProfile.getThreads().get(threadId);
assertNotNull("Thread not found in Profile", current);
int level = 0;
List<StackFrame> frames = asList(stack);
reverse(frames);
for (StackFrame frame : frames)
{
level++;
Optional<LeanNode> child = current.getChildren().stream().filter(
node -> node.getFrame().getMethodId() == frame.getMethodId()
&& node.getFrame().getLineNr() == frame.getLineNumber()
&& node.getFrame().getBci() == frame.getBci())
.findFirst();
assertTrue("Descendant at level " + level + " not found", child.isPresent());
current = child.get();
assertNodeRepresentsFrame(current, frame);
}
}
public void assertNodeRepresentsFrame(LeanNode node, StackFrame stackFrame)
{
FrameInfo info = node.getFrame();
assertEquals(stackFrame.getMethodId(), info.getMethodId());
assertEquals(stackFrame.getLineNumber(), info.getLineNr());
assertEquals(stackFrame.getBci(), info.getBci());
}
public void assertSelfCountEquals(int selfCount, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Self Count", selfCount, info.getSelfCnt());
}
public void assertTotalCountEquals(int totalCount, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Total Count", totalCount, info.getTotalCnt());
}
public void assertCountsEqual(int selfCount, int totalCount, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Self Count", selfCount, info.getSelfCnt());
assertEquals("Wrong Total Count", totalCount, info.getTotalCnt());
}
public void assertSelfTimeEquals(long selfTime, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Self Time", BigInteger.valueOf(selfTime), info.getSelfTime());
}
public void assertTotalTimeEquals(long totalTime, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Total Time", BigInteger.valueOf(totalTime), info.getTotalTime());
}
public void assertTimesEqual(long selfTime, long totalTime, long threadId, StackFrame... stack)
{
NumericInfo info = getNode(threadId, stack).getData();
assertEquals("Wrong Self Time", BigInteger.valueOf(selfTime), info.getSelfTime());
assertEquals("Wrong Total Time", BigInteger.valueOf(totalTime), info.getTotalTime());
}
}