diff options
Diffstat (limited to 'api/src/test/java/io/opencensus/trace')
33 files changed, 3725 insertions, 0 deletions
diff --git a/api/src/test/java/io/opencensus/trace/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/AnnotationTest.java new file mode 100644 index 00000000..0db5d93c --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AnnotationTest.java @@ -0,0 +1,102 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class AnnotationTest { + @Test(expected = NullPointerException.class) + public void fromDescription_NullDescription() { + Annotation.fromDescription(null); + } + + @Test + public void fromDescription() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullDescription() { + Annotation.fromDescriptionAndAttributes(null, Collections.<String, AttributeValue>emptyMap()); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullAttributes() { + Annotation.fromDescriptionAndAttributes("", null); + } + + @Test + public void fromDescriptionAndAttributes() { + Map<String, AttributeValue> attributes = new HashMap<String, AttributeValue>(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes()).isEqualTo(attributes); + } + + @Test + public void fromDescriptionAndAttributes_EmptyAttributes() { + Annotation annotation = + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.<String, AttributeValue>emptyMap()); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test + public void annotation_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + Map<String, AttributeValue> attributes = new HashMap<String, AttributeValue>(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester + .addEqualityGroup( + Annotation.fromDescription("MyAnnotationText"), + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.<String, AttributeValue>emptyMap())) + .addEqualityGroup( + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) + .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); + tester.testEquals(); + } + + @Test + public void annotation_ToString() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.toString()).contains("MyAnnotationText"); + Map<String, AttributeValue> attributes = new HashMap<String, AttributeValue>(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); + assertThat(annotation.toString()).contains("MyAnnotationText2"); + assertThat(annotation.toString()).contains(attributes.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java new file mode 100644 index 00000000..05ef43c0 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -0,0 +1,233 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import javax.annotation.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link AttributeValue}. */ +@RunWith(JUnit4.class) +public class AttributeValueTest { + @Test + public void stringAttributeValue() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + attribute.match( + new Function<String, Object>() { + @Override + @Nullable + public Object apply(String stringValue) { + assertThat(stringValue).isEqualTo("MyStringAttributeValue"); + return null; + } + }, + new Function<Boolean, Object>() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a String"); + return null; + } + }, + new Function<Long, Object>() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a String"); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void booleanAttributeValue() { + AttributeValue attribute = AttributeValue.booleanAttributeValue(true); + attribute.match( + new Function<String, Object>() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Boolean"); + return null; + } + }, + new Function<Boolean, Object>() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + assertThat(booleanValue).isTrue(); + return null; + } + }, + new Function<Long, Object>() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a Boolean"); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void longAttributeValue() { + AttributeValue attribute = AttributeValue.longAttributeValue(123456L); + attribute.match( + new Function<String, Object>() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Long"); + return null; + } + }, + new Function<Boolean, Object>() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a Long"); + return null; + } + }, + new Function<Long, Object>() { + @Override + @Nullable + public Object apply(Long longValue) { + assertThat(longValue).isEqualTo(123456L); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void doubleAttributeValue() { + AttributeValue attribute = AttributeValue.doubleAttributeValue(1.23456); + attribute.match( + new Function<String, Object>() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Boolean, Object>() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Long, Object>() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Double, Object>() { + @Override + @Nullable + public Object apply(Double doubleValue) { + assertThat(doubleValue).isEqualTo(1.23456); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void doubleAttributeValue_DeprecatedMatchFunction() { + AttributeValue attribute = AttributeValue.doubleAttributeValue(1.23456); + attribute.match( + new Function<String, Object>() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Boolean, Object>() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Long, Object>() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a Double"); + return null; + } + }, + new Function<Object, Object>() { + @Override + @Nullable + public Object apply(Object value) { + assertThat(value).isEqualTo(1.23456); + return null; + } + }); + } + + @Test + public void attributeValue_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + AttributeValue.stringAttributeValue("MyStringAttributeValue"), + AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); + tester.addEqualityGroup( + AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); + tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); + tester.addEqualityGroup( + AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); + tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); + tester.addEqualityGroup( + AttributeValue.doubleAttributeValue(1.23456), AttributeValue.doubleAttributeValue(1.23456)); + tester.addEqualityGroup(AttributeValue.doubleAttributeValue(1.234567)); + tester.testEquals(); + } + + @Test + public void attributeValue_ToString() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.toString()).contains("MyStringAttributeValue"); + attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.toString()).contains("true"); + attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.toString()).contains("123456"); + attribute = AttributeValue.doubleAttributeValue(1.23456); + assertThat(attribute.toString()).contains("1.23456"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java new file mode 100644 index 00000000..185a5acd --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -0,0 +1,68 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BlankSpan}. */ +@RunWith(JUnit4.class) +public class BlankSpanTest { + @Test + public void hasInvalidContextAndDefaultSpanOptions() { + assertThat(BlankSpan.INSTANCE.getContext()).isEqualTo(SpanContext.INVALID); + assertThat(BlankSpan.INSTANCE.getOptions().isEmpty()).isTrue(); + } + + @Test + public void doNotCrash() { + Map<String, AttributeValue> attributes = new HashMap<String, AttributeValue>(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Map<String, AttributeValue> multipleAttributes = new HashMap<String, AttributeValue>(); + multipleAttributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + multipleAttributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(true)); + multipleAttributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123)); + // Tests only that all the methods are not crashing/throwing errors. + BlankSpan.INSTANCE.putAttribute( + "MyStringAttributeKey2", AttributeValue.stringAttributeValue("MyStringAttributeValue2")); + BlankSpan.INSTANCE.addAttributes(attributes); + BlankSpan.INSTANCE.addAttributes(multipleAttributes); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation"); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation", attributes); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation", multipleAttributes); + BlankSpan.INSTANCE.addAnnotation(Annotation.fromDescription("MyAnnotation")); + BlankSpan.INSTANCE.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); + BlankSpan.INSTANCE.addMessageEvent(MessageEvent.builder(MessageEvent.Type.SENT, 1L).build()); + BlankSpan.INSTANCE.addLink( + Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD_LINKED_SPAN)); + BlankSpan.INSTANCE.setStatus(Status.OK); + BlankSpan.INSTANCE.end(EndSpanOptions.DEFAULT); + BlankSpan.INSTANCE.end(); + } + + @Test + public void blankSpan_ToString() { + assertThat(BlankSpan.INSTANCE.toString()).isEqualTo("BlankSpan"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java new file mode 100644 index 00000000..6b16c3d0 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -0,0 +1,294 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +import io.grpc.Context; +import io.opencensus.common.Scope; +import io.opencensus.trace.unsafe.ContextUtils; +import java.util.concurrent.Callable; +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 CurrentSpanUtils}. */ +@RunWith(JUnit4.class) +public class CurrentSpanUtilsTest { + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. + private void executeRunnableAndExpectError(Runnable runnable, Throwable error) { + boolean called = false; + try { + CurrentSpanUtils.withSpan(span, true, runnable).run(); + } catch (Throwable e) { + assertThat(e).isEqualTo(error); + called = true; + } + assertThat(called).isTrue(); + } + + // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. + private void executeCallableAndExpectError(Callable<Object> callable, Throwable error) { + boolean called = false; + try { + CurrentSpanUtils.withSpan(span, true, callable).call(); + } catch (Throwable e) { + assertThat(e).isEqualTo(error); + called = true; + } + assertThat(called).isTrue(); + } + + @Test + public void getCurrentSpan_WhenNoContext() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void getCurrentSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); + // Make sure context is detached even if test fails. + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + Context.current().detach(origContext); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpan_CloseDetaches() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Scope ws = CurrentSpanUtils.withSpan(span, false); + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + ws.close(); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + verifyZeroInteractions(span); + } + + @Test + public void withSpan_CloseDetachesAndEndsSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Scope ss = CurrentSpanUtils.withSpan(span, true); + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void withSpanRunnable() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } + }; + CurrentSpanUtils.withSpan(span, false, runnable).run(); + verifyZeroInteractions(span); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_EndSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } + }; + CurrentSpanUtils.withSpan(span, true, runnable).run(); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_WithError() { + final AssertionError error = new AssertionError("MyError"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeRunnableAndExpectError(runnable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_WithErrorNoMessage() { + final AssertionError error = new AssertionError(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeRunnableAndExpectError(runnable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable() throws Exception { + final Object ret = new Object(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + return ret; + } + }; + assertThat(CurrentSpanUtils.withSpan(span, false, callable).call()).isEqualTo(ret); + verifyZeroInteractions(span); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_EndSpan() throws Exception { + final Object ret = new Object(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + return ret; + } + }; + assertThat(CurrentSpanUtils.withSpan(span, true, callable).call()).isEqualTo(ret); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithException() { + final Exception exception = new Exception("MyException"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw exception; + } + }; + executeCallableAndExpectError(callable, exception); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyException")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithExceptionNoMessage() { + final Exception exception = new Exception(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw exception; + } + }; + executeCallableAndExpectError(callable, exception); + verify(span).setStatus(Status.UNKNOWN.withDescription("Exception")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithError() { + final AssertionError error = new AssertionError("MyError"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeCallableAndExpectError(callable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithErrorNoMessage() { + final AssertionError error = new AssertionError(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable<Object> callable = + new Callable<Object>() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeCallableAndExpectError(callable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java new file mode 100644 index 00000000..b6ab8e0e --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -0,0 +1,80 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link EndSpanOptions}. */ +@RunWith(JUnit4.class) +public class EndSpanOptionsTest { + @Test + public void endSpanOptions_DefaultOptions() { + assertThat(EndSpanOptions.DEFAULT.getStatus()).isNull(); + assertThat(EndSpanOptions.DEFAULT.getSampleToLocalSpanStore()).isFalse(); + } + + @Test + public void setStatus_Ok() { + EndSpanOptions endSpanOptions = EndSpanOptions.builder().setStatus(Status.OK).build(); + assertThat(endSpanOptions.getStatus()).isEqualTo(Status.OK); + } + + @Test + public void setStatus_Error() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.getStatus()) + .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); + } + + @Test + public void setSampleToLocalSpanStore() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder().setSampleToLocalSpanStore(true).build(); + assertThat(endSpanOptions.getSampleToLocalSpanStore()).isTrue(); + } + + @Test + public void endSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(), + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build()); + tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); + tester.testEquals(); + } + + @Test + public void endSpanOptions_ToString() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java new file mode 100644 index 00000000..5c1ebf5d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/LinkTest.java @@ -0,0 +1,112 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.Link.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class LinkTest { + private final Map<String, AttributeValue> attributesMap = new HashMap<String, AttributeValue>(); + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + + @Before + public void setUp() { + attributesMap.put("MyAttributeKey0", AttributeValue.stringAttributeValue("MyStringAttribute")); + attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); + attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); + } + + @Test + public void fromSpanContext_ChildLink() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); + } + + @Test + public void fromSpanContext_ChildLink_WithAttributes() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN, attributesMap); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); + assertThat(link.getAttributes()).isEqualTo(attributesMap); + } + + @Test + public void fromSpanContext_ParentLink() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); + } + + @Test + public void fromSpanContext_ParentLink_WithAttributes() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); + assertThat(link.getAttributes()).isEqualTo(attributesMap); + } + + @Test + public void link_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap), + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap)); + tester.testEquals(); + } + + @Test + public void link_ToString() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN, attributesMap); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("CHILD_LINKED_SPAN"); + assertThat(link.toString()).contains(attributesMap.toString()); + link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("PARENT_LINKED_SPAN"); + assertThat(link.toString()).contains(attributesMap.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java b/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java new file mode 100644 index 00000000..3444d2b3 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2018, 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import java.nio.charset.Charset; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link io.opencensus.trace.LowerCaseBase16Encoding}. */ +@RunWith(JUnit4.class) +public class LowerCaseBase16EncodingTest { + private static final Charset CHARSET = Charset.forName("UTF-8"); + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void valid_EncodeDecode() { + testEncoding("", ""); + testEncoding("f", "66"); + testEncoding("fo", "666f"); + testEncoding("foo", "666f6f"); + testEncoding("foob", "666f6f62"); + testEncoding("fooba", "666f6f6261"); + testEncoding("foobar", "666f6f626172"); + } + + @Test + public void invalidDecodings_UnrecongnizedCharacters() { + // These contain bytes not in the decoding. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid character g"); + LowerCaseBase16Encoding.decodeToBytes("efhg"); + } + + @Test + public void invalidDecodings_InvalidInputLength() { + // Valid base16 strings always have an even length. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 3"); + LowerCaseBase16Encoding.decodeToBytes("abc"); + } + + @Test + public void invalidDecodings_InvalidInputLengthAndCharacter() { + // These have a combination of invalid length and unrecognized characters. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 1"); + LowerCaseBase16Encoding.decodeToBytes("?"); + } + + private static void testEncoding(String decoded, String encoded) { + testEncodes(decoded, encoded); + testDecodes(encoded, decoded); + } + + private static void testEncodes(String decoded, String encoded) { + assertThat(LowerCaseBase16Encoding.encodeToString(decoded.getBytes(CHARSET))) + .isEqualTo(encoded); + } + + private static void testDecodes(String encoded, String decoded) { + assertThat(LowerCaseBase16Encoding.decodeToBytes(encoded)).isEqualTo(decoded.getBytes(CHARSET)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/MessageEventTest.java b/api/src/test/java/io/opencensus/trace/MessageEventTest.java new file mode 100644 index 00000000..fde32fe6 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/MessageEventTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2018, 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MessageEvent}. */ +@RunWith(JUnit4.class) +public class MessageEventTest { + @Test(expected = NullPointerException.class) + public void buildMessageEvent_NullType() { + MessageEvent.builder(null, 1L).build(); + } + + @Test + public void buildMessageEvent_WithRequiredFields() { + MessageEvent messageEvent = MessageEvent.builder(MessageEvent.Type.SENT, 1L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(0L); + } + + @Test + public void buildMessageEvent_WithUncompressedMessageSize() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L).setUncompressedMessageSize(123L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildMessageEvent_WithCompressedMessageSize() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L).setCompressedMessageSize(123L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getCompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildMessageEvent_WithAllValues() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.RECEIVED, 1L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.RECEIVED); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(123L); + assertThat(messageEvent.getCompressedMessageSize()).isEqualTo(63L); + } + + @Test + public void messageEvent_ToString() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(messageEvent.toString()).contains("type=SENT"); + assertThat(messageEvent.toString()).contains("messageId=1"); + assertThat(messageEvent.toString()).contains("compressedMessageSize=63"); + assertThat(messageEvent.toString()).contains("uncompressedMessageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java new file mode 100644 index 00000000..8c132377 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java @@ -0,0 +1,118 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Timestamp; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NetworkEvent}. */ +@RunWith(JUnit4.class) +public class NetworkEventTest { + @Test(expected = NullPointerException.class) + public void buildNetworkEvent_NullType() { + NetworkEvent.builder(null, 1L).build(); + } + + @Test + public void buildNetworkEvent_WithRequiredFields() { + NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithTimestamp() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithUncompressedMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setUncompressedMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithCompressedMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setCompressedMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getCompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithAllValues() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + // Test that getMessageSize returns same as getUncompressedMessageSize(); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getCompressedMessageSize()).isEqualTo(63L); + } + + @Test + public void networkEvent_ToString() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); + assertThat(networkEvent.toString()).contains("type=SENT"); + assertThat(networkEvent.toString()).contains("messageId=1"); + assertThat(networkEvent.toString()).contains("compressedMessageSize=63"); + assertThat(networkEvent.toString()).contains("uncompressedMessageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/NoopSpan.java b/api/src/test/java/io/opencensus/trace/NoopSpan.java new file mode 100644 index 00000000..a21a8aac --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/NoopSpan.java @@ -0,0 +1,69 @@ +/* + * 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.trace; + +import io.opencensus.internal.Utils; +import java.util.EnumSet; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Class to be used in tests where an implementation for the Span is needed. + * + * <p>Not final to allow Mockito to "spy" this class. + */ +public class NoopSpan extends Span { + + /** Creates a new {@code NoopSpan}. */ + public NoopSpan(SpanContext context, @Nullable EnumSet<Options> options) { + super(Utils.checkNotNull(context, "context"), options); + } + + @Override + public void putAttributes(Map<String, AttributeValue> attributes) { + Utils.checkNotNull(attributes, "attributes"); + } + + @Override + public void addAnnotation(String description, Map<String, AttributeValue> attributes) { + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(attributes, "attributes"); + } + + @Override + public void addAnnotation(Annotation annotation) { + Utils.checkNotNull(annotation, "annotation"); + } + + @Override + public void addNetworkEvent(NetworkEvent networkEvent) {} + + @Override + public void addMessageEvent(MessageEvent messageEvent) { + Utils.checkNotNull(messageEvent, "messageEvent"); + } + + @Override + public void addLink(Link link) { + Utils.checkNotNull(link, "link"); + } + + @Override + public void end(EndSpanOptions options) { + Utils.checkNotNull(options, "options"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java new file mode 100644 index 00000000..839c8945 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -0,0 +1,104 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.opencensus.common.Scope; +import io.opencensus.trace.Span.Kind; +import io.opencensus.trace.samplers.Samplers; +import java.util.Collections; +import java.util.concurrent.Callable; +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 SpanBuilder}. */ +@RunWith(JUnit4.class) +// Need to suppress warnings for MustBeClosed because Java-6 does not support try-with-resources. +@SuppressWarnings("MustBeClosedChecker") +public class SpanBuilderTest { + private final Tracer tracer = Tracing.getTracer(); + @Mock private SpanBuilder spanBuilder; + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(spanBuilder.startSpan()).thenReturn(span); + } + + @Test + public void startScopedSpan() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + Scope scope = spanBuilder.startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + scope.close(); + } + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startSpanAndRun() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + spanBuilder.startSpanAndRun( + new Runnable() { + @Override + public void run() { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } + }); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startSpanAndCall() throws Exception { + final Object ret = new Object(); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat( + spanBuilder.startSpanAndCall( + new Callable<Object>() { + @Override + public Object call() throws Exception { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + return ret; + } + })) + .isEqualTo(ret); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void doNotCrash_NoopImplementation() throws Exception { + SpanBuilder spanBuilder = tracer.spanBuilder("MySpanName"); + spanBuilder.setParentLinks(Collections.<Span>emptyList()); + spanBuilder.setRecordEvents(true); + spanBuilder.setSampler(Samplers.alwaysSample()); + spanBuilder.setSpanKind(Kind.SERVER); + assertThat(spanBuilder.startSpan()).isSameAs(BlankSpan.INSTANCE); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java new file mode 100644 index 00000000..54e188c8 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -0,0 +1,133 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanContext}. */ +@RunWith(JUnit4.class) +public class SpanContextTest { + private static final byte[] firstTraceIdBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondTraceIdBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, '0', 0, 0, 0, 0, 0, 0, 0, 0}; + private static final byte[] firstSpanIdBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondSpanIdBytes = new byte[] {'0', 0, 0, 0, 0, 0, 0, 0}; + private static final Tracestate firstTracestate = Tracestate.builder().set("foo", "bar").build(); + private static final Tracestate secondTracestate = Tracestate.builder().set("foo", "baz").build(); + private static final SpanContext first = + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.DEFAULT, + firstTracestate); + private static final SpanContext second = + SpanContext.create( + TraceId.fromBytes(secondTraceIdBytes), + SpanId.fromBytes(secondSpanIdBytes), + TraceOptions.builder().setIsSampled(true).build(), + secondTracestate); + + @Test + public void invalidSpanContext() { + assertThat(SpanContext.INVALID.getTraceId()).isEqualTo(TraceId.INVALID); + assertThat(SpanContext.INVALID.getSpanId()).isEqualTo(SpanId.INVALID); + assertThat(SpanContext.INVALID.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT); + } + + @Test + public void isValid() { + assertThat(SpanContext.INVALID.isValid()).isFalse(); + assertThat( + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), SpanId.INVALID, TraceOptions.DEFAULT) + .isValid()) + .isFalse(); + assertThat( + SpanContext.create( + TraceId.INVALID, SpanId.fromBytes(firstSpanIdBytes), TraceOptions.DEFAULT) + .isValid()) + .isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getTraceId() { + assertThat(first.getTraceId()).isEqualTo(TraceId.fromBytes(firstTraceIdBytes)); + assertThat(second.getTraceId()).isEqualTo(TraceId.fromBytes(secondTraceIdBytes)); + } + + @Test + public void getSpanId() { + assertThat(first.getSpanId()).isEqualTo(SpanId.fromBytes(firstSpanIdBytes)); + assertThat(second.getSpanId()).isEqualTo(SpanId.fromBytes(secondSpanIdBytes)); + } + + @Test + public void getTraceOptions() { + assertThat(first.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT); + assertThat(second.getTraceOptions()) + .isEqualTo(TraceOptions.builder().setIsSampled(true).build()); + } + + @Test + public void getTracestate() { + assertThat(first.getTracestate()).isEqualTo(firstTracestate); + assertThat(second.getTracestate()).isEqualTo(secondTracestate); + } + + @Test + public void spanContext_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + first, + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.DEFAULT), + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.builder().setIsSampled(false).build(), + firstTracestate)); + tester.addEqualityGroup( + second, + SpanContext.create( + TraceId.fromBytes(secondTraceIdBytes), + SpanId.fromBytes(secondSpanIdBytes), + TraceOptions.builder().setIsSampled(true).build(), + secondTracestate)); + tester.testEquals(); + } + + @Test + public void spanContext_ToString() { + assertThat(first.toString()).contains(TraceId.fromBytes(firstTraceIdBytes).toString()); + assertThat(first.toString()).contains(SpanId.fromBytes(firstSpanIdBytes).toString()); + assertThat(first.toString()).contains(TraceOptions.DEFAULT.toString()); + assertThat(second.toString()).contains(TraceId.fromBytes(secondTraceIdBytes).toString()); + assertThat(second.toString()).contains(SpanId.fromBytes(secondSpanIdBytes).toString()); + assertThat(second.toString()) + .contains(TraceOptions.builder().setIsSampled(true).build().toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java new file mode 100644 index 00000000..4a5bc2ae --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanIdTest.java @@ -0,0 +1,90 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanId}. */ +@RunWith(JUnit4.class) +public class SpanIdTest { + private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 'A'}; + private static final SpanId first = SpanId.fromBytes(firstBytes); + private static final SpanId second = SpanId.fromBytes(secondBytes); + + @Test + public void invalidSpanId() { + assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); + } + + @Test + public void isValid() { + assertThat(SpanId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void fromLowerBase16() { + assertThat(SpanId.fromLowerBase16("0000000000000000")).isEqualTo(SpanId.INVALID); + assertThat(SpanId.fromLowerBase16("0000000000000061")).isEqualTo(first); + assertThat(SpanId.fromLowerBase16("ff00000000000041")).isEqualTo(second); + } + + @Test + public void toLowerBase16() { + assertThat(SpanId.INVALID.toLowerBase16()).isEqualTo("0000000000000000"); + assertThat(first.toLowerBase16()).isEqualTo("0000000000000061"); + assertThat(second.toLowerBase16()).isEqualTo("ff00000000000041"); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); + tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); + assertThat(first.toString()).contains("0000000000000061"); + assertThat(second.toString()).contains("ff00000000000041"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java new file mode 100644 index 00000000..f7546ca4 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -0,0 +1,119 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; + +import java.util.Collections; +import java.util.EnumSet; +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.Mockito; + +/** Unit tests for {@link Span}. */ +@RunWith(JUnit4.class) +public class SpanTest { + private Random random; + private SpanContext spanContext; + private SpanContext notSampledSpanContext; + private EnumSet<Span.Options> spanOptions; + + @Before + public void setUp() { + random = new Random(1234); + spanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.builder().setIsSampled(true).build()); + notSampledSpanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.DEFAULT); + spanOptions = EnumSet.of(Span.Options.RECORD_EVENTS); + } + + @Test(expected = NullPointerException.class) + public void newSpan_WithNullContext() { + new NoopSpan(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void newSpan_SampledContextAndNullOptions() { + new NoopSpan(spanContext, null); + } + + @Test(expected = IllegalArgumentException.class) + public void newSpan_SampledContextAndEmptyOptions() { + new NoopSpan(spanContext, EnumSet.noneOf(Span.Options.class)); + } + + @Test + public void getOptions_WhenNullOptions() { + Span span = new NoopSpan(notSampledSpanContext, null); + assertThat(span.getOptions()).isEmpty(); + } + + @Test + public void getContextAndOptions() { + Span span = new NoopSpan(spanContext, spanOptions); + assertThat(span.getContext()).isEqualTo(spanContext); + assertThat(span.getOptions()).isEqualTo(spanOptions); + } + + @Test + public void putAttributeCallsAddAttributesByDefault() { + Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); + span.putAttribute("MyKey", AttributeValue.booleanAttributeValue(true)); + span.end(); + verify(span) + .putAttributes( + eq(Collections.singletonMap("MyKey", AttributeValue.booleanAttributeValue(true)))); + } + + @Test + public void endCallsEndWithDefaultOptions() { + Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); + span.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void addMessageEventDefaultImplementation() { + Span mockSpan = Mockito.mock(Span.class); + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 123) + .setUncompressedMessageSize(456) + .setCompressedMessageSize(789) + .build(); + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 123) + .setUncompressedMessageSize(456) + .setCompressedMessageSize(789) + .build(); + Mockito.doCallRealMethod().when(mockSpan).addMessageEvent(messageEvent); + mockSpan.addMessageEvent(messageEvent); + verify(mockSpan).addNetworkEvent(eq(networkEvent)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/StatusTest.java b/api/src/test/java/io/opencensus/trace/StatusTest.java new file mode 100644 index 00000000..108db2d2 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/StatusTest.java @@ -0,0 +1,54 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Status}. */ +@RunWith(JUnit4.class) +public class StatusTest { + @Test + public void status_Ok() { + assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); + assertThat(Status.OK.getDescription()).isNull(); + assertThat(Status.OK.isOk()).isTrue(); + } + + @Test + public void createStatus_WithDescription() { + Status status = Status.UNKNOWN.withDescription("This is an error."); + assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); + assertThat(status.getDescription()).isEqualTo("This is an error."); + assertThat(status.isOk()).isFalse(); + } + + @Test + public void status_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); + tester.addEqualityGroup( + Status.CANCELLED.withDescription("ThisIsAnError"), + Status.CANCELLED.withDescription("ThisIsAnError")); + tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java new file mode 100644 index 00000000..1c3f07d5 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -0,0 +1,59 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.internal.ZeroTimeClock; +import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceComponent}. */ +@RunWith(JUnit4.class) +public class TraceComponentTest { + @Test + public void defaultTracer() { + assertThat(TraceComponent.newNoopTraceComponent().getTracer()).isSameAs(Tracer.getNoopTracer()); + } + + @Test + public void defaultBinaryPropagationHandler() { + assertThat(TraceComponent.newNoopTraceComponent().getPropagationComponent()) + .isSameAs(PropagationComponent.getNoopPropagationComponent()); + } + + @Test + public void defaultClock() { + assertThat(TraceComponent.newNoopTraceComponent().getClock()).isInstanceOf(ZeroTimeClock.class); + } + + @Test + public void defaultTraceExporter() { + assertThat(TraceComponent.newNoopTraceComponent().getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } + + @Test + public void defaultTraceConfig() { + assertThat(TraceComponent.newNoopTraceComponent().getTraceConfig()) + .isSameAs(TraceConfig.getNoopTraceConfig()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java new file mode 100644 index 00000000..c8b5dc8f --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceIdTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2016-17, 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceId}. */ +@RunWith(JUnit4.class) +public class TraceIdTest { + private static final byte[] firstBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = + new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; + private static final TraceId first = TraceId.fromBytes(firstBytes); + private static final TraceId second = TraceId.fromBytes(secondBytes); + + @Test + public void invalidTraceId() { + assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); + } + + @Test + public void isValid() { + assertThat(TraceId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void fromLowerBase16() { + assertThat(TraceId.fromLowerBase16("00000000000000000000000000000000")) + .isEqualTo(TraceId.INVALID); + assertThat(TraceId.fromLowerBase16("00000000000000000000000000000061")).isEqualTo(first); + assertThat(TraceId.fromLowerBase16("ff000000000000000000000000000041")).isEqualTo(second); + } + + @Test + public void toLowerBase16() { + assertThat(TraceId.INVALID.toLowerBase16()).isEqualTo("00000000000000000000000000000000"); + assertThat(first.toLowerBase16()).isEqualTo("00000000000000000000000000000061"); + assertThat(second.toLowerBase16()).isEqualTo("ff000000000000000000000000000041"); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); + tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); + assertThat(first.toString()).contains("00000000000000000000000000000061"); + assertThat(second.toString()).contains("ff000000000000000000000000000041"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java new file mode 100644 index 00000000..3c46d097 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -0,0 +1,98 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceOptions}. */ +@RunWith(JUnit4.class) +public class TraceOptionsTest { + private static final byte FIRST_BYTE = (byte) 0xff; + private static final byte SECOND_BYTE = 1; + private static final byte THIRD_BYTE = 6; + + @Test + public void getOptions() { + assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled(false).build().getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled(true).build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.builder().setIsSampled(true).setIsSampled(false).build().getOptions()) + .isEqualTo(0); + assertThat(TraceOptions.fromByte(FIRST_BYTE).getOptions()).isEqualTo(-1); + assertThat(TraceOptions.fromByte(SECOND_BYTE).getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromByte(THIRD_BYTE).getOptions()).isEqualTo(6); + } + + @Test + public void isSampled() { + assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); + assertThat(TraceOptions.builder().setIsSampled(true).build().isSampled()).isTrue(); + } + + @Test + public void toFromByte() { + assertThat(TraceOptions.fromByte(FIRST_BYTE).getByte()).isEqualTo(FIRST_BYTE); + assertThat(TraceOptions.fromByte(SECOND_BYTE).getByte()).isEqualTo(SECOND_BYTE); + assertThat(TraceOptions.fromByte(THIRD_BYTE).getByte()).isEqualTo(THIRD_BYTE); + } + + @Test + @SuppressWarnings("deprecation") + public void deprecated_fromBytes() { + assertThat(TraceOptions.fromBytes(new byte[] {FIRST_BYTE}).getByte()).isEqualTo(FIRST_BYTE); + assertThat(TraceOptions.fromBytes(new byte[] {1, FIRST_BYTE}, 1).getByte()) + .isEqualTo(FIRST_BYTE); + } + + @Test + @SuppressWarnings("deprecation") + public void deprecated_getBytes() { + assertThat(TraceOptions.fromByte(FIRST_BYTE).getBytes()).isEqualTo(new byte[] {FIRST_BYTE}); + } + + @Test + public void builder_FromOptions() { + assertThat( + TraceOptions.builder(TraceOptions.fromByte(THIRD_BYTE)) + .setIsSampled(true) + .build() + .getOptions()) + .isEqualTo(6 | 1); + } + + @Test + public void traceOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceOptions.DEFAULT); + tester.addEqualityGroup( + TraceOptions.fromByte(SECOND_BYTE), TraceOptions.builder().setIsSampled(true).build()); + tester.addEqualityGroup(TraceOptions.fromByte(FIRST_BYTE)); + tester.testEquals(); + } + + @Test + public void traceOptions_ToString() { + assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); + assertThat(TraceOptions.builder().setIsSampled(true).build().toString()) + .contains("sampled=true"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java new file mode 100644 index 00000000..58dd4bbe --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -0,0 +1,174 @@ +/* + * 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.trace; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import io.opencensus.common.Scope; +import java.util.concurrent.Callable; +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 Tracer}. */ +@RunWith(JUnit4.class) +// Need to suppress warnings for MustBeClosed because Java-6 does not support try-with-resources. +@SuppressWarnings("MustBeClosedChecker") +public class TracerTest { + private static final Tracer noopTracer = Tracer.getNoopTracer(); + private static final String SPAN_NAME = "MySpanName"; + @Mock private Tracer tracer; + @Mock private SpanBuilder spanBuilder; + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void defaultGetCurrentSpan() { + assertThat(noopTracer.getCurrentSpan()).isEqualTo(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void withSpan_NullSpan() { + noopTracer.withSpan(null); + } + + @Test + public void getCurrentSpan_WithSpan() { + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + Scope ws = noopTracer.withSpan(span); + try { + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); + } finally { + ws.close(); + } + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void wrapRunnable() { + Runnable runnable; + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + runnable = + tracer.withSpan( + span, + new Runnable() { + @Override + public void run() { + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); + } + }); + // When we run the runnable we will have the span in the current Context. + runnable.run(); + verifyZeroInteractions(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void wrapCallable() throws Exception { + final Object ret = new Object(); + Callable<Object> callable; + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + callable = + tracer.withSpan( + span, + new Callable<Object>() { + @Override + public Object call() throws Exception { + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); + return ret; + } + }); + // When we call the callable we will have the span in the current Context. + assertThat(callable.call()).isEqualTo(ret); + verifyZeroInteractions(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithName_NullName() { + noopTracer.spanBuilder(null); + } + + @Test + public void defaultSpanBuilderWithName() { + assertThat(noopTracer.spanBuilder(SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithParentAndName_NullName() { + noopTracer.spanBuilderWithExplicitParent(null, null); + } + + @Test + public void defaultSpanBuilderWithParentAndName() { + assertThat(noopTracer.spanBuilderWithExplicitParent(SPAN_NAME, null).startSpan()) + .isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithRemoteParent_NullName() { + noopTracer.spanBuilderWithRemoteParent(null, null); + } + + @Test + public void defaultSpanBuilderWithRemoteParent_NullParent() { + assertThat(noopTracer.spanBuilderWithRemoteParent(SPAN_NAME, null).startSpan()) + .isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void defaultSpanBuilderWithRemoteParent() { + assertThat(noopTracer.spanBuilderWithRemoteParent(SPAN_NAME, SpanContext.INVALID).startSpan()) + .isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startSpanWithParentFromContext() { + Scope ws = tracer.withSpan(span); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(span))) + .thenReturn(spanBuilder); + assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); + } finally { + ws.close(); + } + } + + @Test + public void startSpanWithInvalidParentFromContext() { + Scope ws = tracer.withSpan(BlankSpan.INSTANCE); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(BlankSpan.INSTANCE))) + .thenReturn(spanBuilder); + assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); + } finally { + ws.close(); + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracestateTest.java b/api/src/test/java/io/opencensus/trace/TracestateTest.java new file mode 100644 index 00000000..3374eb75 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracestateTest.java @@ -0,0 +1,235 @@ +/* + * Copyright 2018, 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.Tracestate.Entry; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Tracestate}. */ +@RunWith(JUnit4.class) +public class TracestateTest { + private static final String FIRST_KEY = "key_1"; + private static final String SECOND_KEY = "key_2"; + private static final String FIRST_VALUE = "value.1"; + private static final String SECOND_VALUE = "value.2"; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final Tracestate EMPTY = Tracestate.builder().build(); + private final Tracestate firstTracestate = EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).build(); + private final Tracestate secondTracestate = + EMPTY.toBuilder().set(SECOND_KEY, SECOND_VALUE).build(); + private final Tracestate multiValueTracestate = + EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).set(SECOND_KEY, SECOND_VALUE).build(); + + @Test + public void get() { + assertThat(firstTracestate.get(FIRST_KEY)).isEqualTo(FIRST_VALUE); + assertThat(secondTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + assertThat(multiValueTracestate.get(FIRST_KEY)).isEqualTo(FIRST_VALUE); + assertThat(multiValueTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + } + + @Test + public void getEntries() { + assertThat(firstTracestate.getEntries()).containsExactly(Entry.create(FIRST_KEY, FIRST_VALUE)); + assertThat(secondTracestate.getEntries()) + .containsExactly(Entry.create(SECOND_KEY, SECOND_VALUE)); + assertThat(multiValueTracestate.getEntries()) + .containsExactly( + Entry.create(FIRST_KEY, FIRST_VALUE), Entry.create(SECOND_KEY, SECOND_VALUE)); + } + + @Test + public void disallowsNullKey() { + thrown.expect(NullPointerException.class); + EMPTY.toBuilder().set(null, FIRST_VALUE).build(); + } + + @Test + public void invalidFirstKeyCharacter() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set("1_key", FIRST_VALUE).build(); + } + + @Test + public void invalidKeyCharacters() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set("kEy_1", FIRST_VALUE).build(); + } + + @Test + public void invalidKeySize() { + char[] chars = new char[257]; + Arrays.fill(chars, 'a'); + String longKey = new String(chars); + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(longKey, FIRST_VALUE).build(); + } + + @Test + public void allAllowedKeyCharacters() { + StringBuilder stringBuilder = new StringBuilder(); + for (char c = 'a'; c <= 'z'; c++) { + stringBuilder.append(c); + } + for (char c = '0'; c <= '9'; c++) { + stringBuilder.append(c); + } + stringBuilder.append('_'); + stringBuilder.append('-'); + stringBuilder.append('*'); + stringBuilder.append('/'); + String allowedKey = stringBuilder.toString(); + assertThat(EMPTY.toBuilder().set(allowedKey, FIRST_VALUE).build().get(allowedKey)) + .isEqualTo(FIRST_VALUE); + } + + @Test + public void disallowsNullValue() { + thrown.expect(NullPointerException.class); + EMPTY.toBuilder().set(FIRST_KEY, null).build(); + } + + @Test + public void valueCannotContainEqual() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "my_vakue=5").build(); + } + + @Test + public void valueCannotContainComma() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "first,second").build(); + } + + @Test + public void valueCannotContainTrailingSpaces() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "first ").build(); + } + + @Test + public void invalidValueSize() { + char[] chars = new char[257]; + Arrays.fill(chars, 'a'); + String longValue = new String(chars); + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, longValue).build(); + } + + @Test + public void allAllowedValueCharacters() { + StringBuilder stringBuilder = new StringBuilder(); + for (char c = ' ' /* '\u0020' */; c <= '~' /* '\u007E' */; c++) { + if (c == ',' || c == '=') { + continue; + } + stringBuilder.append(c); + } + String allowedValue = stringBuilder.toString(); + assertThat(EMPTY.toBuilder().set(FIRST_KEY, allowedValue).build().get(FIRST_KEY)) + .isEqualTo(allowedValue); + } + + @Test + public void addEntry() { + assertThat(firstTracestate.toBuilder().set(SECOND_KEY, SECOND_VALUE).build()) + .isEqualTo(multiValueTracestate); + } + + @Test + public void updateEntry() { + assertThat(firstTracestate.toBuilder().set(FIRST_KEY, SECOND_VALUE).build().get(FIRST_KEY)) + .isEqualTo(SECOND_VALUE); + Tracestate updatedMultiValueTracestate = + multiValueTracestate.toBuilder().set(FIRST_KEY, SECOND_VALUE).build(); + assertThat(updatedMultiValueTracestate.get(FIRST_KEY)).isEqualTo(SECOND_VALUE); + assertThat(updatedMultiValueTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + } + + @Test + public void addAndUpdateEntry() { + assertThat( + firstTracestate + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .set(SECOND_KEY, FIRST_VALUE) // add a new entry + .build() + .getEntries()) + .containsExactly( + Entry.create(FIRST_KEY, SECOND_VALUE), Entry.create(SECOND_KEY, FIRST_VALUE)); + } + + @Test + public void addSameKey() { + assertThat( + EMPTY + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .set(FIRST_KEY, FIRST_VALUE) // add a new entry + .build() + .getEntries()) + .containsExactly(Entry.create(FIRST_KEY, FIRST_VALUE)); + } + + @Test + public void remove() { + assertThat(multiValueTracestate.toBuilder().remove(SECOND_KEY).build()) + .isEqualTo(firstTracestate); + } + + @Test + public void addAndRemoveEntry() { + assertThat( + EMPTY + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .remove(FIRST_KEY) // add a new entry + .build()) + .isEqualTo(EMPTY); + } + + @Test + public void remove_NullNotAllowed() { + thrown.expect(NullPointerException.class); + multiValueTracestate.toBuilder().remove(null).build(); + } + + @Test + public void tracestate_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(EMPTY, EMPTY); + tester.addEqualityGroup(firstTracestate, EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).build()); + tester.addEqualityGroup( + secondTracestate, EMPTY.toBuilder().set(SECOND_KEY, SECOND_VALUE).build()); + tester.testEquals(); + } + + @Test + public void tracestate_ToString() { + assertThat(EMPTY.toString()).isEqualTo("Tracestate{entries=[]}"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java new file mode 100644 index 00000000..e7c93a95 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2016-17, 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.trace; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Tracing}. */ +@RunWith(JUnit4.class) +public class TracingTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadTraceComponent_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Tracing.loadTraceComponent( + new ClassLoader() { + @Override + public Class<?> loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadTraceComponent_IgnoresMissingClasses() { + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + assertThat(Tracing.loadTraceComponent(classLoader).getClass().getName()) + .isEqualTo("io.opencensus.trace.TraceComponent$NoopTraceComponent"); + } + + @Test + public void defaultTracer() { + assertThat(Tracing.getTracer()).isSameAs(Tracer.getNoopTracer()); + } + + @Test + public void defaultBinaryPropagationHandler() { + assertThat(Tracing.getPropagationComponent()) + .isSameAs(PropagationComponent.getNoopPropagationComponent()); + } + + @Test + public void defaultTraceExporter() { + assertThat(Tracing.getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } + + @Test + public void defaultTraceConfig() { + assertThat(Tracing.getTraceConfig()).isSameAs(TraceConfig.getNoopTraceConfig()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java new file mode 100644 index 00000000..d48e0894 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java @@ -0,0 +1,51 @@ +/* + * 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.trace.config; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.samplers.Samplers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceConfig}. */ +@RunWith(JUnit4.class) +public class TraceConfigTest { + TraceConfig traceConfig = TraceConfig.getNoopTraceConfig(); + + @Test + public void activeTraceParams_NoOpImplementation() { + assertThat(traceConfig.getActiveTraceParams()).isEqualTo(TraceParams.DEFAULT); + } + + @Test + public void updateActiveTraceParams_NoOpImplementation() { + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setSampler(Samplers.alwaysSample()) + .setMaxNumberOfAttributes(8) + .setMaxNumberOfAnnotations(9) + .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfMessageEvents(10) + .setMaxNumberOfLinks(11) + .build(); + traceConfig.updateActiveTraceParams(traceParams); + assertThat(traceConfig.getActiveTraceParams()).isEqualTo(TraceParams.DEFAULT); + } +} diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java new file mode 100644 index 00000000..bdf07d53 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -0,0 +1,97 @@ +/* + * 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.trace.config; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.samplers.Samplers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceParams}. */ +@RunWith(JUnit4.class) +public class TraceParamsTest { + @Test + public void defaultTraceParams() { + assertThat(TraceParams.DEFAULT.getSampler()).isEqualTo(Samplers.probabilitySampler(1e-4)); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAttributes()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfMessageEvents()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(32); + } + + @Test(expected = NullPointerException.class) + public void updateTraceParams_NullSampler() { + TraceParams.DEFAULT.toBuilder().setSampler(null).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAttributes() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAnnotations() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfNetworkEvents() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfMessageEvents() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfMessageEvents(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfLinks() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(0).build(); + } + + @Test + public void updateTraceParams_All() { + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setSampler(Samplers.alwaysSample()) + .setMaxNumberOfAttributes(8) + .setMaxNumberOfAnnotations(9) + .setMaxNumberOfMessageEvents(10) + .setMaxNumberOfLinks(11) + .build(); + assertThat(traceParams.getSampler()).isEqualTo(Samplers.alwaysSample()); + assertThat(traceParams.getMaxNumberOfAttributes()).isEqualTo(8); + assertThat(traceParams.getMaxNumberOfAnnotations()).isEqualTo(9); + // test maxNumberOfNetworkEvent can be set via maxNumberOfMessageEvent + assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + assertThat(traceParams.getMaxNumberOfMessageEvents()).isEqualTo(10); + assertThat(traceParams.getMaxNumberOfLinks()).isEqualTo(11); + } + + @Test + public void updateTraceParams_maxNumberOfNetworkEvents() { + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(10).build(); + assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + // test maxNumberOfMessageEvent can be set via maxNumberOfNetworkEvent + assertThat(traceParams.getMaxNumberOfMessageEvents()).isEqualTo(10); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java new file mode 100644 index 00000000..d7f385d0 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -0,0 +1,46 @@ +/* + * 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.trace.export; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ExportComponent}. */ +@RunWith(JUnit4.class) +public class ExportComponentTest { + private final ExportComponent exportComponent = ExportComponent.newNoopExportComponent(); + + @Test + public void implementationOfSpanExporter() { + assertThat(exportComponent.getSpanExporter()).isEqualTo(SpanExporter.getNoopSpanExporter()); + } + + @Test + public void implementationOfActiveSpans() { + assertThat(exportComponent.getRunningSpanStore()) + .isEqualTo(RunningSpanStore.getNoopRunningSpanStore()); + } + + @Test + public void implementationOfSampledSpanStore() { + assertThat(exportComponent.getSampledSpanStore()) + .isInstanceOf(SampledSpanStore.newNoopSampledSpanStore().getClass()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java new file mode 100644 index 00000000..960da27c --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java @@ -0,0 +1,55 @@ +/* + * 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.trace.export; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.Collection; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopRunningSpanStore}. */ +@RunWith(JUnit4.class) +public final class NoopRunningSpanStoreTest { + + private final RunningSpanStore runningSpanStore = + ExportComponent.newNoopExportComponent().getRunningSpanStore(); + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void noopRunningSpanStore_GetSummary() { + RunningSpanStore.Summary summary = runningSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()).isEmpty(); + } + + @Test + public void noopRunningSpanStore_GetRunningSpans_DisallowsNull() { + thrown.expect(NullPointerException.class); + runningSpanStore.getRunningSpans(null); + } + + @Test + public void noopRunningSpanStore_GetRunningSpans() { + Collection<SpanData> runningSpans = + runningSpanStore.getRunningSpans(RunningSpanStore.Filter.create("TestSpan", 0)); + assertThat(runningSpans).isEmpty(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java new file mode 100644 index 00000000..6e9c7b0f --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java @@ -0,0 +1,94 @@ +/* + * 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.trace.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.opencensus.trace.Status.CanonicalCode; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopSampledSpanStore}. */ +@RunWith(JUnit4.class) +public final class NoopSampledSpanStoreTest { + + private static final SampledSpanStore.PerSpanNameSummary EMPTY_PER_SPAN_NAME_SUMMARY = + SampledSpanStore.PerSpanNameSummary.create( + Collections.<SampledSpanStore.LatencyBucketBoundaries, Integer>emptyMap(), + Collections.<CanonicalCode, Integer>emptyMap()); + + @Test + public void noopSampledSpanStore_RegisterUnregisterAndGetSummary() { + // should return empty before register + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + SampledSpanStore.Summary summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()).isEmpty(); + + // should return non-empty summaries with zero latency/error sampled spans after register + sampledSpanStore.registerSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan1", "TestSpan2", "TestSpan3"))); + summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()) + .containsExactly( + "TestSpan1", EMPTY_PER_SPAN_NAME_SUMMARY, + "TestSpan2", EMPTY_PER_SPAN_NAME_SUMMARY, + "TestSpan3", EMPTY_PER_SPAN_NAME_SUMMARY); + + // should unregister specific spanNames + sampledSpanStore.unregisterSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan1", "TestSpan3"))); + summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()) + .containsExactly("TestSpan2", EMPTY_PER_SPAN_NAME_SUMMARY); + } + + @Test + public void noopSampledSpanStore_GetLatencySampledSpans() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + Collection<SpanData> latencySampledSpans = + sampledSpanStore.getLatencySampledSpans( + SampledSpanStore.LatencyFilter.create("TestLatencyFilter", 0, 0, 0)); + assertThat(latencySampledSpans).isEmpty(); + } + + @Test + public void noopSampledSpanStore_GetErrorSampledSpans() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + Collection<SpanData> errorSampledSpans = + sampledSpanStore.getErrorSampledSpans( + SampledSpanStore.ErrorFilter.create("TestErrorFilter", null, 0)); + assertThat(errorSampledSpans).isEmpty(); + } + + @Test + public void noopSampledSpanStore_GetRegisteredSpanNamesForCollection() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + sampledSpanStore.registerSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan3", "TestSpan4"))); + Set<String> registeredSpanNames = sampledSpanStore.getRegisteredSpanNamesForCollection(); + assertThat(registeredSpanNames).containsExactly("TestSpan3", "TestSpan4"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java new file mode 100644 index 00000000..b991d145 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -0,0 +1,321 @@ +/* + * 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.trace.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Link; +import io.opencensus.trace.Link.Type; +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.Span.Kind; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.export.SpanData.Attributes; +import io.opencensus.trace.export.SpanData.Links; +import io.opencensus.trace.export.SpanData.TimedEvent; +import io.opencensus.trace.export.SpanData.TimedEvents; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanData}. */ +@RunWith(JUnit4.class) +public class SpanDataTest { + private static final Timestamp startTimestamp = Timestamp.create(123, 456); + private static final Timestamp eventTimestamp1 = Timestamp.create(123, 457); + private static final Timestamp eventTimestamp2 = Timestamp.create(123, 458); + private static final Timestamp eventTimestamp3 = Timestamp.create(123, 459); + private static final Timestamp endTimestamp = Timestamp.create(123, 460); + private static final String SPAN_NAME = "MySpanName"; + private static final String ANNOTATION_TEXT = "MyAnnotationText"; + private static final Annotation annotation = Annotation.fromDescription(ANNOTATION_TEXT); + private static final NetworkEvent recvNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).build(); + private static final NetworkEvent sentNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); + private static final MessageEvent recvMessageEvent = + MessageEvent.builder(MessageEvent.Type.RECEIVED, 1).build(); + private static final MessageEvent sentMessageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1).build(); + private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); + private static final int CHILD_SPAN_COUNT = 13; + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final Map<String, AttributeValue> attributesMap = new HashMap<String, AttributeValue>(); + private final List<TimedEvent<Annotation>> annotationsList = + new ArrayList<TimedEvent<Annotation>>(); + private final List<TimedEvent<NetworkEvent>> networkEventsList = + new ArrayList<SpanData.TimedEvent<NetworkEvent>>(); + private final List<TimedEvent<MessageEvent>> messageEventsList = + new ArrayList<SpanData.TimedEvent<MessageEvent>>(); + private final List<Link> linksList = new ArrayList<Link>(); + + private Attributes attributes; + private TimedEvents<Annotation> annotations; + private TimedEvents<NetworkEvent> networkEvents; + private TimedEvents<MessageEvent> messageEvents; + private Links links; + + @Before + public void setUp() { + attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); + attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); + attributes = Attributes.create(attributesMap, 1); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp1, annotation)); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp3, annotation)); + annotations = TimedEvents.create(annotationsList, 2); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); + networkEvents = TimedEvents.create(networkEventsList, 3); + messageEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvMessageEvent)); + messageEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentMessageEvent)); + messageEvents = TimedEvents.create(messageEventsList, 3); + linksList.add(Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)); + links = Links.create(linksList, 0); + } + + @Test + public void spanData_AllValues() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + true, + SPAN_NAME, + Kind.SERVER, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getKind()).isEqualTo(Kind.SERVER); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isEqualTo(CHILD_SPAN_COUNT); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanData_Create_Compatibility() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + true, + SPAN_NAME, + null, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isEqualTo(CHILD_SPAN_COUNT); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanData_RootActiveSpan() { + SpanData spanData = + SpanData.create( + spanContext, + null, + null, + SPAN_NAME, + null, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + null, + null, + null); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isNull(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isNull(); + assertThat(spanData.getStatus()).isNull(); + assertThat(spanData.getEndTimestamp()).isNull(); + } + + @Test + public void spanData_AllDataEmpty() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + false, + SPAN_NAME, + null, + startTimestamp, + Attributes.create(Collections.<String, AttributeValue>emptyMap(), 0), + TimedEvents.create(Collections.<SpanData.TimedEvent<Annotation>>emptyList(), 0), + TimedEvents.create(Collections.<SpanData.TimedEvent<MessageEvent>>emptyList(), 0), + Links.create(Collections.<Link>emptyList(), 0), + 0, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); + assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getMessageEvents().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); + assertThat(spanData.getChildSpanCount()).isEqualTo(0); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanDataEquals() { + SpanData allSpanData1 = + SpanData.create( + spanContext, + parentSpanId, + false, + SPAN_NAME, + Kind.CLIENT, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp); + SpanData allSpanData2 = + SpanData.create( + spanContext, + parentSpanId, + false, + SPAN_NAME, + Kind.CLIENT, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp); + SpanData emptySpanData = + SpanData.create( + spanContext, + parentSpanId, + false, + SPAN_NAME, + null, + startTimestamp, + Attributes.create(Collections.<String, AttributeValue>emptyMap(), 0), + TimedEvents.create(Collections.<SpanData.TimedEvent<Annotation>>emptyList(), 0), + TimedEvents.create(Collections.<SpanData.TimedEvent<MessageEvent>>emptyList(), 0), + Links.create(Collections.<Link>emptyList(), 0), + 0, + status, + endTimestamp); + new EqualsTester() + .addEqualityGroup(allSpanData1, allSpanData2) + .addEqualityGroup(emptySpanData) + .testEquals(); + } + + @Test + public void spanData_ToString() { + String spanDataString = + SpanData.create( + spanContext, + parentSpanId, + false, + SPAN_NAME, + Kind.CLIENT, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp) + .toString(); + assertThat(spanDataString).contains(spanContext.toString()); + assertThat(spanDataString).contains(parentSpanId.toString()); + assertThat(spanDataString).contains(SPAN_NAME); + assertThat(spanDataString).contains(Kind.CLIENT.toString()); + assertThat(spanDataString).contains(startTimestamp.toString()); + assertThat(spanDataString).contains(attributes.toString()); + assertThat(spanDataString).contains(annotations.toString()); + assertThat(spanDataString).contains(messageEvents.toString()); + assertThat(spanDataString).contains(links.toString()); + assertThat(spanDataString).contains(status.toString()); + assertThat(spanDataString).contains(endTimestamp.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java new file mode 100644 index 00000000..4f8c8508 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.trace.internal; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BaseMessageEventUtils}. */ +@RunWith(JUnit4.class) +public class BaseMessageEventUtilsTest { + private static final long SENT_EVENT_ID = 12345L; + private static final long RECV_EVENT_ID = 67890L; + private static final long UNCOMPRESSED_SIZE = 100; + private static final long COMPRESSED_SIZE = 99; + + private static final MessageEvent SENT_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final MessageEvent RECV_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent SENT_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent RECV_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + + @Test + public void networkEventToMessageEvent() { + assertThat(BaseMessageEventUtils.asMessageEvent(SENT_NETWORK_EVENT)) + .isEqualTo(SENT_MESSAGE_EVENT); + assertThat(BaseMessageEventUtils.asMessageEvent(RECV_NETWORK_EVENT)) + .isEqualTo(RECV_MESSAGE_EVENT); + } + + @Test + public void messageEventToNetworkEvent() { + assertThat(BaseMessageEventUtils.asNetworkEvent(SENT_MESSAGE_EVENT)) + .isEqualTo(SENT_NETWORK_EVENT); + assertThat(BaseMessageEventUtils.asNetworkEvent(RECV_MESSAGE_EVENT)) + .isEqualTo(RECV_NETWORK_EVENT); + } +} diff --git a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java new file mode 100644 index 00000000..64544ffe --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java @@ -0,0 +1,71 @@ +/* + * 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.trace.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.SpanContext; +import java.text.ParseException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BinaryFormat}. */ +@RunWith(JUnit4.class) +public class BinaryFormatTest { + private static final BinaryFormat binaryFormat = BinaryFormat.getNoopBinaryFormat(); + + @Test(expected = NullPointerException.class) + public void toBinaryValue_NullSpanContext() { + binaryFormat.toBinaryValue(null); + } + + @Test + public void toBinaryValue_NotNullSpanContext() { + assertThat(binaryFormat.toBinaryValue(SpanContext.INVALID)).isEqualTo(new byte[0]); + } + + @Test(expected = NullPointerException.class) + public void toByteArray_NullSpanContext() { + binaryFormat.toByteArray(null); + } + + @Test + public void toByteArray_NotNullSpanContext() { + assertThat(binaryFormat.toByteArray(SpanContext.INVALID)).isEqualTo(new byte[0]); + } + + @Test(expected = NullPointerException.class) + public void fromBinaryValue_NullInput() throws ParseException { + binaryFormat.fromBinaryValue(null); + } + + @Test + public void fromBinaryValue_NotNullInput() throws ParseException { + assertThat(binaryFormat.fromBinaryValue(new byte[0])).isEqualTo(SpanContext.INVALID); + } + + @Test(expected = NullPointerException.class) + public void fromByteArray_NullInput() throws SpanContextParseException { + binaryFormat.fromByteArray(null); + } + + @Test + public void fromByteArray_NotNullInput() throws SpanContextParseException { + assertThat(binaryFormat.fromByteArray(new byte[0])).isEqualTo(SpanContext.INVALID); + } +} diff --git a/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java new file mode 100644 index 00000000..ba64e98e --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java @@ -0,0 +1,36 @@ +/* + * 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.trace.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link PropagationComponent}. */ +@RunWith(JUnit4.class) +public class PropagationComponentTest { + private final PropagationComponent propagationComponent = + PropagationComponent.getNoopPropagationComponent(); + + @Test + public void implementationOfBinaryFormat() { + assertThat(propagationComponent.getBinaryFormat()) + .isEqualTo(BinaryFormat.getNoopBinaryFormat()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java b/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java new file mode 100644 index 00000000..92efb35d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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.trace.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanContextParseException}. */ +@RunWith(JUnit4.class) +public class SpanContextParseExceptionTest { + + @Test + public void createWithMessage() { + assertThat(new SpanContextParseException("my message").getMessage()).isEqualTo("my message"); + } + + @Test + public void createWithMessageAndCause() { + IOException cause = new IOException(); + SpanContextParseException parseException = new SpanContextParseException("my message", cause); + assertThat(parseException.getMessage()).isEqualTo("my message"); + assertThat(parseException.getCause()).isEqualTo(cause); + } +} diff --git a/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java new file mode 100644 index 00000000..c2e6e127 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java @@ -0,0 +1,75 @@ +/* + * 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.trace.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.propagation.TextFormat.Getter; +import io.opencensus.trace.propagation.TextFormat.Setter; +import javax.annotation.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TextFormat}. */ +@RunWith(JUnit4.class) +public class TextFormatTest { + private static final TextFormat textFormat = TextFormat.getNoopTextFormat(); + + @Test(expected = NullPointerException.class) + public void inject_NullSpanContext() { + textFormat.inject( + null, + new Object(), + new Setter<Object>() { + @Override + public void put(Object carrier, String key, String value) {} + }); + } + + @Test + public void inject_NotNullSpanContext_DoesNotFail() { + textFormat.inject( + SpanContext.INVALID, + new Object(), + new Setter<Object>() { + @Override + public void put(Object carrier, String key, String value) {} + }); + } + + @Test(expected = NullPointerException.class) + public void fromHeaders_NullGetter() throws SpanContextParseException { + textFormat.extract(new Object(), null); + } + + @Test + public void fromHeaders_NotNullGetter() throws SpanContextParseException { + assertThat( + textFormat.extract( + new Object(), + new Getter<Object>() { + @Nullable + @Override + public String get(Object carrier, String key) { + return null; + } + })) + .isSameAs(SpanContext.INVALID); + } +} diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java new file mode 100644 index 00000000..7a46e97a --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -0,0 +1,281 @@ +/* + * 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.trace.samplers; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.NoopSpan; +import io.opencensus.trace.Sampler; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Samplers}. */ +@RunWith(JUnit4.class) +public class SamplersTest { + private static final String SPAN_NAME = "MySpanName"; + private static final int NUM_SAMPLE_TRIES = 1000; + private final Random random = new Random(1234); + private final TraceId traceId = TraceId.generateRandomId(random); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final SpanId spanId = SpanId.generateRandomId(random); + private final SpanContext sampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled(true).build()); + private final SpanContext notSampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); + private final Span sampledSpan = + new NoopSpan(sampledSpanContext, EnumSet.of(Span.Options.RECORD_EVENTS)); + + @Test + public void alwaysSampleSampler_AlwaysReturnTrue() { + // Sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "Another name", + Collections.<Span>emptyList())) + .isTrue(); + // Not sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "Yet another name", + Collections.<Span>emptyList())) + .isTrue(); + } + + @Test + public void alwaysSampleSampler_ToString() { + assertThat(Samplers.alwaysSample().toString()).isEqualTo("AlwaysSampleSampler"); + } + + @Test + public void neverSampleSampler_AlwaysReturnFalse() { + // Sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "bar", + Collections.<Span>emptyList())) + .isFalse(); + // Not sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "quux", + Collections.<Span>emptyList())) + .isFalse(); + } + + @Test + public void neverSampleSampler_ToString() { + assertThat(Samplers.neverSample().toString()).isEqualTo("NeverSampleSampler"); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeHighProbability() { + Samplers.probabilitySampler(1.01); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeLowProbability() { + Samplers.probabilitySampler(-0.00001); + } + + // Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs. + private static void assertSamplerSamplesWithProbability( + Sampler sampler, SpanContext parent, List<Span> parentLinks, double probability) { + Random random = new Random(1234); + int count = 0; // Count of spans with sampling enabled + for (int i = 0; i < NUM_SAMPLE_TRIES; i++) { + if (sampler.shouldSample( + parent, + false, + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + SPAN_NAME, + parentLinks)) { + count++; + } + } + double proportionSampled = (double) count / NUM_SAMPLE_TRIES; + // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. + assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1) + .isTrue(); + } + + @Test + public void probabilitySampler_DifferentProbabilities_NotSampledParent() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + assertSamplerSamplesWithProbability( + neverSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + assertSamplerSamplesWithProbability( + alwaysSample, notSampledSpanContext, Collections.<Span>emptyList(), 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.5); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.2); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, notSampledSpanContext, Collections.<Span>emptyList(), 2.0 / 3.0); + } + + @Test + public void probabilitySampler_DifferentProbabilities_SampledParent() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + assertSamplerSamplesWithProbability( + neverSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + assertSamplerSamplesWithProbability( + alwaysSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0); + } + + @Test + public void probabilitySampler_DifferentProbabilities_SampledParentLink() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + assertSamplerSamplesWithProbability( + neverSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + assertSamplerSamplesWithProbability( + alwaysSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + } + + @Test + public void probabilitySampler_SampleBasedOnTraceId() { + final Sampler defaultProbability = Samplers.probabilitySampler(0.0001); + // 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 notSampledtraceId = + 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 + }); + assertThat( + defaultProbability.shouldSample( + null, + false, + notSampledtraceId, + SpanId.generateRandomId(random), + SPAN_NAME, + Collections.<Span>emptyList())) + .isFalse(); + // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long + // is less than probability * Long.MAX_VALUE; + TraceId sampledtraceId = + TraceId.fromBytes( + new byte[] { + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }); + assertThat( + defaultProbability.shouldSample( + null, + false, + sampledtraceId, + SpanId.generateRandomId(random), + SPAN_NAME, + Collections.<Span>emptyList())) + .isTrue(); + } + + @Test + public void probabilitySampler_getDescription() { + assertThat((Samplers.probabilitySampler(0.5)).getDescription()) + .isEqualTo(String.format("ProbabilitySampler{%.6f}", 0.5)); + } + + @Test + public void probabilitySampler_ToString() { + assertThat((Samplers.probabilitySampler(0.5)).toString()).contains("0.5"); + } +} |