/*
* 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.test;
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.thrift.TBase;
import org.junit.After;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.profiler.context.Span;
import com.navercorp.pinpoint.profiler.context.SpanEvent;
/**
* @author HyunGil Jeong
*/
public class OrderedSpanRecorderTest {
private static final int UNSET_ASYNC_ID = -1;
private static final short UNSET_ASYNC_SEQUENCE = -1;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final OrderedSpanRecorder recorder = new OrderedSpanRecorder();
@After
public void tearDown() throws Exception {
this.recorder.clear();
}
@Test
public void testOrderingWithSameEventTime() {
// given
final long startTime = System.currentTimeMillis();
final long spanId = 1L;
Span span = createSpan(startTime, spanId);
SpanEvent event = createSpanEvent(span, 0, (short) 0);
SpanEvent event1 = createSpanEvent(span, 0, (short) 1);
SpanEvent event2 = createSpanEvent(span, 0, (short) 2);
SpanEvent asyncEvent1_1 = createAsyncSpanEvent(span, 0, (short) 0, 1, (short) 1);
SpanEvent asyncEvent1_2 = createAsyncSpanEvent(span, 0, (short) 1, 1, (short) 1);
SpanEvent asyncEvent2 = createAsyncSpanEvent(span, 0, (short) 0, 2, (short) 1);
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> expectedOrder = Arrays.asList(
span,
event,
event1,
event2,
asyncEvent1_1,
asyncEvent1_2,
asyncEvent2
);
// when
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> listToBeHandled = Arrays.asList(
span, event, event1, event2, asyncEvent1_1, asyncEvent1_2, asyncEvent2
);
Collections.shuffle(listToBeHandled);
for (TBase<?, ?> base : listToBeHandled) {
this.recorder.handleSend(base);
}
// then
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.recorder.print(new PrintStream(baos));
this.logger.debug(baos.toString());
for (TBase<?, ?> expectedBase : expectedOrder) {
TBase<?, ?> actualBase = this.recorder.pop();
assertSame(expectedBase, actualBase);
}
assertNull(this.recorder.pop());
}
@Test
public void testMultipleAsyncSpanEvents() {
// given
final long startTime = System.currentTimeMillis();
final long spanId = 1L;
Span span = createSpan(startTime, spanId);
SpanEvent event1 = createSpanEvent(span, 0, (short) 0);
SpanEvent asyncEvent1_1_1 = createAsyncSpanEvent(span, 0, (short) 0, 1, (short) 1);
SpanEvent asyncEvent1_1_2 = createAsyncSpanEvent(span, 0, (short) 1, 1, (short) 1);
SpanEvent asyncEvent1_2_1 = createAsyncSpanEvent(span, 0, (short) 0, 1, (short) 2);
SpanEvent event2 = createSpanEvent(span, 0, (short) 1);
SpanEvent asyncEvent2_1 = createAsyncSpanEvent(span, 0, (short) 0, 2, (short) 1);
SpanEvent asyncEvent2_2 = createAsyncSpanEvent(span, 0, (short) 0, 2, (short) 2);
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> expectedOrder = Arrays.asList(
span,
event1,
event2,
asyncEvent1_1_1,
asyncEvent1_1_2,
asyncEvent1_2_1,
asyncEvent2_1,
asyncEvent2_2
);
// when
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> listToBeHandled = Arrays.asList(
span, event1, asyncEvent1_1_1, asyncEvent1_1_2, asyncEvent1_2_1, event2, asyncEvent2_1, asyncEvent2_2
);
Collections.shuffle(listToBeHandled);
for (TBase<?, ?> base : listToBeHandled) {
this.recorder.handleSend(base);
}
// then
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.recorder.print(new PrintStream(baos));
this.logger.debug(baos.toString());
for (TBase<?, ?> expectedBase : expectedOrder) {
TBase<?, ?> actualBase = this.recorder.pop();
assertSame(expectedBase, actualBase);
}
assertNull(this.recorder.pop());
}
@Test
public void testMultipleSpanOrdering() {
// given
final long startTime1 = System.currentTimeMillis();
final long spanId1 = 1L;
final long startTime2 = startTime1 + 10L;
final long spanId2 = 2L;
Span span1 = createSpan(startTime1, spanId1);
SpanEvent event1_0 = createSpanEvent(span1, 1, (short) 0);
SpanEvent event1_1 = createSpanEvent(span1, 2, (short) 1);
SpanEvent asyncEvent1_0 = createAsyncSpanEvent(span1, 1, (short) 0, 1, (short) 1);
SpanEvent asyncEvent1_1 = createAsyncSpanEvent(span1, 2, (short) 1, 1, (short) 1);
Span span2 = createSpan(startTime2, spanId2);
SpanEvent event2_0 = createSpanEvent(span2, 0, (short) 0);
SpanEvent event2_1 = createSpanEvent(span2, 1, (short) 1);
SpanEvent asyncEvent2_0 = createAsyncSpanEvent(span2, 0, (short) 0, 2, (short) 1);
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> expectedOrder = Arrays.asList(
span1,
event1_0,
event1_1,
span2,
event2_0,
event2_1,
asyncEvent1_0,
asyncEvent1_1,
asyncEvent2_0
);
// when
@SuppressWarnings("unchecked")
final List<? extends TBase<?, ?>> listToBeHandled = Arrays.asList(
span1, event1_0, event1_1, span2, event2_0, event2_1, asyncEvent1_0, asyncEvent1_1, asyncEvent2_0
);
Collections.shuffle(listToBeHandled);
for (TBase<?, ?> base : listToBeHandled) {
this.recorder.handleSend(base);
}
// then
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.recorder.print(new PrintStream(baos));
this.logger.debug(baos.toString());
for (TBase<?, ?> expectedBase : expectedOrder) {
TBase<?, ?> actualBase = this.recorder.pop();
assertSame(expectedBase, actualBase);
}
assertNull(this.recorder.pop());
}
private SpanEvent createSpanEvent(Span associatedSpan, int startElapsed, short sequence) {
return createAsyncSpanEvent(associatedSpan, startElapsed, sequence, UNSET_ASYNC_ID, UNSET_ASYNC_SEQUENCE);
}
private SpanEvent createAsyncSpanEvent(Span associatedSpan, int startElapsed, short sequence, int asyncId, short asyncSequence) {
SpanEvent event = new SpanEvent(associatedSpan);
event.setStartElapsed(startElapsed);
event.setSequence(sequence);
if (asyncId != UNSET_ASYNC_ID) {
event.setAsyncId(asyncId);
}
if (asyncSequence != UNSET_ASYNC_SEQUENCE) {
event.setAsyncSequence(asyncSequence);
}
return event;
}
private Span createSpan(long startTime, long spanId) {
Span span = new Span();
span.setStartTime(startTime);
span.setSpanId(spanId);
return span;
}
}