package com.navercorp.pinpoint.common.server.bo.serializer.trace.v2; import com.google.common.collect.Lists; import com.navercorp.pinpoint.common.buffer.Buffer; import com.navercorp.pinpoint.common.buffer.OffsetFixedBuffer; import com.navercorp.pinpoint.common.server.bo.RandomTSpan; import com.navercorp.pinpoint.common.server.bo.SpanBo; import com.navercorp.pinpoint.common.server.bo.SpanChunkBo; import com.navercorp.pinpoint.common.server.bo.SpanEventBo; import com.navercorp.pinpoint.common.server.bo.SpanFactory; import com.navercorp.pinpoint.thrift.dto.TSpan; import com.navercorp.pinpoint.thrift.dto.TSpanChunk; import com.navercorp.pinpoint.thrift.dto.TSpanEvent; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.TimeUnit; /** * @author Woonduk Kang(emeroad) */ public class SpanEncoderTest { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final int REPEAT_COUNT = 10; private final RandomTSpan randomTSpan = new RandomTSpan(); private final SpanFactory spanFactory = new SpanFactory(); private SpanEncoder spanEncoder = new SpanEncoderV0(); private SpanDecoder spanDecoder = new SpanDecoderV0(); @Test public void testEncodeSpanColumnValue_simpleSpan() throws Exception { SpanBo spanBo = randomSpan(); assertSpan(spanBo); } @Test public void testEncodeSpanColumnValue_simpleSpan_N() throws Exception { for (int i = 0; i < REPEAT_COUNT; i++) { testEncodeSpanColumnValue_simpleSpan(); } } @Test public void testEncodeSpanColumnValue_complexSpan() throws Exception { SpanBo spanBo = randomComplexSpan(); assertSpan(spanBo); } @Test public void testEncodeSpanColumnValue_complexSpan_N() throws Exception { for (int i = 0; i < REPEAT_COUNT; i++) { testEncodeSpanColumnValue_complexSpan(); } } @Test public void testEncodeSpanColumnValue_simpleSpanChunk() throws Exception { SpanChunkBo spanChunkBo = randomSpanChunk(); assertSpanChunk(spanChunkBo); } @Test public void testEncodeSpanColumnValue_simpleSpanChunk_N() throws Exception { for (int i = 0; i < REPEAT_COUNT; i++) { testEncodeSpanColumnValue_simpleSpanChunk(); } } @Test public void testEncodeSpanColumnValue_complexSpanChunk() throws Exception { SpanChunkBo spanChunkBo = randomComplexSpanChunk(); assertSpanChunk(spanChunkBo); } @Test public void testEncodeSpanColumnValue_complexSpanChunk_N() throws Exception { for (int i = 0; i < REPEAT_COUNT; i++) { testEncodeSpanColumnValue_complexSpanChunk(); } } private long getCollectorAcceptTime() { long currentTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30); long randomSeed = RandomUtils.nextLong(0, TimeUnit.DAYS.toMillis(60)); return currentTime - randomSeed; } private OffsetFixedBuffer wrapBuffer(ByteBuffer byteBuffer) { return new OffsetFixedBuffer(byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.remaining()); } private SpanBo randomSpan() { TSpan tSpan = randomTSpan.randomTSpan(); return spanFactory.buildSpanBo(tSpan); } public SpanBo randomComplexSpan() { TSpan tSpan = randomTSpan.randomTSpan(); TSpanEvent tSpanEvent1 = randomTSpan.randomTSpanEvent((short) 1); TSpanEvent tSpanEvent2 = randomTSpan.randomTSpanEvent((short) 2); TSpanEvent tSpanEvent3 = randomTSpan.randomTSpanEvent((short) 3); TSpanEvent tSpanEvent4 = randomTSpan.randomTSpanEvent((short) 5); tSpan.setSpanEventList(Lists.newArrayList(tSpanEvent1, tSpanEvent2, tSpanEvent3, tSpanEvent4)); return spanFactory.buildSpanBo(tSpan); } private SpanChunkBo randomSpanChunk() { TSpanChunk tSpanChunk = randomTSpan.randomTSpanChunk(); return spanFactory.buildSpanChunkBo(tSpanChunk); } public SpanChunkBo randomComplexSpanChunk() { TSpanChunk tSpanChunk = randomTSpan.randomTSpanChunk(); TSpanEvent tSpanEvent1 = randomTSpan.randomTSpanEvent((short) 1); TSpanEvent tSpanEvent2 = randomTSpan.randomTSpanEvent((short) 2); TSpanEvent tSpanEvent3 = randomTSpan.randomTSpanEvent((short) 3); TSpanEvent tSpanEvent4 = randomTSpan.randomTSpanEvent((short) 5); tSpanChunk.setSpanEventList(Lists.newArrayList(tSpanEvent1, tSpanEvent2, tSpanEvent3, tSpanEvent4)); return spanFactory.buildSpanChunkBo(tSpanChunk); } private void assertSpan(SpanBo spanBo) { spanBo.setCollectorAcceptTime(getCollectorAcceptTime()); SpanEncodingContext<SpanBo> encodingContext = new SpanEncodingContext<SpanBo>(spanBo); Buffer qualifier = wrapBuffer(spanEncoder.encodeSpanQualifier(encodingContext)); Buffer column = wrapBuffer(spanEncoder.encodeSpanColumnValue(encodingContext)); SpanDecodingContext decodingContext = new SpanDecodingContext(); decodingContext.setTransactionId(spanBo.getTransactionId()); decodingContext.setCollectorAcceptedTime(spanBo.getCollectorAcceptTime()); SpanBo decode = (SpanBo) spanDecoder.decode(qualifier, column, decodingContext); logger.debug("span dump \noriginal spanBo:{} \ndecode spanBo:{} ", spanBo, decode); List<String> notSerializedField = Lists.newArrayList("parentApplicationId", "parentApplicationServiceType"); List<String> excludeField = Lists.newArrayList("annotationBoList", "spanEventBoList"); notSerializedField.addAll(excludeField); Assert.assertTrue(EqualsBuilder.reflectionEquals(decode, spanBo, notSerializedField)); logger.debug("{} {}", spanBo.getAnnotationBoList(), decode.getAnnotationBoList()); Assert.assertTrue("annotation", EqualsBuilder.reflectionEquals(spanBo.getAnnotationBoList(), decode.getAnnotationBoList())); List<SpanEventBo> spanEventBoList = spanBo.getSpanEventBoList(); List<SpanEventBo> decodedSpanEventBoList = decode.getSpanEventBoList(); Assert.assertTrue(EqualsBuilder.reflectionEquals(spanEventBoList, decodedSpanEventBoList)); } private void assertSpanChunk(SpanChunkBo spanChunkBo) { spanChunkBo.setCollectorAcceptTime(getCollectorAcceptTime()); SpanEncodingContext<SpanChunkBo> encodingContext = new SpanEncodingContext<SpanChunkBo>(spanChunkBo); Buffer qualifier = wrapBuffer(spanEncoder.encodeSpanChunkQualifier(encodingContext)); Buffer column = wrapBuffer(spanEncoder.encodeSpanChunkColumnValue(encodingContext)); SpanDecodingContext decodingContext = new SpanDecodingContext(); decodingContext.setTransactionId(spanChunkBo.getTransactionId()); decodingContext.setCollectorAcceptedTime(spanChunkBo.getCollectorAcceptTime()); SpanChunkBo decode = (SpanChunkBo) spanDecoder.decode(qualifier, column, decodingContext); logger.debug("spanChunk dump \noriginal spanChunkBo:{} \ndecode spanChunkBo:{} ", spanChunkBo, decode); List<String> notSerializedField = Lists.newArrayList("endPoint", "serviceType", "applicationServiceType"); List<String> excludeField = Lists.newArrayList("spanEventBoList"); notSerializedField.addAll(excludeField); Assert.assertTrue(EqualsBuilder.reflectionEquals(decode, spanChunkBo, notSerializedField)); List<SpanEventBo> spanEventBoList = spanChunkBo.getSpanEventBoList(); List<SpanEventBo> decodedSpanEventBoList = decode.getSpanEventBoList(); Assert.assertTrue(EqualsBuilder.reflectionEquals(spanEventBoList, decodedSpanEventBoList)); } @Test public void testEncodeSpanColumnValue_spanEvent_startTimeDelta_equals() { SpanBo spanBo = randomComplexSpan(); SpanEventBo spanEventBo0 = spanBo.getSpanEventBoList().get(0); SpanEventBo spanEventBo1 = spanBo.getSpanEventBoList().get(1); spanEventBo1.setStartElapsed(spanEventBo0.getStartElapsed()); assertSpan(spanBo); } @Test public void testEncodeSpanColumnValue_spanEvent_depth_equals() { SpanBo spanBo = randomComplexSpan(); SpanEventBo spanEventBo0 = spanBo.getSpanEventBoList().get(0); SpanEventBo spanEventBo1 = spanBo.getSpanEventBoList().get(1); spanEventBo1.setDepth(spanEventBo0.getDepth()); assertSpan(spanBo); } @Test public void testEncodeSpanColumnValue_spanEvent_service_equals() { SpanBo spanBo = randomComplexSpan(); SpanEventBo spanEventBo0 = spanBo.getSpanEventBoList().get(0); SpanEventBo spanEventBo1 = spanBo.getSpanEventBoList().get(1); spanEventBo1.setServiceType(spanEventBo0.getServiceType()); assertSpan(spanBo); } }