/*
* Copyright 2015 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.web.calltree.span;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.navercorp.pinpoint.common.server.bo.SpanBo;
import com.navercorp.pinpoint.common.server.bo.SpanEventBo;
/**
*
* @author jaehong.kim
*
*/
public class CallTreeTest {
private static final boolean SYNC = false;
private static final boolean ASYNC = true;
private SpanCallTree callTree = new SpanCallTree(makeSpanAlign());
private List<String> expectResult = new ArrayList<String>();
@Test
public void add() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
expectResult.add("#####");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
callTree.add(2, makeSpanAlign(SYNC, (short) 1));
callTree.add(3, makeSpanAlign(SYNC, (short) 2));
callTree.add(4, makeSpanAlign(SYNC, (short) 3));
assertDepth("add", callTree, expectResult);
}
@Test
public void addAndSort() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
expectResult.add("#####");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
callTree.add(2, makeSpanAlign(SYNC, (short) 1));
callTree.add(3, makeSpanAlign(SYNC, (short) 2));
callTree.add(4, makeSpanAlign(SYNC, (short) 3));
assertDepth("addAndSort", callTree, expectResult);
callTree.sort();
assertDepth("addAndSort", callTree, expectResult);
}
@Test
public void addLevel() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
expectResult.add("#####");
expectResult.add("#####");
expectResult.add("#####");
expectResult.add("#####");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
callTree.add(2, makeSpanAlign(SYNC, (short) 1));
callTree.add(3, makeSpanAlign(SYNC, (short) 2));
callTree.add(4, makeSpanAlign(SYNC, (short) 3));
callTree.add(-1, makeSpanAlign(SYNC, (short) 4));
callTree.add(-1, makeSpanAlign(SYNC, (short) 5));
callTree.add(-1, makeSpanAlign(SYNC, (short) 6));
assertDepth("addLevel", callTree, expectResult);
}
@Test
public void addComplex() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
expectResult.add("#####");
expectResult.add("######");
expectResult.add("######");
expectResult.add("######");
expectResult.add("######");
expectResult.add("######");
expectResult.add("#####");
expectResult.add("#####");
expectResult.add("######");
expectResult.add("#######");
expectResult.add("########");
expectResult.add("########");
expectResult.add("#####");
expectResult.add("#####");
expectResult.add("#####");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
callTree.add(2, makeSpanAlign(SYNC, (short) 1));
callTree.add(3, makeSpanAlign(SYNC, (short) 2));
callTree.add(4, makeSpanAlign(SYNC, (short) 3));
callTree.add(5, makeSpanAlign(SYNC, (short) 4));
callTree.add(-1, makeSpanAlign(SYNC, (short) 5));
callTree.add(-1, makeSpanAlign(SYNC, (short) 6));
callTree.add(-1, makeSpanAlign(SYNC, (short) 7));
callTree.add(-1, makeSpanAlign(SYNC, (short) 8));
callTree.add(4, makeSpanAlign(SYNC, (short) 9));
callTree.add(-1, makeSpanAlign(SYNC, (short) 10));
callTree.add(5, makeSpanAlign(SYNC, (short) 11));
callTree.add(6, makeSpanAlign(SYNC, (short) 12));
callTree.add(7, makeSpanAlign(SYNC, (short) 13));
callTree.add(-1, makeSpanAlign(SYNC, (short) 14));
callTree.add(4, makeSpanAlign(SYNC, (short) 15));
callTree.add(-1, makeSpanAlign(SYNC, (short) 16));
callTree.add(-1, makeSpanAlign(SYNC, (short) 17));
assertDepth("addComplex", callTree, expectResult);
}
@Test
public void addSubTree() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("##");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
SpanCallTree subTree = new SpanCallTree(makeSpanAlign());
callTree.add(subTree);
callTree.add(-1, makeSpanAlign(SYNC, (short) 1));
assertDepth("addSubTree", callTree, expectResult);
}
@Test
public void addNestedSubTree() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
expectResult.add("#####");
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
SpanCallTree subTree = new SpanCallTree(makeSpanAlign(ASYNC, (short) 0));
subTree.add(1, makeSpanAlign(ASYNC, (short) 1));
SpanCallTree subTree2 = new SpanCallTree(makeSpanAlign(ASYNC, (short) 0));
subTree.add(subTree2);
callTree.add(subTree);
assertDepth("addNestedSubTree", callTree, expectResult);
}
@Test
public void missing() {
expectResult.clear();
expectResult.add("#");
try {
callTree.add(-1, makeSpanAlign(SYNC, (short) 20));
callTree.add(-1, makeSpanAlign(SYNC, (short) 21));
callTree.add(-1, makeSpanAlign(SYNC, (short) 22));
callTree.add(-1, makeSpanAlign(SYNC, (short) 23));
} catch (Exception ignored) {
}
assertDepth("missing-case-1", callTree, expectResult);
}
@Test
public void missingMiddleNodes() {
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("####");
try {
callTree.add(1, makeSpanAlign(SYNC, (short) 0));
callTree.add(2, makeSpanAlign(SYNC, (short) 1));
callTree.add(3, makeSpanAlign(SYNC, (short) 2));
// callTree.add(4, makeSpanAlign(SYNC, (short) 3));
// callTree.add(5, makeSpanAlign(SYNC, (short) 4));
// callTree.add(-1, makeSpanAlign(SYNC, (short) 5));
callTree.add(-1, makeSpanAlign(SYNC, (short) 6));
callTree.add(-1, makeSpanAlign(SYNC, (short) 7));
callTree.add(-1, makeSpanAlign(SYNC, (short) 8));
callTree.add(4, makeSpanAlign(SYNC, (short) 9));
callTree.add(-1, makeSpanAlign(SYNC, (short) 10));
callTree.add(5, makeSpanAlign(SYNC, (short) 11));
callTree.add(6, makeSpanAlign(SYNC, (short) 12));
callTree.add(7, makeSpanAlign(SYNC, (short) 13));
callTree.add(-1, makeSpanAlign(SYNC, (short) 14));
callTree.add(4, makeSpanAlign(SYNC, (short) 15));
callTree.add(-1, makeSpanAlign(SYNC, (short) 16));
callTree.add(-1, makeSpanAlign(SYNC, (short) 17));
} catch (Exception ignored) {
}
assertDepth("missing-case-2", callTree, expectResult);
}
@Test
public void missingAsync() {
expectResult.add("#");
expectResult.add("##");
callTree.add(1, makeSpanAlign(SYNC, (short) 0, 1, -1));
try {
SpanCallTree subTree = new SpanCallTree(makeSpanAlign());
// subTree.add(1, makeSpanAlign(ASYNC, (short) 0, -1, 1));
subTree.add(2, makeSpanAlign(ASYNC, (short) 1, 2, 1));
callTree.add(subTree);
} catch (Exception ignored) {
}
assertDepth("missing-case-3", callTree, expectResult);
}
@Test
public void missingAsyncEvent() {
expectResult.add("#");
expectResult.add("##");
expectResult.add("##");
callTree.add(1, makeSpanAlign(SYNC, (short) 0, 1, -1));
// callTree.add(makeSpanEventBo(ASYNC, (short) 0, 1));
callTree.add(-1, makeSpanAlign(SYNC, (short) 1, -1, -1));
assertDepth("missing-case-5", callTree, expectResult);
}
@Test
public void sort() {
expectResult.add("#");
expectResult.add("##");
expectResult.add("###"); // remote
expectResult.add("####"); // remote
expectResult.add("###");
expectResult.add("###");
expectResult.add("##");
SpanAlign root = makeSpanAlign(0, 10);
SpanCallTree callTree = new SpanCallTree(root);
callTree.add(1, makeSpanAlign(root.getSpanBo(), SYNC, (short) 0, -1, -1, 1, 1));
SpanAlign remoteRoot = makeSpanAlign(4, 5);
SpanCallTree subTree = new SpanCallTree(remoteRoot);
subTree.add(1, makeSpanAlign(remoteRoot.getSpanBo(), SYNC, (short) 0, -1, -1, 1, 1));
callTree.add(subTree);
callTree.add(2, makeSpanAlign(root.getSpanBo(), SYNC, (short) 1, -1, -1, 2, 1));
callTree.add(-1, makeSpanAlign(root.getSpanBo(), SYNC, (short) 2, -1, -1, 3, 1));
callTree.add(1, makeSpanAlign(root.getSpanBo(), SYNC, (short) 3, -1, -1, 4, 1));
assertDepth("before sort", callTree, expectResult);
callTree.sort();
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("###");
expectResult.add("###"); // remote
expectResult.add("####"); // remote
expectResult.add("##");
assertDepth("after sort", callTree, expectResult);
}
@Test
public void sort2() {
expectResult.add("#");
expectResult.add("##");
expectResult.add("###"); // remote 1
expectResult.add("####"); // remote 1
expectResult.add("###"); // remote 2
expectResult.add("###");
SpanAlign root = makeSpanAlign(0, 10);
SpanCallTree callTree = new SpanCallTree(root);
callTree.add(1, makeSpanAlign(root.getSpanBo(), SYNC, (short) 0, -1, -1, 1, 1));
SpanAlign remoteRoot1 = makeSpanAlign(4, 5);
SpanCallTree subTree1 = new SpanCallTree(remoteRoot1);
subTree1.add(1, makeSpanAlign(remoteRoot1.getSpanBo(), SYNC, (short) 0, -1, -1, 1, 1));
callTree.add(subTree1);
SpanAlign remoteRoot2 = makeSpanAlign(3, 4);
SpanCallTree subTree2 = new SpanCallTree(remoteRoot2);
callTree.add(subTree2);
callTree.add(2, makeSpanAlign(root.getSpanBo(), SYNC, (short) 1, -1, -1, 2, 1));
assertDepth("before sort", callTree, expectResult);
callTree.sort();
expectResult.clear();
expectResult.add("#");
expectResult.add("##");
expectResult.add("###");
expectResult.add("###"); // remote 2
expectResult.add("###"); // remote 1
expectResult.add("####"); // remote 1
assertDepth("after sort", callTree, expectResult);
}
private void assertDepth(final String name, SpanCallTree tree, List<String> result) {
int index = 0;
CallTreeIterator iterator = tree.iterator();
CallTreeNode node = null;
while ((node = iterator.next()) != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= node.getDepth(); i++) {
sb.append("#");
}
final String expected = result.get(index++);
printDepth(name, index, sb.toString(), expected);
}
}
private void printDepth(final String name, final int index, final String depth, final String expected) {
if (!expected.equals(depth)) {
fail("Not Matched " + name + "(" + index + "): " + depth + ", expected=" + expected);
}
}
private SpanAlign makeSpanAlign() {
return makeSpanAlign(0, 0);
}
private SpanAlign makeSpanAlign(long startTime, int elapsed) {
SpanBo span = new SpanBo();
span.setStartTime(startTime);
span.setElapsed(elapsed);
return new SpanAlign(span);
}
private SpanAlign makeSpanAlign(final boolean async, final short sequence) {
return makeSpanAlign(async, sequence, -1, -1);
}
private SpanAlign makeSpanAlign(final boolean async, final short sequence, final int nextAsyncId, final int asyncId) {
return makeSpanAlign(new SpanBo(), async, sequence, nextAsyncId, asyncId, -1, -1);
}
private SpanAlign makeSpanAlign(SpanBo span, final boolean async, final short sequence, int nextAsyncId, final int asyncId, int startElapsed, int endElapsed) {
SpanEventBo event = new SpanEventBo();
event.setAsyncId(async ? 1 : -1);
event.setSequence(sequence);
event.setNextAsyncId(nextAsyncId);
event.setAsyncId(asyncId);
event.setStartElapsed(startElapsed);
event.setEndElapsed(endElapsed);
return new SpanAlign(span, event);
}
}