diff options
Diffstat (limited to 'impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java')
-rw-r--r-- | impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java new file mode 100644 index 00000000..3267eac5 --- /dev/null +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java @@ -0,0 +1,404 @@ +/* + * Copyright 2017, OpenCensus Authors + * + * 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 io.opencensus.implcore.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.internal.RandomHandler; +import io.opencensus.testing.common.TestClock; +import io.opencensus.trace.Span; +import io.opencensus.trace.Span.Kind; +import io.opencensus.trace.Span.Options; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.config.TraceParams; +import io.opencensus.trace.export.SpanData; +import io.opencensus.trace.samplers.Samplers; +import java.util.Collections; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link SpanBuilderImpl}. */ +@RunWith(JUnit4.class) +public class SpanBuilderImplTest { + private static final String SPAN_NAME = "MySpanName"; + private SpanBuilderImpl.Options spanBuilderOptions; + private final TraceParams alwaysSampleTraceParams = + TraceParams.DEFAULT.toBuilder().setSampler(Samplers.alwaysSample()).build(); + private final TestClock testClock = TestClock.create(); + private final RandomHandler randomHandler = new FakeRandomHandler(); + @Mock private StartEndHandler startEndHandler; + @Mock private TraceConfig traceConfig; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + spanBuilderOptions = + new SpanBuilderImpl.Options(randomHandler, startEndHandler, testClock, traceConfig); + when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); + } + + @Test + public void startSpan_CreatesTheCorrectSpanImplInstance() { + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.alwaysSample()) + .startSpan()) + .isInstanceOf(RecordEventsSpanImpl.class); + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .setSampler(Samplers.neverSample()) + .startSpan()) + .isInstanceOf(RecordEventsSpanImpl.class); + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan()) + .isInstanceOf(NoRecordEventsSpanImpl.class); + } + + @Test + public void setSpanKind_NotNull() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSpanKind(Kind.CLIENT) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getKind()).isEqualTo(Kind.CLIENT); + assertThat(span.toSpanData().getKind()).isEqualTo(Kind.CLIENT); + } + + @Test + public void setSpanKind_DefaultNull() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getKind()).isNull(); + assertThat(span.toSpanData().getKind()).isNull(); + } + + @Test + public void startSpanNullParent() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); + assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isNull(); + assertThat(spanData.getStartTimestamp()).isEqualTo(testClock.now()); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + } + + @Test + public void startSpanNullParentWithRecordEvents() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); + assertThat(span.getContext().getTraceOptions().isSampled()).isFalse(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isNull(); + } + + @Test + public void startSpanNullParentNoRecordOptions() { + Span span = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isFalse(); + assertThat(span.getContext().getTraceOptions().isSampled()).isFalse(); + } + + @Test + public void startChildSpan() { + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions).startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue(); + assertThat(((RecordEventsSpanImpl) rootSpan).toSpanData().getHasRemoteParent()).isNull(); + Span childSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions).startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); + assertThat(((RecordEventsSpanImpl) childSpan).toSpanData().getParentSpanId()) + .isEqualTo(rootSpan.getContext().getSpanId()); + assertThat(((RecordEventsSpanImpl) childSpan).toSpanData().getHasRemoteParent()).isFalse(); + assertThat(((RecordEventsSpanImpl) childSpan).getTimestampConverter()) + .isEqualTo(((RecordEventsSpanImpl) rootSpan).getTimestampConverter()); + } + + @Test + public void startRemoteSpan_NullParent() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); + assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isNull(); + } + + @Test + public void startRemoteSpanInvalidParent() { + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent( + SPAN_NAME, SpanContext.INVALID, spanBuilderOptions) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); + assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isNull(); + } + + @Test + public void startRemoteSpan() { + SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(randomHandler.current()), + SpanId.generateRandomId(randomHandler.current()), + TraceOptions.DEFAULT); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, spanContext, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); + assertThat(span.getContext().isValid()).isTrue(); + assertThat(span.getContext().getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getParentSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(spanData.getHasRemoteParent()).isTrue(); + } + + @Test + public void startRootSpan_WithSpecifiedSampler() { + // Apply given sampler before default sampler for root spans. + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse(); + } + + @Test + public void startRootSpan_WithoutSpecifiedSampler() { + // Apply default sampler (always true in the tests) for root spans. + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions).startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue(); + } + + @Test + public void startRemoteChildSpan_WithSpecifiedSampler() { + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.alwaysSample()) + .startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue(); + // Apply given sampler before default sampler for spans with remote parent. + Span childSpan = + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, rootSpan.getContext(), spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse(); + } + + @Test + public void startRemoteChildSpan_WithoutSpecifiedSampler() { + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse(); + // Apply default sampler (always true in the tests) for spans with remote parent. + Span childSpan = + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, rootSpan.getContext(), spanBuilderOptions) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isTrue(); + } + + @Test + public void startChildSpan_WithSpecifiedSampler() { + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.alwaysSample()) + .startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue(); + // Apply the given sampler for child spans. + Span childSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse(); + } + + @Test + public void startChildSpan_WithoutSpecifiedSampler() { + Span rootSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(rootSpan.getContext().isValid()).isTrue(); + assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isFalse(); + // Don't apply the default sampler (always true) for child spans. + Span childSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions).startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse(); + } + + @Test + public void startChildSpan_SampledLinkedParent() { + Span rootSpanUnsampled = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan(); + assertThat(rootSpanUnsampled.getContext().getTraceOptions().isSampled()).isFalse(); + Span rootSpanSampled = + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.alwaysSample()) + .startSpan(); + assertThat(rootSpanSampled.getContext().getTraceOptions().isSampled()).isTrue(); + // Sampled because the linked parent is sampled. + Span childSpan = + SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpanUnsampled, spanBuilderOptions) + .setParentLinks(Collections.singletonList(rootSpanSampled)) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()) + .isEqualTo(rootSpanUnsampled.getContext().getTraceId()); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isTrue(); + } + + @Test + public void startRemoteChildSpan_WithProbabilitySamplerDefaultSampler() { + when(traceConfig.getActiveTraceParams()).thenReturn(TraceParams.DEFAULT); + // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long + // is not less than probability * Long.MAX_VALUE; + TraceId traceId = + TraceId.fromBytes( + new byte[] { + (byte) 0x8F, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }); + + // If parent is sampled then the remote child must be sampled. + Span childSpan = + SpanBuilderImpl.createWithRemoteParent( + SPAN_NAME, + SpanContext.create( + traceId, + SpanId.generateRandomId(randomHandler.current()), + TraceOptions.builder().setIsSampled(true).build()), + spanBuilderOptions) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(traceId); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isTrue(); + childSpan.end(); + + assertThat(traceConfig.getActiveTraceParams()).isEqualTo(TraceParams.DEFAULT); + + // If parent is not sampled then the remote child must be not sampled. + childSpan = + SpanBuilderImpl.createWithRemoteParent( + SPAN_NAME, + SpanContext.create( + traceId, + SpanId.generateRandomId(randomHandler.current()), + TraceOptions.DEFAULT), + spanBuilderOptions) + .startSpan(); + assertThat(childSpan.getContext().isValid()).isTrue(); + assertThat(childSpan.getContext().getTraceId()).isEqualTo(traceId); + assertThat(childSpan.getContext().getTraceOptions().isSampled()).isFalse(); + childSpan.end(); + } + + private static final class FakeRandomHandler extends RandomHandler { + private final Random random; + + FakeRandomHandler() { + this.random = new Random(1234); + } + + @Override + public Random current() { + return random; + } + } +} |