aboutsummaryrefslogtreecommitdiff
path: root/api/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'api/src/test')
-rw-r--r--api/src/test/java/io/opencensus/common/DurationTest.java152
-rw-r--r--api/src/test/java/io/opencensus/common/FunctionsTest.java64
-rw-r--r--api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java155
-rw-r--r--api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java56
-rw-r--r--api/src/test/java/io/opencensus/common/ServerStatsTest.java78
-rw-r--r--api/src/test/java/io/opencensus/common/TimeUtilsTest.java60
-rw-r--r--api/src/test/java/io/opencensus/common/TimestampTest.java217
-rw-r--r--api/src/test/java/io/opencensus/internal/ProviderTest.java114
-rw-r--r--api/src/test/java/io/opencensus/internal/StringUtilsTest.java35
-rw-r--r--api/src/test/java/io/opencensus/internal/UtilsTest.java144
-rw-r--r--api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java89
-rw-r--r--api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java89
-rw-r--r--api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java88
-rw-r--r--api/src/test/java/io/opencensus/metrics/LabelKeyTest.java86
-rw-r--r--api/src/test/java/io/opencensus/metrics/LabelValueTest.java74
-rw-r--r--api/src/test/java/io/opencensus/metrics/LongGaugeTest.java87
-rw-r--r--api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java220
-rw-r--r--api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java40
-rw-r--r--api/src/test/java/io/opencensus/metrics/MetricsTest.java71
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/DistributionTest.java331
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java33
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java103
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java80
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/MetricTest.java180
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/PointTest.java69
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/SummaryTest.java189
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java151
-rw-r--r--api/src/test/java/io/opencensus/metrics/export/ValueTest.java168
-rw-r--r--api/src/test/java/io/opencensus/stats/AggregationDataTest.java231
-rw-r--r--api/src/test/java/io/opencensus/stats/AggregationTest.java97
-rw-r--r--api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java87
-rw-r--r--api/src/test/java/io/opencensus/stats/MeasureTest.java129
-rw-r--r--api/src/test/java/io/opencensus/stats/NoopStatsTest.java133
-rw-r--r--api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java186
-rw-r--r--api/src/test/java/io/opencensus/stats/StatsTest.java85
-rw-r--r--api/src/test/java/io/opencensus/stats/ViewDataTest.java301
-rw-r--r--api/src/test/java/io/opencensus/stats/ViewTest.java164
-rw-r--r--api/src/test/java/io/opencensus/tags/InternalUtilsTest.java44
-rw-r--r--api/src/test/java/io/opencensus/tags/NoopTagsTest.java179
-rw-r--r--api/src/test/java/io/opencensus/tags/TagContextTest.java103
-rw-r--r--api/src/test/java/io/opencensus/tags/TagKeyTest.java80
-rw-r--r--api/src/test/java/io/opencensus/tags/TagTest.java46
-rw-r--r--api/src/test/java/io/opencensus/tags/TagValueTest.java75
-rw-r--r--api/src/test/java/io/opencensus/tags/TagsTest.java85
-rw-r--r--api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java44
-rw-r--r--api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java44
-rw-r--r--api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java62
-rw-r--r--api/src/test/java/io/opencensus/trace/AnnotationTest.java102
-rw-r--r--api/src/test/java/io/opencensus/trace/AttributeValueTest.java233
-rw-r--r--api/src/test/java/io/opencensus/trace/BlankSpanTest.java68
-rw-r--r--api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java294
-rw-r--r--api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java80
-rw-r--r--api/src/test/java/io/opencensus/trace/LinkTest.java112
-rw-r--r--api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java83
-rw-r--r--api/src/test/java/io/opencensus/trace/MessageEventTest.java84
-rw-r--r--api/src/test/java/io/opencensus/trace/NetworkEventTest.java118
-rw-r--r--api/src/test/java/io/opencensus/trace/NoopSpan.java69
-rw-r--r--api/src/test/java/io/opencensus/trace/SpanBuilderTest.java104
-rw-r--r--api/src/test/java/io/opencensus/trace/SpanContextTest.java133
-rw-r--r--api/src/test/java/io/opencensus/trace/SpanIdTest.java90
-rw-r--r--api/src/test/java/io/opencensus/trace/SpanTest.java119
-rw-r--r--api/src/test/java/io/opencensus/trace/StatusTest.java54
-rw-r--r--api/src/test/java/io/opencensus/trace/TraceComponentTest.java59
-rw-r--r--api/src/test/java/io/opencensus/trace/TraceIdTest.java93
-rw-r--r--api/src/test/java/io/opencensus/trace/TraceOptionsTest.java98
-rw-r--r--api/src/test/java/io/opencensus/trace/TracerTest.java174
-rw-r--r--api/src/test/java/io/opencensus/trace/TracestateTest.java235
-rw-r--r--api/src/test/java/io/opencensus/trace/TracingTest.java83
-rw-r--r--api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java51
-rw-r--r--api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java97
-rw-r--r--api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java46
-rw-r--r--api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java55
-rw-r--r--api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java94
-rw-r--r--api/src/test/java/io/opencensus/trace/export/SpanDataTest.java321
-rw-r--r--api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java71
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java71
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java36
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java42
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java75
-rw-r--r--api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java281
80 files changed, 9123 insertions, 0 deletions
diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java
new file mode 100644
index 00000000..ea636ca0
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/DurationTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 Duration}. */
+@RunWith(JUnit4.class)
+public class DurationTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testDurationCreate() {
+ assertThat(Duration.create(24, 42).getSeconds()).isEqualTo(24);
+ assertThat(Duration.create(24, 42).getNanos()).isEqualTo(42);
+ assertThat(Duration.create(-24, -42).getSeconds()).isEqualTo(-24);
+ assertThat(Duration.create(-24, -42).getNanos()).isEqualTo(-42);
+ assertThat(Duration.create(315576000000L, 999999999).getSeconds()).isEqualTo(315576000000L);
+ assertThat(Duration.create(315576000000L, 999999999).getNanos()).isEqualTo(999999999);
+ assertThat(Duration.create(-315576000000L, -999999999).getSeconds()).isEqualTo(-315576000000L);
+ assertThat(Duration.create(-315576000000L, -999999999).getNanos()).isEqualTo(-999999999);
+ }
+
+ @Test
+ public void create_SecondsTooLow() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001");
+ Duration.create(-315576000001L, 0);
+ }
+
+ @Test
+ public void create_SecondsTooHigh() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001");
+ Duration.create(315576000001L, 0);
+ }
+
+ @Test
+ public void create_NanosTooLow() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is less than minimum (-999999999): -1000000000");
+ Duration.create(0, -1000000000);
+ }
+
+ @Test
+ public void create_NanosTooHigh() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000");
+ Duration.create(0, 1000000000);
+ }
+
+ @Test
+ public void create_NegativeSecondsPositiveNanos() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' and 'nanos' have inconsistent sign: seconds=-1, nanos=1");
+ Duration.create(-1, 1);
+ }
+
+ @Test
+ public void create_PositiveSecondsNegativeNanos() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' and 'nanos' have inconsistent sign: seconds=1, nanos=-1");
+ Duration.create(1, -1);
+ }
+
+ @Test
+ public void testDurationFromMillis() {
+ assertThat(Duration.fromMillis(0)).isEqualTo(Duration.create(0, 0));
+ assertThat(Duration.fromMillis(987)).isEqualTo(Duration.create(0, 987000000));
+ assertThat(Duration.fromMillis(3456)).isEqualTo(Duration.create(3, 456000000));
+ }
+
+ @Test
+ public void testDurationFromMillisNegative() {
+ assertThat(Duration.fromMillis(-1)).isEqualTo(Duration.create(0, -1000000));
+ assertThat(Duration.fromMillis(-999)).isEqualTo(Duration.create(0, -999000000));
+ assertThat(Duration.fromMillis(-1000)).isEqualTo(Duration.create(-1, 0));
+ assertThat(Duration.fromMillis(-3456)).isEqualTo(Duration.create(-3, -456000000));
+ }
+
+ @Test
+ public void fromMillis_TooLow() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001");
+ Duration.fromMillis(-315576000001000L);
+ }
+
+ @Test
+ public void fromMillis_TooHigh() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001");
+ Duration.fromMillis(315576000001000L);
+ }
+
+ @Test
+ public void duration_CompareLength() {
+ assertThat(Duration.create(0, 0).compareTo(Duration.create(0, 0))).isEqualTo(0);
+ assertThat(Duration.create(24, 42).compareTo(Duration.create(24, 42))).isEqualTo(0);
+ assertThat(Duration.create(-24, -42).compareTo(Duration.create(-24, -42))).isEqualTo(0);
+ assertThat(Duration.create(25, 42).compareTo(Duration.create(24, 42))).isEqualTo(1);
+ assertThat(Duration.create(24, 45).compareTo(Duration.create(24, 42))).isEqualTo(1);
+ assertThat(Duration.create(24, 42).compareTo(Duration.create(25, 42))).isEqualTo(-1);
+ assertThat(Duration.create(24, 42).compareTo(Duration.create(24, 45))).isEqualTo(-1);
+ assertThat(Duration.create(-24, -45).compareTo(Duration.create(-24, -42))).isEqualTo(-1);
+ assertThat(Duration.create(-24, -42).compareTo(Duration.create(-25, -42))).isEqualTo(1);
+ assertThat(Duration.create(24, 42).compareTo(Duration.create(-24, -42))).isEqualTo(1);
+ }
+
+ @Test
+ public void testDurationEqual() {
+ // Positive tests.
+ assertThat(Duration.create(0, 0)).isEqualTo(Duration.create(0, 0));
+ assertThat(Duration.create(24, 42)).isEqualTo(Duration.create(24, 42));
+ assertThat(Duration.create(-24, -42)).isEqualTo(Duration.create(-24, -42));
+ // Negative tests.
+ assertThat(Duration.create(25, 42)).isNotEqualTo(Duration.create(24, 42));
+ assertThat(Duration.create(24, 43)).isNotEqualTo(Duration.create(24, 42));
+ assertThat(Duration.create(-25, -42)).isNotEqualTo(Duration.create(-24, -42));
+ assertThat(Duration.create(-24, -43)).isNotEqualTo(Duration.create(-24, -42));
+ }
+
+ @Test
+ public void toMillis() {
+ assertThat(Duration.create(10, 0).toMillis()).isEqualTo(10000L);
+ assertThat(Duration.create(10, 1000).toMillis()).isEqualTo(10000L);
+ assertThat(Duration.create(0, (int) 1e6).toMillis()).isEqualTo(1L);
+ assertThat(Duration.create(0, 0).toMillis()).isEqualTo(0L);
+ assertThat(Duration.create(-10, 0).toMillis()).isEqualTo(-10000L);
+ assertThat(Duration.create(-10, -1000).toMillis()).isEqualTo(-10000L);
+ assertThat(Duration.create(0, -(int) 1e6).toMillis()).isEqualTo(-1L);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java
new file mode 100644
index 00000000..55d58d4d
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link Functions}. */
+@RunWith(JUnit4.class)
+public class FunctionsTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testReturnNull() {
+ assertThat(Functions.returnNull().apply("ignored")).isNull();
+ }
+
+ @Test
+ public void testReturnConstant() {
+ assertThat(Functions.returnConstant(123).apply("ignored")).isEqualTo(123);
+ }
+
+ @Test
+ public void testReturnToString() {
+ assertThat(Functions.returnToString().apply("input")).isEqualTo("input");
+ assertThat(Functions.returnToString().apply(Boolean.FALSE)).isEqualTo("false");
+ assertThat(Functions.returnToString().apply(Double.valueOf(123.45))).isEqualTo("123.45");
+ assertThat(Functions.returnToString().apply(null)).isEqualTo(null);
+ }
+
+ @Test
+ public void testThrowIllegalArgumentException() {
+ Function<Object, Void> f = Functions.throwIllegalArgumentException();
+ thrown.expect(IllegalArgumentException.class);
+ f.apply("ignored");
+ }
+
+ @Test
+ public void testThrowAssertionError() {
+ Function<Object, Void> f = Functions.throwAssertionError();
+ thrown.handleAssertionErrors();
+ thrown.expect(AssertionError.class);
+ f.apply("ignored");
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java b/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java
new file mode 100644
index 00000000..6db14a79
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+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 ServerStatsEncoding}. */
+@RunWith(JUnit4.class)
+public class ServerStatsEncodingTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void encodeDecodeTest() throws ServerStatsDeserializationException {
+ ServerStats serverStatsToBeEncoded = null;
+ ServerStats serverStatsDecoded = null;
+ byte[] serialized = null;
+
+ serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+ serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized);
+ assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded);
+
+ serverStatsToBeEncoded = ServerStats.create(0, 22, (byte) 0);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+ serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized);
+ assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded);
+
+ serverStatsToBeEncoded = ServerStats.create(450, 0, (byte) 0);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+ serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized);
+ assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded);
+ }
+
+ @Test
+ public void skipUnknownFieldTest() throws ServerStatsDeserializationException {
+ ServerStats serverStatsToBeEncoded = null;
+ ServerStats serverStatsDecoded = null;
+ byte[] serialized = null;
+
+ serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+
+ // Add new field at the end.
+ byte[] serializedExpanded = new byte[serialized.length + 9];
+ System.arraycopy(serialized, 0, serializedExpanded, 0, serialized.length);
+ final ByteBuffer bb = ByteBuffer.wrap(serializedExpanded);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.position(serialized.length);
+ bb.put((byte) 255);
+ bb.putLong(0L);
+ byte[] newSerialized = bb.array();
+
+ serverStatsDecoded = ServerStatsEncoding.parseBytes(newSerialized);
+ assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded);
+ }
+
+ @Test
+ public void negativeLbLatencyValueTest() throws ServerStatsDeserializationException {
+ ServerStats serverStatsToBeEncoded = null;
+ ServerStats serverStatsDecoded = null;
+ byte[] serialized = null;
+
+ serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+
+ // update serialized byte[] with negative value for lbLatency.
+ final ByteBuffer bb = ByteBuffer.wrap(serialized);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.position(2);
+ bb.putLong(-100L);
+
+ byte[] newSerialized = bb.array();
+ thrown.expect(ServerStatsDeserializationException.class);
+ thrown.expectMessage("Serialized ServiceStats contains invalid values");
+ ServerStatsEncoding.parseBytes(newSerialized);
+ }
+
+ @Test
+ public void negativeServerLatencyValueTest() throws ServerStatsDeserializationException {
+ ServerStats serverStatsToBeEncoded = null;
+ ServerStats serverStatsDecoded = null;
+ byte[] serialized = null;
+
+ serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1);
+ serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded);
+
+ // update serialized byte[] with negative value for serviceLatency.
+ final ByteBuffer bb = ByteBuffer.wrap(serialized);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.position(11);
+ bb.putLong(-101L);
+
+ byte[] newSerialized = bb.array();
+ thrown.expect(ServerStatsDeserializationException.class);
+ thrown.expectMessage("Serialized ServiceStats contains invalid values");
+ ServerStatsEncoding.parseBytes(newSerialized);
+ }
+
+ @Test
+ public void emptySerializedBuffer() throws ServerStatsDeserializationException {
+ final ByteBuffer bb = ByteBuffer.allocate(0);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+
+ byte[] newSerialized = bb.array();
+ thrown.expect(ServerStatsDeserializationException.class);
+ thrown.expectMessage("Serialized ServerStats buffer is empty");
+ ServerStatsEncoding.parseBytes(newSerialized);
+ }
+
+ @Test
+ public void invalidNegativeVersion() throws ServerStatsDeserializationException {
+ final ByteBuffer bb = ByteBuffer.allocate(10);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.put((byte) -1);
+ byte[] newSerialized = bb.array();
+ thrown.expect(ServerStatsDeserializationException.class);
+ thrown.expectMessage("Invalid ServerStats version: -1");
+ ServerStatsEncoding.parseBytes(newSerialized);
+ }
+
+ @Test
+ public void invalidCompatibleVersion() throws ServerStatsDeserializationException {
+ final ByteBuffer bb = ByteBuffer.allocate(10);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.put((byte) (ServerStatsEncoding.CURRENT_VERSION + 1));
+ byte[] newSerialized = bb.array();
+ thrown.expect(ServerStatsDeserializationException.class);
+ thrown.expectMessage(
+ "Invalid ServerStats version: " + (ServerStatsEncoding.CURRENT_VERSION + 1));
+ ServerStatsEncoding.parseBytes(newSerialized);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java b/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java
new file mode 100644
index 00000000..ed786f6c
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.common.ServerStatsFieldEnums.Id;
+import io.opencensus.common.ServerStatsFieldEnums.Size;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link ServerStatsFieldEnums}. */
+@RunWith(JUnit4.class)
+public class ServerStatsFieldEnumsTest {
+
+ @Test
+ public void enumIdValueOfTest() {
+ assertThat(Id.valueOf(0)).isEqualTo(Id.SERVER_STATS_LB_LATENCY_ID);
+ assertThat(Id.valueOf(1)).isEqualTo(Id.SERVER_STATS_SERVICE_LATENCY_ID);
+ assertThat(Id.valueOf(2)).isEqualTo(Id.SERVER_STATS_TRACE_OPTION_ID);
+ }
+
+ @Test
+ public void enumIdInvalidValueOfTest() {
+ assertThat(Id.valueOf(-1)).isNull();
+ assertThat(Id.valueOf(Id.values().length)).isNull();
+ assertThat(Id.valueOf(Id.values().length + 1)).isNull();
+ }
+
+ @Test
+ public void enumSizeValueTest() {
+ assertThat(Size.SERVER_STATS_LB_LATENCY_SIZE.value()).isEqualTo(8);
+ assertThat(Size.SERVER_STATS_SERVICE_LATENCY_SIZE.value()).isEqualTo(8);
+ assertThat(Size.SERVER_STATS_TRACE_OPTION_SIZE.value()).isEqualTo(1);
+ }
+
+ @Test
+ public void totalSizeTest() {
+ assertThat(ServerStatsFieldEnums.getTotalSize()).isEqualTo(20);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/ServerStatsTest.java b/api/src/test/java/io/opencensus/common/ServerStatsTest.java
new file mode 100644
index 00000000..620bbb4f
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/ServerStatsTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 ServerStats}. */
+@RunWith(JUnit4.class)
+public class ServerStatsTest {
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void serverStatsCreate() {
+ ServerStats serverStats = null;
+
+ serverStats = ServerStats.create(31, 22, (byte) 0);
+ assertThat(serverStats.getLbLatencyNs()).isEqualTo(31);
+ assertThat(serverStats.getServiceLatencyNs()).isEqualTo(22);
+ assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0);
+
+ serverStats = ServerStats.create(1000011L, 900022L, (byte) 1);
+ assertThat(serverStats.getLbLatencyNs()).isEqualTo(1000011L);
+ assertThat(serverStats.getServiceLatencyNs()).isEqualTo(900022L);
+ assertThat(serverStats.getTraceOption()).isEqualTo((byte) 1);
+
+ serverStats = ServerStats.create(0, 22, (byte) 0);
+ assertThat(serverStats.getLbLatencyNs()).isEqualTo(0);
+ assertThat(serverStats.getServiceLatencyNs()).isEqualTo(22);
+ assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0);
+
+ serverStats = ServerStats.create(1010, 0, (byte) 0);
+ assertThat(serverStats.getLbLatencyNs()).isEqualTo(1010);
+ assertThat(serverStats.getServiceLatencyNs()).isEqualTo(0);
+ assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0);
+ }
+
+ @Test
+ public void create_LbLatencyNegative() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'getLbLatencyNs' is less than zero");
+ ServerStats.create(-1L, 100, (byte) 0);
+ }
+
+ @Test
+ public void create_ServerLatencyNegative() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'getServiceLatencyNs' is less than zero");
+ ServerStats.create(100L, -1L, (byte) 0);
+ }
+
+ @Test
+ public void create_LbLatencyAndServerLatencyNegative() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'getLbLatencyNs' is less than zero");
+ ServerStats.create(-100L, -1L, (byte) 0);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/TimeUtilsTest.java b/api/src/test/java/io/opencensus/common/TimeUtilsTest.java
new file mode 100644
index 00000000..d6228566
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/TimeUtilsTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link TimeUtils}. */
+@RunWith(JUnit4.class)
+public final class TimeUtilsTest {
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void compareLongs() {
+ assertThat(TimeUtils.compareLongs(-1L, 1L)).isLessThan(0);
+ assertThat(TimeUtils.compareLongs(10L, 10L)).isEqualTo(0);
+ assertThat(TimeUtils.compareLongs(1L, 0L)).isGreaterThan(0);
+ }
+
+ @Test
+ public void checkedAdd_TooLow() {
+ thrown.expect(ArithmeticException.class);
+ thrown.expectMessage("Long sum overflow: x=-9223372036854775807, y=-2");
+ TimeUtils.checkedAdd(Long.MIN_VALUE + 1, -2);
+ }
+
+ @Test
+ public void checkedAdd_TooHigh() {
+ thrown.expect(ArithmeticException.class);
+ thrown.expectMessage("Long sum overflow: x=9223372036854775806, y=2");
+ TimeUtils.checkedAdd(Long.MAX_VALUE - 1, 2);
+ }
+
+ @Test
+ public void checkedAdd_Valid() {
+ assertThat(TimeUtils.checkedAdd(1, 2)).isEqualTo(3);
+ assertThat(TimeUtils.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE))
+ .isEqualTo(2L * Integer.MAX_VALUE);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java
new file mode 100644
index 00000000..b193b3c8
--- /dev/null
+++ b/api/src/test/java/io/opencensus/common/TimestampTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 Timestamp}. */
+@RunWith(JUnit4.class)
+public class TimestampTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void timestampCreate() {
+ assertThat(Timestamp.create(24, 42).getSeconds()).isEqualTo(24);
+ assertThat(Timestamp.create(24, 42).getNanos()).isEqualTo(42);
+ assertThat(Timestamp.create(-24, 42).getSeconds()).isEqualTo(-24);
+ assertThat(Timestamp.create(-24, 42).getNanos()).isEqualTo(42);
+ assertThat(Timestamp.create(315576000000L, 999999999).getSeconds()).isEqualTo(315576000000L);
+ assertThat(Timestamp.create(315576000000L, 999999999).getNanos()).isEqualTo(999999999);
+ assertThat(Timestamp.create(-315576000000L, 999999999).getSeconds()).isEqualTo(-315576000000L);
+ assertThat(Timestamp.create(-315576000000L, 999999999).getNanos()).isEqualTo(999999999);
+ }
+
+ @Test
+ public void create_SecondsTooLow() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001");
+ Timestamp.create(-315576000001L, 0);
+ }
+
+ @Test
+ public void create_SecondsTooHigh() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001");
+ Timestamp.create(315576000001L, 0);
+ }
+
+ @Test
+ public void create_NanosTooLow_PositiveTime() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is less than zero: -1");
+ Timestamp.create(1, -1);
+ }
+
+ @Test
+ public void create_NanosTooHigh_PositiveTime() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000");
+ Timestamp.create(1, 1000000000);
+ }
+
+ @Test
+ public void create_NanosTooLow_NegativeTime() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is less than zero: -1");
+ Timestamp.create(-1, -1);
+ }
+
+ @Test
+ public void create_NanosTooHigh_NegativeTime() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000");
+ Timestamp.create(-1, 1000000000);
+ }
+
+ @Test
+ public void timestampFromMillis() {
+ assertThat(Timestamp.fromMillis(0)).isEqualTo(Timestamp.create(0, 0));
+ assertThat(Timestamp.fromMillis(987)).isEqualTo(Timestamp.create(0, 987000000));
+ assertThat(Timestamp.fromMillis(3456)).isEqualTo(Timestamp.create(3, 456000000));
+ }
+
+ @Test
+ public void timestampFromMillis_Negative() {
+ assertThat(Timestamp.fromMillis(-1)).isEqualTo(Timestamp.create(-1, 999000000));
+ assertThat(Timestamp.fromMillis(-999)).isEqualTo(Timestamp.create(-1, 1000000));
+ assertThat(Timestamp.fromMillis(-3456)).isEqualTo(Timestamp.create(-4, 544000000));
+ }
+
+ @Test
+ public void fromMillis_TooLow() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001");
+ Timestamp.fromMillis(-315576000001000L);
+ }
+
+ @Test
+ public void fromMillis_TooHigh() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001");
+ Timestamp.fromMillis(315576000001000L);
+ }
+
+ @Test
+ public void timestampAddNanos() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.addNanos(0)).isEqualTo(timestamp);
+ assertThat(timestamp.addNanos(999999777)).isEqualTo(Timestamp.create(1235, 0));
+ assertThat(timestamp.addNanos(1300200500)).isEqualTo(Timestamp.create(1235, 300200723));
+ assertThat(timestamp.addNanos(1999999777)).isEqualTo(Timestamp.create(1236, 0));
+ assertThat(timestamp.addNanos(9876543789L)).isEqualTo(Timestamp.create(1243, 876544012));
+ assertThat(timestamp.addNanos(Long.MAX_VALUE))
+ .isEqualTo(Timestamp.create(1234L + 9223372036L, 223 + 854775807));
+ }
+
+ @Test
+ public void timestampAddNanos_Negative() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.addNanos(-223)).isEqualTo(Timestamp.create(1234, 0));
+ assertThat(timestamp.addNanos(-1000000223)).isEqualTo(Timestamp.create(1233, 0));
+ assertThat(timestamp.addNanos(-1300200500)).isEqualTo(Timestamp.create(1232, 699799723));
+ assertThat(timestamp.addNanos(-4123456213L)).isEqualTo(Timestamp.create(1229, 876544010));
+ assertThat(timestamp.addNanos(Long.MIN_VALUE))
+ .isEqualTo(Timestamp.create(1234L - 9223372036L - 1, 223 + 145224192));
+ }
+
+ @Test
+ public void timestampAddDuration() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.addDuration(Duration.create(1, 0))).isEqualTo(Timestamp.create(1235, 223));
+ assertThat(timestamp.addDuration(Duration.create(0, 1))).isEqualTo(Timestamp.create(1234, 224));
+ assertThat(timestamp.addDuration(Duration.create(1, 1))).isEqualTo(Timestamp.create(1235, 224));
+ assertThat(timestamp.addDuration(Duration.create(1, 999999900)))
+ .isEqualTo(Timestamp.create(1236, 123));
+ }
+
+ @Test
+ public void timestampAddDuration_Negative() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.addDuration(Duration.create(-1234, -223)))
+ .isEqualTo(Timestamp.create(0, 0));
+ assertThat(timestamp.addDuration(Duration.create(-1, 0)))
+ .isEqualTo(Timestamp.create(1233, 223));
+ assertThat(timestamp.addDuration(Duration.create(-1, -1)))
+ .isEqualTo(Timestamp.create(1233, 222));
+ assertThat(timestamp.addDuration(Duration.create(-1, -323)))
+ .isEqualTo(Timestamp.create(1232, 999999900));
+ assertThat(timestamp.addDuration(Duration.create(-33, -999999999)))
+ .isEqualTo(Timestamp.create(1200, 224));
+ }
+
+ @Test
+ public void timestampSubtractTimestamp() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(0, 0)))
+ .isEqualTo(Duration.create(1234, 223));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1233, 223)))
+ .isEqualTo(Duration.create(1, 0));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1233, 222)))
+ .isEqualTo(Duration.create(1, 1));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1232, 999999900)))
+ .isEqualTo(Duration.create(1, 323));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1200, 224)))
+ .isEqualTo(Duration.create(33, 999999999));
+ }
+
+ @Test
+ public void timestampSubtractTimestamp_NegativeResult() {
+ Timestamp timestamp = Timestamp.create(1234, 223);
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1235, 223)))
+ .isEqualTo(Duration.create(-1, 0));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1234, 224)))
+ .isEqualTo(Duration.create(0, -1));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1235, 224)))
+ .isEqualTo(Duration.create(-1, -1));
+ assertThat(timestamp.subtractTimestamp(Timestamp.create(1236, 123)))
+ .isEqualTo(Duration.create(-1, -999999900));
+ }
+
+ @Test
+ public void timestamp_CompareTo() {
+ assertThat(Timestamp.create(0, 0).compareTo(Timestamp.create(0, 0))).isEqualTo(0);
+ assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(24, 42))).isEqualTo(0);
+ assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-24, 42))).isEqualTo(0);
+ assertThat(Timestamp.create(25, 42).compareTo(Timestamp.create(24, 42))).isEqualTo(1);
+ assertThat(Timestamp.create(24, 45).compareTo(Timestamp.create(24, 42))).isEqualTo(1);
+ assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(25, 42))).isEqualTo(-1);
+ assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(24, 45))).isEqualTo(-1);
+ assertThat(Timestamp.create(-25, 42).compareTo(Timestamp.create(-24, 42))).isEqualTo(-1);
+ assertThat(Timestamp.create(-24, 45).compareTo(Timestamp.create(-24, 42))).isEqualTo(1);
+ assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-25, 42))).isEqualTo(1);
+ assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-24, 45))).isEqualTo(-1);
+ }
+
+ @Test
+ public void timestamp_Equal() {
+ // Positive tests.
+ assertThat(Timestamp.create(0, 0)).isEqualTo(Timestamp.create(0, 0));
+ assertThat(Timestamp.create(24, 42)).isEqualTo(Timestamp.create(24, 42));
+ assertThat(Timestamp.create(-24, 42)).isEqualTo(Timestamp.create(-24, 42));
+ // Negative tests.
+ assertThat(Timestamp.create(25, 42)).isNotEqualTo(Timestamp.create(24, 42));
+ assertThat(Timestamp.create(24, 43)).isNotEqualTo(Timestamp.create(24, 42));
+ assertThat(Timestamp.create(-25, 42)).isNotEqualTo(Timestamp.create(-24, 42));
+ assertThat(Timestamp.create(-24, 43)).isNotEqualTo(Timestamp.create(-24, 42));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java
new file mode 100644
index 00000000..1f4c33fa
--- /dev/null
+++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.internal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.ServiceConfigurationError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link Provider}. */
+@RunWith(JUnit4.class)
+public class ProviderTest {
+ static class GoodClass {
+ public GoodClass() {}
+ }
+
+ static class PrivateConstructorClass {
+ private PrivateConstructorClass() {}
+ }
+
+ static class NoDefaultConstructorClass {
+ public NoDefaultConstructorClass(int arg) {}
+ }
+
+ private static class PrivateClass {}
+
+ static interface MyInterface {}
+
+ static class MyInterfaceImpl implements MyInterface {
+ public MyInterfaceImpl() {}
+ }
+
+ @Test(expected = ServiceConfigurationError.class)
+ public void createInstance_ThrowsErrorWhenClassIsPrivate() throws ClassNotFoundException {
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$PrivateClass",
+ true,
+ ProviderTest.class.getClassLoader()),
+ PrivateClass.class);
+ }
+
+ @Test(expected = ServiceConfigurationError.class)
+ public void createInstance_ThrowsErrorWhenClassHasPrivateConstructor()
+ throws ClassNotFoundException {
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$PrivateConstructorClass",
+ true,
+ ProviderTest.class.getClassLoader()),
+ PrivateConstructorClass.class);
+ }
+
+ @Test(expected = ServiceConfigurationError.class)
+ public void createInstance_ThrowsErrorWhenClassDoesNotHaveDefaultConstructor()
+ throws ClassNotFoundException {
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$NoDefaultConstructorClass",
+ true,
+ ProviderTest.class.getClassLoader()),
+ NoDefaultConstructorClass.class);
+ }
+
+ @Test(expected = ServiceConfigurationError.class)
+ public void createInstance_ThrowsErrorWhenClassIsNotASubclass() throws ClassNotFoundException {
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$GoodClass",
+ true,
+ ProviderTest.class.getClassLoader()),
+ MyInterface.class);
+ }
+
+ @Test
+ public void createInstance_GoodClass() throws ClassNotFoundException {
+ assertThat(
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$GoodClass",
+ true,
+ ProviderTest.class.getClassLoader()),
+ GoodClass.class))
+ .isNotNull();
+ }
+
+ @Test
+ public void createInstance_GoodSubclass() throws ClassNotFoundException {
+ assertThat(
+ Provider.createInstance(
+ Class.forName(
+ "io.opencensus.internal.ProviderTest$MyInterfaceImpl",
+ true,
+ ProviderTest.class.getClassLoader()),
+ MyInterface.class))
+ .isNotNull();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/internal/StringUtilsTest.java b/api/src/test/java/io/opencensus/internal/StringUtilsTest.java
new file mode 100644
index 00000000..5e866940
--- /dev/null
+++ b/api/src/test/java/io/opencensus/internal/StringUtilsTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link StringUtils}. */
+@RunWith(JUnit4.class)
+public final class StringUtilsTest {
+
+ @Test
+ public void isPrintableString() {
+ assertTrue(StringUtils.isPrintableString("abcd"));
+ assertFalse(StringUtils.isPrintableString("\2ab\3cd"));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java
new file mode 100644
index 00000000..608a8fe0
--- /dev/null
+++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link Utils}. */
+@RunWith(JUnit4.class)
+public final class UtilsTest {
+ private static final String TEST_MESSAGE = "test message";
+ private static final String TEST_MESSAGE_TEMPLATE = "I ate %s eggs.";
+ private static final int TEST_MESSAGE_VALUE = 2;
+ private static final String FORMATED_SIMPLE_TEST_MESSAGE = "I ate 2 eggs.";
+ private static final String FORMATED_COMPLEX_TEST_MESSAGE = "I ate 2 eggs. [2]";
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void checkArgument() {
+ Utils.checkArgument(true, TEST_MESSAGE);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(TEST_MESSAGE);
+ Utils.checkArgument(false, TEST_MESSAGE);
+ }
+
+ @Test
+ public void checkArgument_NullErrorMessage() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("null");
+ Utils.checkArgument(false, null);
+ }
+
+ @Test
+ public void checkArgument_WithSimpleFormat() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(FORMATED_SIMPLE_TEST_MESSAGE);
+ Utils.checkArgument(false, TEST_MESSAGE_TEMPLATE, TEST_MESSAGE_VALUE);
+ }
+
+ @Test
+ public void checkArgument_WithComplexFormat() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(FORMATED_COMPLEX_TEST_MESSAGE);
+ Utils.checkArgument(false, TEST_MESSAGE_TEMPLATE, TEST_MESSAGE_VALUE, TEST_MESSAGE_VALUE);
+ }
+
+ @Test
+ public void checkState() {
+ Utils.checkNotNull(true, TEST_MESSAGE);
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage(TEST_MESSAGE);
+ Utils.checkState(false, TEST_MESSAGE);
+ }
+
+ @Test
+ public void checkState_NullErrorMessage() {
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("null");
+ Utils.checkState(false, null);
+ }
+
+ @Test
+ public void checkNotNull() {
+ Utils.checkNotNull(new Object(), TEST_MESSAGE);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(TEST_MESSAGE);
+ Utils.checkNotNull(null, TEST_MESSAGE);
+ }
+
+ @Test
+ public void checkNotNull_NullErrorMessage() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("null");
+ Utils.checkNotNull(null, null);
+ }
+
+ @Test
+ public void checkIndex_Valid() {
+ Utils.checkIndex(1, 2);
+ }
+
+ @Test
+ public void checkIndex_NegativeSize() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Negative size: -1");
+ Utils.checkIndex(0, -1);
+ }
+
+ @Test
+ public void checkIndex_NegativeIndex() {
+ thrown.expect(IndexOutOfBoundsException.class);
+ thrown.expectMessage("Index out of bounds: size=10, index=-2");
+ Utils.checkIndex(-2, 10);
+ }
+
+ @Test
+ public void checkIndex_IndexEqualToSize() {
+ thrown.expect(IndexOutOfBoundsException.class);
+ thrown.expectMessage("Index out of bounds: size=5, index=5");
+ Utils.checkIndex(5, 5);
+ }
+
+ @Test
+ public void checkIndex_IndexGreaterThanSize() {
+ thrown.expect(IndexOutOfBoundsException.class);
+ thrown.expectMessage("Index out of bounds: size=10, index=11");
+ Utils.checkIndex(11, 10);
+ }
+
+ @Test
+ public void equalsObjects_Equal() {
+ assertTrue(Utils.equalsObjects(null, null));
+ assertTrue(Utils.equalsObjects(new Date(1L), new Date(1L)));
+ }
+
+ @Test
+ public void equalsObjects_Unequal() {
+ assertFalse(Utils.equalsObjects(null, new Object()));
+ assertFalse(Utils.equalsObjects(new Object(), null));
+ assertFalse(Utils.equalsObjects(new Object(), new Object()));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java
new file mode 100644
index 00000000..dbae3c49
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.metrics;
+
+import io.opencensus.common.ToDoubleFunction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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 DerivedDoubleGauge}. */
+// TODO(mayurkale): Add more tests, once DerivedDoubleGauge plugs-in into the registry.
+@RunWith(JUnit4.class)
+public class DerivedDoubleGaugeTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String UNIT = "1";
+ private static final List<LabelKey> LABEL_KEY =
+ Collections.singletonList(LabelKey.create("key", "key description"));
+ private static final List<LabelValue> LABEL_VALUES =
+ Collections.singletonList(LabelValue.create("value"));
+ private static final List<LabelValue> EMPTY_LABEL_VALUES = new ArrayList<LabelValue>();
+
+ private final DerivedDoubleGauge derivedDoubleGauge =
+ DerivedDoubleGauge.newNoopDerivedDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ private static final ToDoubleFunction<Object> doubleFunction =
+ new ToDoubleFunction<Object>() {
+ @Override
+ public double applyAsDouble(Object value) {
+ return 5.0;
+ }
+ };
+
+ @Test
+ public void noopCreateTimeSeries_WithNullLabelValues() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ derivedDoubleGauge.createTimeSeries(null, null, doubleFunction);
+ }
+
+ @Test
+ public void noopCreateTimeSeries_WithNullElement() {
+ List<LabelValue> labelValues = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValue element should not be null.");
+ derivedDoubleGauge.createTimeSeries(labelValues, null, doubleFunction);
+ }
+
+ @Test
+ public void noopCreateTimeSeries_WithInvalidLabelSize() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Incorrect number of labels.");
+ derivedDoubleGauge.createTimeSeries(EMPTY_LABEL_VALUES, null, doubleFunction);
+ }
+
+ @Test
+ public void createTimeSeries_WithNullFunction() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("function");
+ derivedDoubleGauge.createTimeSeries(LABEL_VALUES, null, null);
+ }
+
+ @Test
+ public void noopRemoveTimeSeries_WithNullLabelValues() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ derivedDoubleGauge.removeTimeSeries(null);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java
new file mode 100644
index 00000000..6a462881
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.metrics;
+
+import io.opencensus.common.ToLongFunction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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 DerivedLongGauge}. */
+// TODO(mayurkale): Add more tests, once DerivedLongGauge plugs-in into the registry.
+@RunWith(JUnit4.class)
+public class DerivedLongGaugeTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String UNIT = "1";
+ private static final List<LabelKey> LABEL_KEY =
+ Collections.singletonList(LabelKey.create("key", "key description"));
+ private static final List<LabelValue> LABEL_VALUES =
+ Collections.singletonList(LabelValue.create("value"));
+ private static final List<LabelValue> EMPTY_LABEL_VALUES = new ArrayList<LabelValue>();
+
+ private final DerivedLongGauge derivedLongGauge =
+ DerivedLongGauge.newNoopDerivedLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ private static final ToLongFunction<Object> longFunction =
+ new ToLongFunction<Object>() {
+ @Override
+ public long applyAsLong(Object value) {
+ return 5;
+ }
+ };
+
+ @Test
+ public void noopCreateTimeSeries_WithNullLabelValues() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ derivedLongGauge.createTimeSeries(null, null, longFunction);
+ }
+
+ @Test
+ public void noopCreateTimeSeries_WithNullElement() {
+ List<LabelValue> labelValues = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValue element should not be null.");
+ derivedLongGauge.createTimeSeries(labelValues, null, longFunction);
+ }
+
+ @Test
+ public void noopCreateTimeSeries_WithInvalidLabelSize() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Incorrect number of labels.");
+ derivedLongGauge.createTimeSeries(EMPTY_LABEL_VALUES, null, longFunction);
+ }
+
+ @Test
+ public void createTimeSeries_WithNullFunction() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("function");
+ derivedLongGauge.createTimeSeries(LABEL_VALUES, null, null);
+ }
+
+ @Test
+ public void noopRemoveTimeSeries_WithNullLabelValues() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ derivedLongGauge.removeTimeSeries(null);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java
new file mode 100644
index 00000000..b0cdea7c
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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 DoubleGauge}. */
+@RunWith(JUnit4.class)
+public class DoubleGaugeTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String UNIT = "1";
+ private static final List<LabelKey> LABEL_KEY =
+ Collections.singletonList(LabelKey.create("key", "key description"));
+ private static final List<LabelValue> LABEL_VALUES =
+ Collections.singletonList(LabelValue.create("value"));
+ private static final List<LabelKey> EMPTY_LABEL_KEYS = new ArrayList<LabelKey>();
+ private static final List<LabelValue> EMPTY_LABEL_VALUES = new ArrayList<LabelValue>();
+
+ // TODO(mayurkale): Add more tests, once DoubleGauge plugs-in into the registry.
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithNullLabelValues() {
+ DoubleGauge doubleGauge =
+ DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ doubleGauge.getOrCreateTimeSeries(null);
+ }
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithNullElement() {
+ List<LabelValue> labelValues = Collections.singletonList(null);
+ DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValue element should not be null.");
+ doubleGauge.getOrCreateTimeSeries(labelValues);
+ }
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithInvalidLabelSize() {
+ DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Incorrect number of labels.");
+ doubleGauge.getOrCreateTimeSeries(EMPTY_LABEL_VALUES);
+ }
+
+ @Test
+ public void noopRemoveTimeSeries_WithNullLabelValues() {
+ DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ doubleGauge.removeTimeSeries(null);
+ }
+
+ @Test
+ public void noopSameAs() {
+ DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ assertThat(doubleGauge.getDefaultTimeSeries()).isSameAs(doubleGauge.getDefaultTimeSeries());
+ assertThat(doubleGauge.getDefaultTimeSeries())
+ .isSameAs(doubleGauge.getOrCreateTimeSeries(LABEL_VALUES));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java
new file mode 100644
index 00000000..83f2b59a
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.metrics;
+
+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 LabelKey}. */
+@RunWith(JUnit4.class)
+public class LabelKeyTest {
+
+ private static final LabelKey KEY = LabelKey.create("key", "description");
+
+ @Test
+ public void testGetKey() {
+ assertThat(KEY.getKey()).isEqualTo("key");
+ }
+
+ @Test
+ public void testGetDescription() {
+ assertThat(KEY.getDescription()).isEqualTo("description");
+ }
+
+ @Test
+ public void create_NoLengthConstraint() {
+ // We have a length constraint of 256-characters for TagKey. That constraint doesn't apply to
+ // LabelKey.
+ char[] chars = new char[300];
+ Arrays.fill(chars, 'k');
+ String key = new String(chars);
+ assertThat(LabelKey.create(key, "").getKey()).isEqualTo(key);
+ }
+
+ @Test
+ public void create_WithUnprintableChars() {
+ String key = "\2ab\3cd";
+ String description = "\4ef\5gh";
+ LabelKey labelKey = LabelKey.create(key, description);
+ assertThat(labelKey.getKey()).isEqualTo(key);
+ assertThat(labelKey.getDescription()).isEqualTo(description);
+ }
+
+ @Test
+ public void create_WithNonAsciiChars() {
+ String key = "é”®";
+ String description = "测试用键";
+ LabelKey nonAsciiKey = LabelKey.create(key, description);
+ assertThat(nonAsciiKey.getKey()).isEqualTo(key);
+ assertThat(nonAsciiKey.getDescription()).isEqualTo(description);
+ }
+
+ @Test
+ public void create_Empty() {
+ LabelKey emptyKey = LabelKey.create("", "");
+ assertThat(emptyKey.getKey()).isEmpty();
+ assertThat(emptyKey.getDescription()).isEmpty();
+ }
+
+ @Test
+ public void testLabelKeyEquals() {
+ new EqualsTester()
+ .addEqualityGroup(LabelKey.create("foo", ""), LabelKey.create("foo", ""))
+ .addEqualityGroup(LabelKey.create("foo", "description"))
+ .addEqualityGroup(LabelKey.create("bar", ""))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/LabelValueTest.java b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java
new file mode 100644
index 00000000..e5526b2f
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.metrics;
+
+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 LabelValue}. */
+@RunWith(JUnit4.class)
+public class LabelValueTest {
+
+ private static final LabelValue VALUE = LabelValue.create("value");
+ private static final LabelValue UNSET = LabelValue.create(null);
+ private static final LabelValue EMPTY = LabelValue.create("");
+
+ @Test
+ public void testGetValue() {
+ assertThat(VALUE.getValue()).isEqualTo("value");
+ assertThat(UNSET.getValue()).isNull();
+ assertThat(EMPTY.getValue()).isEmpty();
+ }
+
+ @Test
+ public void create_NoLengthConstraint() {
+ // We have a length constraint of 256-characters for TagValue. That constraint doesn't apply to
+ // LabelValue.
+ char[] chars = new char[300];
+ Arrays.fill(chars, 'v');
+ String value = new String(chars);
+ assertThat(LabelValue.create(value).getValue()).isEqualTo(value);
+ }
+
+ @Test
+ public void create_WithUnprintableChars() {
+ String value = "\2ab\3cd";
+ assertThat(LabelValue.create(value).getValue()).isEqualTo(value);
+ }
+
+ @Test
+ public void create_WithNonAsciiChars() {
+ String value = "值";
+ LabelValue nonAsciiValue = LabelValue.create(value);
+ assertThat(nonAsciiValue.getValue()).isEqualTo(value);
+ }
+
+ @Test
+ public void testLabelValueEquals() {
+ new EqualsTester()
+ .addEqualityGroup(LabelValue.create("foo"), LabelValue.create("foo"))
+ .addEqualityGroup(UNSET)
+ .addEqualityGroup(EMPTY)
+ .addEqualityGroup(LabelValue.create("bar"))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java
new file mode 100644
index 00000000..eedb287c
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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 LongGauge}. */
+@RunWith(JUnit4.class)
+public class LongGaugeTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String UNIT = "1";
+ private static final List<LabelKey> LABEL_KEY =
+ Collections.singletonList(LabelKey.create("key", "key description"));
+ private static final List<LabelValue> LABEL_VALUES =
+ Collections.singletonList(LabelValue.create("value"));
+ private static final List<LabelKey> EMPTY_LABEL_KEYS = new ArrayList<LabelKey>();
+ private static final List<LabelValue> EMPTY_LABEL_VALUES = new ArrayList<LabelValue>();
+
+ // TODO(mayurkale): Add more tests, once LongGauge plugs-in into the registry.
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithNullLabelValues() {
+ LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ longGauge.getOrCreateTimeSeries(null);
+ }
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithNullElement() {
+ List<LabelValue> labelValues = Collections.singletonList(null);
+ LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValue element should not be null.");
+ longGauge.getOrCreateTimeSeries(labelValues);
+ }
+
+ @Test
+ public void noopGetOrCreateTimeSeries_WithInvalidLabelSize() {
+ LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Incorrect number of labels.");
+ longGauge.getOrCreateTimeSeries(EMPTY_LABEL_VALUES);
+ }
+
+ @Test
+ public void noopRemoveTimeSeries_WithNullLabelValues() {
+ LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelValues");
+ longGauge.removeTimeSeries(null);
+ }
+
+ @Test
+ public void noopSameAs() {
+ LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ assertThat(longGauge.getDefaultTimeSeries()).isSameAs(longGauge.getDefaultTimeSeries());
+ assertThat(longGauge.getDefaultTimeSeries())
+ .isSameAs(longGauge.getOrCreateTimeSeries(LABEL_VALUES));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java
new file mode 100644
index 00000000..d8a26cc8
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.Collections;
+import java.util.List;
+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 MetricRegistry}. */
+@RunWith(JUnit4.class)
+public class MetricRegistryTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final String NAME = "name";
+ private static final String NAME_2 = "name2";
+ private static final String NAME_3 = "name3";
+ private static final String NAME_4 = "name4";
+ private static final String DESCRIPTION = "description";
+ private static final String UNIT = "1";
+ private static final List<LabelKey> LABEL_KEY =
+ Collections.singletonList(LabelKey.create("key", "key description"));
+ private static final List<LabelValue> LABEL_VALUES =
+ Collections.singletonList(LabelValue.create("value"));
+ private final MetricRegistry metricRegistry =
+ MetricsComponent.newNoopMetricsComponent().getMetricRegistry();
+
+ @Test
+ public void noopAddLongGauge_NullName() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("name");
+ metricRegistry.addLongGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddLongGauge_NullDescription() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("description");
+ metricRegistry.addLongGauge(NAME, null, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddLongGauge_NullUnit() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("unit");
+ metricRegistry.addLongGauge(NAME, DESCRIPTION, null, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddLongGauge_NullLabels() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKeys");
+ metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, null);
+ }
+
+ @Test
+ public void noopAddLongGauge_WithNullElement() {
+ List<LabelKey> labelKeys = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKey element should not be null.");
+ metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, labelKeys);
+ }
+
+ @Test
+ public void noopAddDoubleGauge_NullName() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("name");
+ metricRegistry.addDoubleGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDoubleGauge_NullDescription() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("description");
+ metricRegistry.addDoubleGauge(NAME_2, null, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDoubleGauge_NullUnit() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("unit");
+ metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, null, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDoubleGauge_NullLabels() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKeys");
+ metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, null);
+ }
+
+ @Test
+ public void noopAddDoubleGauge_WithNullElement() {
+ List<LabelKey> labelKeys = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKey element should not be null.");
+ metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, labelKeys);
+ }
+
+ @Test
+ public void noopAddDerivedLongGauge_NullName() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("name");
+ metricRegistry.addDerivedLongGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedLongGauge_NullDescription() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("description");
+ metricRegistry.addDerivedLongGauge(NAME_3, null, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedLongGauge_NullUnit() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("unit");
+ metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, null, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedLongGauge_NullLabels() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKeys");
+ metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, null);
+ }
+
+ @Test
+ public void noopAddDerivedLongGauge_WithNullElement() {
+ List<LabelKey> labelKeys = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKey element should not be null.");
+ metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, labelKeys);
+ }
+
+ @Test
+ public void noopAddDerivedDoubleGauge_NullName() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("name");
+ metricRegistry.addDerivedDoubleGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedDoubleGauge_NullDescription() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("description");
+ metricRegistry.addDerivedDoubleGauge(NAME_4, null, UNIT, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedDoubleGauge_NullUnit() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("unit");
+ metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, null, LABEL_KEY);
+ }
+
+ @Test
+ public void noopAddDerivedDoubleGauge_NullLabels() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKeys");
+ metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, null);
+ }
+
+ @Test
+ public void noopAddDerivedDoubleGauge_WithNullElement() {
+ List<LabelKey> labelKeys = Collections.singletonList(null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("labelKey element should not be null.");
+ metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, labelKeys);
+ }
+
+ @Test
+ public void noopSameAs() {
+ LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
+ assertThat(longGauge.getDefaultTimeSeries()).isSameAs(longGauge.getDefaultTimeSeries());
+ assertThat(longGauge.getDefaultTimeSeries())
+ .isSameAs(longGauge.getOrCreateTimeSeries(LABEL_VALUES));
+
+ DoubleGauge doubleGauge = metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY);
+ assertThat(doubleGauge.getDefaultTimeSeries()).isSameAs(doubleGauge.getDefaultTimeSeries());
+ assertThat(doubleGauge.getDefaultTimeSeries())
+ .isSameAs(doubleGauge.getOrCreateTimeSeries(LABEL_VALUES));
+ }
+
+ @Test
+ public void noopInstanceOf() {
+ assertThat(metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY))
+ .isInstanceOf(LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY).getClass());
+ assertThat(metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY))
+ .isInstanceOf(
+ DoubleGauge.newNoopDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY).getClass());
+ assertThat(metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, LABEL_KEY))
+ .isInstanceOf(
+ DerivedLongGauge.newNoopDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, LABEL_KEY)
+ .getClass());
+ assertThat(metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, LABEL_KEY))
+ .isInstanceOf(
+ DerivedDoubleGauge.newNoopDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, LABEL_KEY)
+ .getClass());
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java
new file mode 100644
index 00000000..1c4e70f7
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.metrics.export.ExportComponent;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link MetricsComponent}. */
+@RunWith(JUnit4.class)
+public class MetricsComponentTest {
+ @Test
+ public void defaultExportComponent() {
+ assertThat(MetricsComponent.newNoopMetricsComponent().getExportComponent())
+ .isInstanceOf(ExportComponent.newNoopExportComponent().getClass());
+ }
+
+ @Test
+ public void defaultMetricRegistry() {
+ assertThat(MetricsComponent.newNoopMetricsComponent().getMetricRegistry())
+ .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass());
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/MetricsTest.java b/api/src/test/java/io/opencensus/metrics/MetricsTest.java
new file mode 100644
index 00000000..9e0eee1f
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/MetricsTest.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.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.metrics.export.ExportComponent;
+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 Metrics}. */
+@RunWith(JUnit4.class)
+public class MetricsTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void loadMetricsComponent_UsesProvidedClassLoader() {
+ final RuntimeException toThrow = new RuntimeException("UseClassLoader");
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("UseClassLoader");
+ Metrics.loadMetricsComponent(
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) {
+ throw toThrow;
+ }
+ });
+ }
+
+ @Test
+ public void loadMetricsComponent_IgnoresMissingClasses() {
+ ClassLoader classLoader =
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException();
+ }
+ };
+ assertThat(Metrics.loadMetricsComponent(classLoader).getClass().getName())
+ .isEqualTo("io.opencensus.metrics.MetricsComponent$NoopMetricsComponent");
+ }
+
+ @Test
+ public void defaultExportComponent() {
+ assertThat(Metrics.getExportComponent())
+ .isInstanceOf(ExportComponent.newNoopExportComponent().getClass());
+ }
+
+ @Test
+ public void defaultMetricRegistry() {
+ assertThat(Metrics.getMetricRegistry())
+ .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass());
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java
new file mode 100644
index 00000000..85b31498
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java
@@ -0,0 +1,331 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Function;
+import io.opencensus.common.Functions;
+import io.opencensus.common.Timestamp;
+import io.opencensus.metrics.export.Distribution.Bucket;
+import io.opencensus.metrics.export.Distribution.BucketOptions;
+import io.opencensus.metrics.export.Distribution.BucketOptions.ExplicitOptions;
+import io.opencensus.metrics.export.Distribution.Exemplar;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+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 Distribution}. */
+@RunWith(JUnit4.class)
+public class DistributionTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ private static final Timestamp TIMESTAMP = Timestamp.create(1, 0);
+ private static final Map<String, String> ATTACHMENTS = Collections.singletonMap("key", "value");
+ private static final double TOLERANCE = 1e-6;
+
+ @Test
+ public void createAndGet_Bucket() {
+ Bucket bucket = Bucket.create(98);
+ assertThat(bucket.getCount()).isEqualTo(98);
+ assertThat(bucket.getExemplar()).isNull();
+ }
+
+ @Test
+ public void createAndGet_BucketWithExemplar() {
+ Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS);
+ Bucket bucket = Bucket.create(7, exemplar);
+ assertThat(bucket.getCount()).isEqualTo(7);
+ assertThat(bucket.getExemplar()).isEqualTo(exemplar);
+ }
+
+ @Test
+ public void createBucket_preventNullExemplar() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("exemplar");
+ Bucket.create(1, null);
+ }
+
+ @Test
+ public void createAndGet_Exemplar() {
+ Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS);
+ assertThat(exemplar.getValue()).isWithin(TOLERANCE).of(-9.9);
+ assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP);
+ assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS);
+ }
+
+ @Test
+ public void createAndGet_ExplicitBuckets() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 3.0);
+
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+ final List<Double> actual = new ArrayList<Double>();
+ bucketOptions.match(
+ new Function<ExplicitOptions, Object>() {
+ @Override
+ public Object apply(ExplicitOptions arg) {
+ actual.addAll(arg.getBucketBoundaries());
+ return null;
+ }
+ },
+ Functions.throwAssertionError());
+
+ assertThat(actual).containsExactlyElementsIn(bucketBounds).inOrder();
+ }
+
+ @Test
+ public void createAndGet_ExplicitBucketsNegativeBounds() {
+ List<Double> bucketBounds = Collections.singletonList(-1.0);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("bucket boundary should be > 0");
+ BucketOptions.explicitOptions(bucketBounds);
+ }
+
+ @Test
+ public void createAndGet_PreventNullExplicitBuckets() {
+ thrown.expect(NullPointerException.class);
+ BucketOptions.explicitOptions(Arrays.asList(1.0, null, 3.0));
+ }
+
+ @Test
+ public void createAndGet_ExplicitBucketsEmptyBounds() {
+ List<Double> bucketBounds = new ArrayList<Double>();
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+
+ final List<Double> actual = new ArrayList<Double>();
+ bucketOptions.match(
+ new Function<ExplicitOptions, Object>() {
+ @Override
+ public Object apply(ExplicitOptions arg) {
+ actual.addAll(arg.getBucketBoundaries());
+ return null;
+ }
+ },
+ Functions.throwAssertionError());
+
+ assertThat(actual).isEmpty();
+ }
+
+ @Test
+ public void createBucketOptions_UnorderedBucketBounds() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 5.0, 2.0);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("bucket boundaries not sorted.");
+ BucketOptions.explicitOptions(bucketBounds);
+ }
+
+ @Test
+ public void createAndGet_PreventNullBucketOptions() {
+ thrown.expect(NullPointerException.class);
+ BucketOptions.explicitOptions(null);
+ }
+
+ @Test
+ public void createAndGet_Distribution() {
+ Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS);
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+ List<Bucket> buckets =
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar));
+ Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketOptions, buckets);
+ assertThat(distribution.getCount()).isEqualTo(10);
+ assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6);
+ assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54);
+
+ final List<Double> actual = new ArrayList<Double>();
+ distribution
+ .getBucketOptions()
+ .match(
+ new Function<ExplicitOptions, Object>() {
+ @Override
+ public Object apply(ExplicitOptions arg) {
+ actual.addAll(arg.getBucketBoundaries());
+ return null;
+ }
+ },
+ Functions.throwAssertionError());
+
+ assertThat(actual).containsExactlyElementsIn(bucketBounds).inOrder();
+
+ assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder();
+ }
+
+ @Test
+ public void createBucket_NegativeCount() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("bucket count should be non-negative.");
+ Bucket.create(-5);
+ }
+
+ @Test
+ public void createExemplar_PreventNullAttachments() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("attachments");
+ Exemplar.create(15, TIMESTAMP, null);
+ }
+
+ @Test
+ public void createExemplar_PreventNullAttachmentKey() {
+ Map<String, String> attachments = Collections.singletonMap(null, "value");
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("key of attachment");
+ Exemplar.create(15, TIMESTAMP, attachments);
+ }
+
+ @Test
+ public void createExemplar_PreventNullAttachmentValue() {
+ Map<String, String> attachments = Collections.singletonMap("key", null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value of attachment");
+ Exemplar.create(15, TIMESTAMP, attachments);
+ }
+
+ @Test
+ public void createDistribution_NegativeCount() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("count should be non-negative.");
+ Distribution.create(-10, 6.6, 678.54, bucketOptions, buckets);
+ }
+
+ @Test
+ public void createDistribution_NegativeSumOfSquaredDeviations() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0));
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum of squared deviations should be non-negative.");
+ Distribution.create(0, 6.6, -678.54, bucketOptions, buckets);
+ }
+
+ @Test
+ public void createDistribution_ZeroCountAndPositiveMean() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0));
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum should be 0 if count is 0.");
+ Distribution.create(0, 6.6, 0, bucketOptions, buckets);
+ }
+
+ @Test
+ public void createDistribution_ZeroCountAndSumOfSquaredDeviations() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0));
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum of squared deviations should be 0 if count is 0.");
+ Distribution.create(0, 0, 678.54, bucketOptions, buckets);
+ }
+
+ @Test
+ public void createDistribution_NullBucketBoundaries() {
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucketBoundaries");
+ Distribution.create(10, 6.6, 678.54, BucketOptions.explicitOptions(null), buckets);
+ }
+
+ @Test
+ public void createDistribution_NullBucketBoundary() {
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucketBoundary");
+ Distribution.create(
+ 10, 6.6, 678.54, BucketOptions.explicitOptions(Arrays.asList(2.5, null)), buckets);
+ }
+
+ @Test
+ public void createDistribution_NullBucketOptions() {
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucketOptions");
+ Distribution.create(10, 6.6, 678.54, null, buckets);
+ }
+
+ @Test
+ public void createDistribution_NullBucketList() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("buckets");
+ Distribution.create(10, 6.6, 678.54, bucketOptions, null);
+ }
+
+ @Test
+ public void createDistribution_NullBucket() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 5.0);
+ BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds);
+ List<Bucket> buckets =
+ Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4));
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucket");
+ Distribution.create(10, 6.6, 678.54, bucketOptions, buckets);
+ }
+
+ @Test
+ public void testEquals() {
+ List<Double> bucketBounds = Arrays.asList(1.0, 2.0, 2.5);
+ new EqualsTester()
+ .addEqualityGroup(
+ Distribution.create(
+ 10,
+ 10,
+ 1,
+ BucketOptions.explicitOptions(bucketBounds),
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))),
+ Distribution.create(
+ 10,
+ 10,
+ 1,
+ BucketOptions.explicitOptions(bucketBounds),
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))
+ .addEqualityGroup(
+ Distribution.create(
+ 7,
+ 10,
+ 23.456,
+ BucketOptions.explicitOptions(bucketBounds),
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java
new file mode 100644
index 00000000..15c6e883
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.metrics.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 {
+ @Test
+ public void defaultMetricExporter() {
+ assertThat(ExportComponent.newNoopExportComponent().getMetricProducerManager())
+ .isInstanceOf(MetricProducerManager.class);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java
new file mode 100644
index 00000000..502170c6
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.metrics.LabelKey;
+import io.opencensus.metrics.export.MetricDescriptor.Type;
+import java.util.Arrays;
+import java.util.List;
+import org.hamcrest.CoreMatchers;
+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 MetricDescriptor}. */
+@RunWith(JUnit4.class)
+public class MetricDescriptorTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ private static final String METRIC_NAME_1 = "metric1";
+ private static final String METRIC_NAME_2 = "metric2";
+ private static final String DESCRIPTION = "Metric description.";
+ private static final String UNIT = "kb/s";
+ private static final LabelKey KEY_1 = LabelKey.create("key1", "some key");
+ private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key");
+
+ @Test
+ public void testGet() {
+ MetricDescriptor metricDescriptor =
+ MetricDescriptor.create(
+ METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2));
+ assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1);
+ assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT);
+ assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE);
+ assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder();
+ }
+
+ @Test
+ public void preventNullLabelKeyList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelKeys"));
+ MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null);
+ }
+
+ @Test
+ public void preventNullLabelKey() {
+ List<LabelKey> keys = Arrays.asList(KEY_1, null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelKey"));
+ MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ MetricDescriptor.create(
+ METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)),
+ MetricDescriptor.create(
+ METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)))
+ .addEqualityGroup(
+ MetricDescriptor.create(
+ METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)))
+ .addEqualityGroup(
+ MetricDescriptor.create(
+ METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2)))
+ .addEqualityGroup(
+ MetricDescriptor.create(
+ METRIC_NAME_1,
+ DESCRIPTION,
+ UNIT,
+ Type.CUMULATIVE_DISTRIBUTION,
+ Arrays.asList(KEY_1, KEY_2)))
+ .addEqualityGroup(
+ MetricDescriptor.create(
+ METRIC_NAME_1,
+ DESCRIPTION,
+ UNIT,
+ Type.CUMULATIVE_DISTRIBUTION,
+ Arrays.asList(KEY_1)))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java
new file mode 100644
index 00000000..1025427f
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unit tests for {@link MetricProducerManager}. */
+@RunWith(JUnit4.class)
+public class MetricProducerManagerTest {
+ private final MetricProducerManager metricProducerManager =
+ MetricProducerManager.newNoopMetricProducerManager();
+ @Mock private MetricProducer metricProducer;
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void add_DisallowsNull() {
+ thrown.expect(NullPointerException.class);
+ metricProducerManager.add(null);
+ }
+
+ @Test
+ public void add() {
+ metricProducerManager.add(metricProducer);
+ assertThat(metricProducerManager.getAllMetricProducer()).isEmpty();
+ }
+
+ @Test
+ public void addAndRemove() {
+ metricProducerManager.add(metricProducer);
+ assertThat(metricProducerManager.getAllMetricProducer()).isEmpty();
+ metricProducerManager.remove(metricProducer);
+ assertThat(metricProducerManager.getAllMetricProducer()).isEmpty();
+ }
+
+ @Test
+ public void remove_DisallowsNull() {
+ thrown.expect(NullPointerException.class);
+ metricProducerManager.remove(null);
+ }
+
+ @Test
+ public void remove_FromEmpty() {
+ metricProducerManager.remove(metricProducer);
+ assertThat(metricProducerManager.getAllMetricProducer()).isEmpty();
+ }
+
+ @Test
+ public void getAllMetricProducer_empty() {
+ assertThat(metricProducerManager.getAllMetricProducer()).isEmpty();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java
new file mode 100644
index 00000000..ed205289
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Timestamp;
+import io.opencensus.metrics.LabelKey;
+import io.opencensus.metrics.LabelValue;
+import io.opencensus.metrics.export.MetricDescriptor.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+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 Metric}. */
+@RunWith(JUnit4.class)
+public class MetricTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ private static final String METRIC_NAME_1 = "metric1";
+ private static final String METRIC_NAME_2 = "metric2";
+ private static final String DESCRIPTION = "Metric description.";
+ private static final String UNIT = "kb/s";
+ private static final LabelKey KEY_1 = LabelKey.create("key1", "some key");
+ private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key");
+ private static final MetricDescriptor METRIC_DESCRIPTOR_1 =
+ MetricDescriptor.create(
+ METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2));
+ private static final MetricDescriptor METRIC_DESCRIPTOR_2 =
+ MetricDescriptor.create(
+ METRIC_NAME_2,
+ DESCRIPTION,
+ UNIT,
+ Type.CUMULATIVE_INT64,
+ Collections.singletonList(KEY_1));
+ private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1");
+ private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1");
+ private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create("");
+ private static final Value VALUE_LONG = Value.longValue(12345678);
+ private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77);
+ private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79);
+ private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000);
+ private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000);
+ private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000);
+ private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2);
+ private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3);
+ private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3);
+ private static final TimeSeries GAUGE_TIME_SERIES_1 =
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Collections.singletonList(POINT_1), null);
+ private static final TimeSeries GAUGE_TIME_SERIES_2 =
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Collections.singletonList(POINT_2), null);
+ private static final TimeSeries CUMULATIVE_TIME_SERIES =
+ TimeSeries.create(
+ Collections.singletonList(LABEL_VALUE_EMPTY),
+ Collections.singletonList(POINT_3),
+ TIMESTAMP_1);
+
+ @Test
+ public void testGet() {
+ Metric metric =
+ Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2));
+ assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1);
+ assertThat(metric.getTimeSeriesList())
+ .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)
+ .inOrder();
+ }
+
+ @Test
+ public void typeMismatch_GaugeDouble_Long() {
+ typeMismatch(
+ METRIC_DESCRIPTOR_1,
+ Collections.singletonList(CUMULATIVE_TIME_SERIES),
+ String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong"));
+ }
+
+ @Test
+ public void typeMismatch_CumulativeInt64_Double() {
+ typeMismatch(
+ METRIC_DESCRIPTOR_2,
+ Collections.singletonList(GAUGE_TIME_SERIES_1),
+ String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble"));
+ }
+
+ private void typeMismatch(
+ MetricDescriptor metricDescriptor, List<TimeSeries> timeSeriesList, String errorMessage) {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(errorMessage);
+ Metric.create(metricDescriptor, timeSeriesList);
+ }
+
+ @Test
+ public void create_WithNullMetricDescriptor() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("metricDescriptor");
+ Metric.create(null, Collections.<TimeSeries>emptyList());
+ }
+
+ @Test
+ public void create_WithNullTimeSeriesList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("timeSeriesList");
+ Metric.create(METRIC_DESCRIPTOR_1, null);
+ }
+
+ @Test
+ public void create_WithNullTimeSeries() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("timeSeries");
+ Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, null));
+ }
+
+ @Test
+ public void immutableTimeSeriesList() {
+ List<TimeSeries> timeSeriesList = new ArrayList<TimeSeries>();
+ timeSeriesList.add(GAUGE_TIME_SERIES_1);
+ Metric metric = Metric.create(METRIC_DESCRIPTOR_1, timeSeriesList);
+ timeSeriesList.add(GAUGE_TIME_SERIES_2);
+ assertThat(metric.getTimeSeriesList()).containsExactly(GAUGE_TIME_SERIES_1);
+ }
+
+ @Test
+ public void createWithOneTimeSeries_WithNullTimeSeries() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("timeSeries");
+ Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_1, null);
+ }
+
+ @Test
+ public void createWithOneTimeSeries_WithNullMetricDescriptor() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("metricDescriptor");
+ Metric.createWithOneTimeSeries(null, GAUGE_TIME_SERIES_1);
+ }
+
+ @Test
+ public void testGet_WithOneTimeSeries() {
+ Metric metric = Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_1, GAUGE_TIME_SERIES_1);
+ assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1);
+ assertThat(metric.getTimeSeriesList()).containsExactly(GAUGE_TIME_SERIES_1);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Metric.create(
+ METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)),
+ Metric.create(
+ METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)))
+ .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.<TimeSeries>emptyList()))
+ .addEqualityGroup(
+ Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_2, CUMULATIVE_TIME_SERIES))
+ .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.<TimeSeries>emptyList()))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/PointTest.java b/api/src/test/java/io/opencensus/metrics/export/PointTest.java
new file mode 100644
index 00000000..cdfc7792
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/PointTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Timestamp;
+import io.opencensus.metrics.export.Distribution.Bucket;
+import io.opencensus.metrics.export.Distribution.BucketOptions;
+import java.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link Point}. */
+@RunWith(JUnit4.class)
+public class PointTest {
+
+ private static final Value DOUBLE_VALUE = Value.doubleValue(55.5);
+ private static final Value LONG_VALUE = Value.longValue(9876543210L);
+ private static final Value DISTRIBUTION_VALUE =
+ Value.distributionValue(
+ Distribution.create(
+ 10,
+ 6.6,
+ 678.54,
+ BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)),
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))));
+ private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2);
+ private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4);
+ private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6);
+
+ @Test
+ public void testGet() {
+ Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1);
+ assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE);
+ assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1))
+ .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1))
+ .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2))
+ .addEqualityGroup(
+ Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2),
+ Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2))
+ .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java b/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java
new file mode 100644
index 00000000..c10df043
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.metrics.export.Summary.Snapshot;
+import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile;
+import java.util.Collections;
+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 Summary}. */
+@RunWith(JUnit4.class)
+public class SummaryTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+ private static final double TOLERANCE = 1e-6;
+
+ @Test
+ public void createAndGet_ValueAtPercentile() {
+ ValueAtPercentile valueAtPercentile = ValueAtPercentile.create(99.5, 10.2);
+ assertThat(valueAtPercentile.getPercentile()).isWithin(TOLERANCE).of(99.5);
+ assertThat(valueAtPercentile.getValue()).isWithin(TOLERANCE).of(10.2);
+ }
+
+ @Test
+ public void createValueAtPercentile_InvalidValueAtPercentileInterval() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("percentile must be in the interval (0.0, 100.0]");
+ ValueAtPercentile.create(100.1, 10.2);
+ }
+
+ @Test
+ public void createValueAtPercentile_NegativeValue() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("value must be non-negative");
+ ValueAtPercentile.create(99.5, -10.2);
+ }
+
+ @Test
+ public void createAndGet_Snapshot() {
+ Snapshot snapshot =
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ assertThat(snapshot.getCount()).isEqualTo(10);
+ assertThat(snapshot.getSum()).isWithin(TOLERANCE).of(87.07);
+ assertThat(snapshot.getValueAtPercentiles())
+ .containsExactly(ValueAtPercentile.create(99.5, 10.2));
+ }
+
+ @Test
+ public void createAndGet_Snapshot_WithNullCountAndSum() {
+ Snapshot snapshot =
+ Snapshot.create(
+ null, null, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ assertThat(snapshot.getCount()).isNull();
+ assertThat(snapshot.getSum()).isNull();
+ assertThat(snapshot.getValueAtPercentiles())
+ .containsExactly(ValueAtPercentile.create(99.5, 10.2));
+ }
+
+ @Test
+ public void createSnapshot_NegativeCount() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("count must be non-negative");
+ Snapshot.create(-10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_NegativeSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be non-negative");
+ Snapshot.create(10L, -87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_ZeroCountAndNonZeroSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be 0 if count is 0");
+ Snapshot.create(0L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_NullValueAtPercentilesList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("valueAtPercentiles");
+ Snapshot.create(10L, 87.07, null);
+ }
+
+ @Test
+ public void createSnapshot_OneNullValueAtPercentile() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value in valueAtPercentiles");
+ Snapshot.create(10L, 87.07, Collections.<ValueAtPercentile>singletonList(null));
+ }
+
+ @Test
+ public void createAndGet_Summary() {
+ Snapshot snapshot =
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ Summary summary = Summary.create(10L, 6.6, snapshot);
+ assertThat(summary.getCount()).isEqualTo(10);
+ assertThat(summary.getSum()).isWithin(TOLERANCE).of(6.6);
+ assertThat(summary.getSnapshot()).isEqualTo(snapshot);
+ }
+
+ @Test
+ public void createSummary_NegativeCount() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("count must be non-negative");
+ Summary.create(
+ -10L, 6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_NegativeSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be non-negative");
+ Summary.create(
+ 10L, -6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_ZeroCountAndNonZeroSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be 0 if count is 0");
+ Summary.create(
+ 0L, 6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_NullSnapshot() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("snapshot");
+ Summary.create(10L, 6.6, null);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))),
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 7L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 10L,
+ 7.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 10L, 10.0, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList())))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java
new file mode 100644
index 00000000..92a2c8cf
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Timestamp;
+import io.opencensus.metrics.LabelValue;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.hamcrest.CoreMatchers;
+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 TimeSeries}. */
+@RunWith(JUnit4.class)
+public class TimeSeriesTest {
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1");
+ private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2");
+ private static final Value VALUE_LONG = Value.longValue(12345678);
+ private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77);
+ private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000);
+ private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000);
+ private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000);
+ private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2);
+ private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3);
+
+ @Test
+ public void testGet_TimeSeries() {
+ TimeSeries cumulativeTimeSeries =
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1);
+ assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1);
+ assertThat(cumulativeTimeSeries.getLabelValues())
+ .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2)
+ .inOrder();
+ assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder();
+ }
+
+ @Test
+ public void create_WithNullLabelValueList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelValues"));
+ TimeSeries.create(null, Collections.<Point>emptyList(), TIMESTAMP_1);
+ }
+
+ @Test
+ public void create_WithNullLabelValue() {
+ List<LabelValue> labelValues = Arrays.asList(LABEL_VALUE_1, null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelValue"));
+ TimeSeries.create(labelValues, Collections.<Point>emptyList(), TIMESTAMP_1);
+ }
+
+ @Test
+ public void create_WithNullPointList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("points"));
+ TimeSeries.create(Collections.<LabelValue>emptyList(), null, TIMESTAMP_1);
+ }
+
+ @Test
+ public void create_WithNullPoint() {
+ List<Point> points = Arrays.asList(POINT_1, null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("point"));
+ TimeSeries.create(Collections.<LabelValue>emptyList(), points, TIMESTAMP_1);
+ }
+
+ @Test
+ public void testGet_WithOnePointTimeSeries() {
+ TimeSeries cumulativeTimeSeries =
+ TimeSeries.createWithOnePoint(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), POINT_1, TIMESTAMP_1);
+ assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1);
+ assertThat(cumulativeTimeSeries.getLabelValues())
+ .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2)
+ .inOrder();
+ assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder();
+ }
+
+ @Test
+ public void createWithOnePoint_WithNullLabelValueList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelValues"));
+ TimeSeries.createWithOnePoint(null, POINT_1, TIMESTAMP_1);
+ }
+
+ @Test
+ public void createWithOnePoint_WithNullLabelValue() {
+ List<LabelValue> labelValues = Arrays.asList(LABEL_VALUE_1, null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("labelValue"));
+ TimeSeries.createWithOnePoint(labelValues, POINT_1, TIMESTAMP_1);
+ }
+
+ @Test
+ public void createWithOnePoint_WithNullPointList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage(CoreMatchers.equalTo("point"));
+ TimeSeries.createWithOnePoint(Collections.<LabelValue>emptyList(), null, TIMESTAMP_1);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1),
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1))
+ .addEqualityGroup(
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null),
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null))
+ .addEqualityGroup(
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2))
+ .addEqualityGroup(
+ TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2))
+ .addEqualityGroup(
+ TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2))
+ .addEqualityGroup(
+ TimeSeries.create(
+ Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/export/ValueTest.java b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java
new file mode 100644
index 00000000..bf947692
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.metrics.export;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Function;
+import io.opencensus.common.Functions;
+import io.opencensus.metrics.export.Distribution.Bucket;
+import io.opencensus.metrics.export.Distribution.BucketOptions;
+import io.opencensus.metrics.export.Distribution.BucketOptions.ExplicitOptions;
+import io.opencensus.metrics.export.Summary.Snapshot;
+import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile;
+import io.opencensus.metrics.export.Value.ValueDistribution;
+import io.opencensus.metrics.export.Value.ValueDouble;
+import io.opencensus.metrics.export.Value.ValueLong;
+import io.opencensus.metrics.export.Value.ValueSummary;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link Value}. */
+@RunWith(JUnit4.class)
+public class ValueTest {
+ private static final double TOLERANCE = 1e-6;
+
+ private static final Distribution DISTRIBUTION =
+ Distribution.create(
+ 10,
+ 10,
+ 1,
+ BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)),
+ Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)));
+ private static final Summary SUMMARY =
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2))));
+
+ @Test
+ public void createAndGet_ValueDouble() {
+ Value value = Value.doubleValue(-34.56);
+ assertThat(value).isInstanceOf(ValueDouble.class);
+ assertThat(((ValueDouble) value).getValue()).isWithin(TOLERANCE).of(-34.56);
+ }
+
+ @Test
+ public void createAndGet_ValueLong() {
+ Value value = Value.longValue(123456789);
+ assertThat(value).isInstanceOf(ValueLong.class);
+ assertThat(((ValueLong) value).getValue()).isEqualTo(123456789);
+ }
+
+ @Test
+ public void createAndGet_ValueDistribution() {
+ Value value = Value.distributionValue(DISTRIBUTION);
+ assertThat(value).isInstanceOf(ValueDistribution.class);
+ assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION);
+ }
+
+ @Test
+ public void createAndGet_ValueSummary() {
+ Value value = Value.summaryValue(SUMMARY);
+ assertThat(value).isInstanceOf(ValueSummary.class);
+ assertThat(((ValueSummary) value).getValue()).isEqualTo(SUMMARY);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0))
+ .addEqualityGroup(Value.doubleValue(2.0))
+ .addEqualityGroup(Value.longValue(1L))
+ .addEqualityGroup(Value.longValue(2L))
+ .addEqualityGroup(
+ Value.distributionValue(
+ Distribution.create(
+ 7,
+ 10,
+ 23.456,
+ BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)),
+ Arrays.asList(
+ Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))))
+ .testEquals();
+ }
+
+ @Test
+ public void testMatch() {
+ List<Value> values =
+ Arrays.asList(
+ ValueDouble.create(1.0),
+ ValueLong.create(-1),
+ ValueDistribution.create(DISTRIBUTION),
+ ValueSummary.create(SUMMARY));
+ List<Number> expected =
+ Arrays.<Number>asList(1.0, -1L, 10.0, 10L, 1.0, 1.0, 2.0, 5.0, 3L, 1L, 2L, 4L);
+ final List<Number> actual = new ArrayList<Number>();
+ for (Value value : values) {
+ value.match(
+ new Function<Double, Object>() {
+ @Override
+ public Object apply(Double arg) {
+ actual.add(arg);
+ return null;
+ }
+ },
+ new Function<Long, Object>() {
+ @Override
+ public Object apply(Long arg) {
+ actual.add(arg);
+ return null;
+ }
+ },
+ new Function<Distribution, Object>() {
+ @Override
+ public Object apply(Distribution arg) {
+ actual.add(arg.getSum());
+ actual.add(arg.getCount());
+ actual.add(arg.getSumOfSquaredDeviations());
+
+ arg.getBucketOptions()
+ .match(
+ new Function<ExplicitOptions, Object>() {
+ @Override
+ public Object apply(ExplicitOptions arg) {
+ actual.addAll(arg.getBucketBoundaries());
+ return null;
+ }
+ },
+ Functions.throwAssertionError());
+
+ for (Bucket bucket : arg.getBuckets()) {
+ actual.add(bucket.getCount());
+ }
+ return null;
+ }
+ },
+ new Function<Summary, Object>() {
+ @Override
+ public Object apply(Summary arg) {
+ return null;
+ }
+ },
+ Functions.throwAssertionError());
+ }
+ assertThat(actual).containsExactlyElementsIn(expected).inOrder();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java
new file mode 100644
index 00000000..a6d6d1de
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java
@@ -0,0 +1,231 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Function;
+import io.opencensus.common.Functions;
+import io.opencensus.common.Timestamp;
+import io.opencensus.stats.AggregationData.CountData;
+import io.opencensus.stats.AggregationData.DistributionData;
+import io.opencensus.stats.AggregationData.DistributionData.Exemplar;
+import io.opencensus.stats.AggregationData.LastValueDataDouble;
+import io.opencensus.stats.AggregationData.LastValueDataLong;
+import io.opencensus.stats.AggregationData.MeanData;
+import io.opencensus.stats.AggregationData.SumDataDouble;
+import io.opencensus.stats.AggregationData.SumDataLong;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+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.stats.AggregationData}. */
+@RunWith(JUnit4.class)
+public class AggregationDataTest {
+
+ private static final double TOLERANCE = 1e-6;
+ private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 0);
+ private static final Timestamp TIMESTAMP_2 = Timestamp.create(2, 0);
+ private static final Map<String, String> ATTACHMENTS = Collections.singletonMap("key", "value");
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testCreateDistributionData() {
+ DistributionData distributionData =
+ DistributionData.create(7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L, 5L));
+ assertThat(distributionData.getMean()).isWithin(TOLERANCE).of(7.7);
+ assertThat(distributionData.getCount()).isEqualTo(10);
+ assertThat(distributionData.getMin()).isWithin(TOLERANCE).of(1.1);
+ assertThat(distributionData.getMax()).isWithin(TOLERANCE).of(9.9);
+ assertThat(distributionData.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(32.2);
+ assertThat(distributionData.getBucketCounts()).containsExactly(4L, 1L, 5L).inOrder();
+ }
+
+ @Test
+ public void testCreateDistributionDataWithExemplar() {
+ Exemplar exemplar1 = Exemplar.create(4, TIMESTAMP_2, ATTACHMENTS);
+ Exemplar exemplar2 = Exemplar.create(1, TIMESTAMP_1, ATTACHMENTS);
+ DistributionData distributionData =
+ DistributionData.create(
+ 7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L), Arrays.asList(exemplar1, exemplar2));
+ assertThat(distributionData.getExemplars()).containsExactly(exemplar1, exemplar2).inOrder();
+ }
+
+ @Test
+ public void testExemplar() {
+ Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP_1, ATTACHMENTS);
+ assertThat(exemplar.getValue()).isEqualTo(15.0);
+ assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP_1);
+ assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachments() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("attachments");
+ Exemplar.create(15, TIMESTAMP_1, null);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachmentKey() {
+ Map<String, String> attachments = Collections.singletonMap(null, "value");
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("key of attachment");
+ Exemplar.create(15, TIMESTAMP_1, attachments);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachmentValue() {
+ Map<String, String> attachments = Collections.singletonMap("key", null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value of attachment");
+ Exemplar.create(15, TIMESTAMP_1, attachments);
+ }
+
+ @Test
+ public void preventNullBucketCountList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucketCounts");
+ DistributionData.create(1, 1, 1, 1, 0, null);
+ }
+
+ @Test
+ public void preventNullBucket() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucket");
+ DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, null));
+ }
+
+ @Test
+ public void preventNullExemplarList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("exemplar list should not be null.");
+ DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), null);
+ }
+
+ @Test
+ public void preventNullExemplar() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("exemplar");
+ DistributionData.create(
+ 1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), Collections.<Exemplar>singletonList(null));
+ }
+
+ @Test
+ public void preventMinIsGreaterThanMax() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("max should be greater or equal to min.");
+ DistributionData.create(1, 1, 10, 1, 0, Arrays.asList(0L, 1L, 0L));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(SumDataDouble.create(10.0), SumDataDouble.create(10.0))
+ .addEqualityGroup(SumDataDouble.create(20.0), SumDataDouble.create(20.0))
+ .addEqualityGroup(SumDataLong.create(20), SumDataLong.create(20))
+ .addEqualityGroup(CountData.create(40), CountData.create(40))
+ .addEqualityGroup(CountData.create(80), CountData.create(80))
+ .addEqualityGroup(
+ DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L)),
+ DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 100L)))
+ .addEqualityGroup(DistributionData.create(110, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(DistributionData.create(10, 110, 1, 1, 0, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(DistributionData.create(10, 10, -1, 1, 0, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(DistributionData.create(10, 10, 1, 5, 0, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(DistributionData.create(10, 10, 1, 1, 55.5, Arrays.asList(0L, 10L, 0L)))
+ .addEqualityGroup(MeanData.create(5.0, 1), MeanData.create(5.0, 1))
+ .addEqualityGroup(MeanData.create(-5.0, 1), MeanData.create(-5.0, 1))
+ .addEqualityGroup(LastValueDataDouble.create(20.0), LastValueDataDouble.create(20.0))
+ .addEqualityGroup(LastValueDataLong.create(20), LastValueDataLong.create(20))
+ .testEquals();
+ }
+
+ @Test
+ public void testMatchAndGet() {
+ List<AggregationData> aggregations =
+ Arrays.asList(
+ SumDataDouble.create(10.0),
+ SumDataLong.create(100000000),
+ CountData.create(40),
+ DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L)),
+ LastValueDataDouble.create(20.0),
+ LastValueDataLong.create(200000000L));
+
+ final List<Object> actual = new ArrayList<Object>();
+ for (AggregationData aggregation : aggregations) {
+ aggregation.match(
+ new Function<SumDataDouble, Void>() {
+ @Override
+ public Void apply(SumDataDouble arg) {
+ actual.add(arg.getSum());
+ return null;
+ }
+ },
+ new Function<SumDataLong, Void>() {
+ @Override
+ public Void apply(SumDataLong arg) {
+ actual.add(arg.getSum());
+ return null;
+ }
+ },
+ new Function<CountData, Void>() {
+ @Override
+ public Void apply(CountData arg) {
+ actual.add(arg.getCount());
+ return null;
+ }
+ },
+ new Function<DistributionData, Void>() {
+ @Override
+ public Void apply(DistributionData arg) {
+ actual.add(arg.getBucketCounts());
+ return null;
+ }
+ },
+ new Function<LastValueDataDouble, Void>() {
+ @Override
+ public Void apply(LastValueDataDouble arg) {
+ actual.add(arg.getLastValue());
+ return null;
+ }
+ },
+ new Function<LastValueDataLong, Void>() {
+ @Override
+ public Void apply(LastValueDataLong arg) {
+ actual.add(arg.getLastValue());
+ return null;
+ }
+ },
+ Functions.<Void>throwIllegalArgumentException());
+ }
+
+ assertThat(actual)
+ .containsExactly(10.0, 100000000L, 40L, Arrays.asList(0L, 10L, 0L), 20.0, 200000000L)
+ .inOrder();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/AggregationTest.java b/api/src/test/java/io/opencensus/stats/AggregationTest.java
new file mode 100644
index 00000000..cf337030
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/AggregationTest.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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Functions;
+import io.opencensus.stats.Aggregation.Count;
+import io.opencensus.stats.Aggregation.Distribution;
+import io.opencensus.stats.Aggregation.LastValue;
+import io.opencensus.stats.Aggregation.Mean;
+import io.opencensus.stats.Aggregation.Sum;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+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.stats.Aggregation}. */
+@RunWith(JUnit4.class)
+public class AggregationTest {
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testCreateDistribution() {
+ BucketBoundaries bucketBoundaries = BucketBoundaries.create(Arrays.asList(0.1, 2.2, 33.3));
+ Distribution distribution = Distribution.create(bucketBoundaries);
+ assertThat(distribution.getBucketBoundaries()).isEqualTo(bucketBoundaries);
+ }
+
+ @Test
+ public void testNullBucketBoundaries() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("bucketBoundaries");
+ Distribution.create(null);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(Sum.create(), Sum.create())
+ .addEqualityGroup(Count.create(), Count.create())
+ .addEqualityGroup(
+ Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))),
+ Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))))
+ .addEqualityGroup(
+ Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0))),
+ Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0))))
+ .addEqualityGroup(Mean.create(), Mean.create())
+ .addEqualityGroup(LastValue.create(), LastValue.create())
+ .testEquals();
+ }
+
+ @Test
+ public void testMatch() {
+ List<Aggregation> aggregations =
+ Arrays.asList(
+ Sum.create(),
+ Count.create(),
+ Mean.create(),
+ Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))),
+ LastValue.create());
+
+ List<String> actual = new ArrayList<String>();
+ for (Aggregation aggregation : aggregations) {
+ actual.add(
+ aggregation.match(
+ Functions.returnConstant("SUM"),
+ Functions.returnConstant("COUNT"),
+ Functions.returnConstant("DISTRIBUTION"),
+ Functions.returnConstant("LASTVALUE"),
+ Functions.returnConstant("UNKNOWN")));
+ }
+
+ assertThat(actual)
+ .isEqualTo(Arrays.asList("SUM", "COUNT", "UNKNOWN", "DISTRIBUTION", "LASTVALUE"));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java
new file mode 100644
index 00000000..36f2edb4
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+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.stats.BucketBoundaries}. */
+@RunWith(JUnit4.class)
+public class BucketBoundariesTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testConstructBoundaries() {
+ List<Double> buckets = Arrays.asList(0.0, 1.0, 2.0);
+ BucketBoundaries bucketBoundaries = BucketBoundaries.create(buckets);
+ assertThat(bucketBoundaries.getBoundaries()).isEqualTo(buckets);
+ }
+
+ @Test
+ public void testBoundariesDoesNotChangeWithOriginalList() {
+ List<Double> original = new ArrayList<Double>();
+ original.add(0.0);
+ original.add(1.0);
+ original.add(2.0);
+ BucketBoundaries bucketBoundaries = BucketBoundaries.create(original);
+ original.set(2, 3.0);
+ original.add(4.0);
+ List<Double> expected = Arrays.asList(0.0, 1.0, 2.0);
+ assertThat(bucketBoundaries.getBoundaries()).isNotEqualTo(original);
+ assertThat(bucketBoundaries.getBoundaries()).isEqualTo(expected);
+ }
+
+ @Test
+ public void testNullBoundaries() throws Exception {
+ thrown.expect(NullPointerException.class);
+ BucketBoundaries.create(null);
+ }
+
+ @Test
+ public void testUnsortedBoundaries() throws Exception {
+ List<Double> buckets = Arrays.asList(0.0, 1.0, 1.0);
+ thrown.expect(IllegalArgumentException.class);
+ BucketBoundaries.create(buckets);
+ }
+
+ @Test
+ public void testNoBoundaries() {
+ List<Double> buckets = Arrays.asList();
+ BucketBoundaries bucketBoundaries = BucketBoundaries.create(buckets);
+ assertThat(bucketBoundaries.getBoundaries()).isEqualTo(buckets);
+ }
+
+ @Test
+ public void testBucketBoundariesEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ BucketBoundaries.create(Arrays.asList(-1.0, 2.0)),
+ BucketBoundaries.create(Arrays.asList(-1.0, 2.0)))
+ .addEqualityGroup(BucketBoundaries.create(Arrays.asList(-1.0)))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/MeasureTest.java b/api/src/test/java/io/opencensus/stats/MeasureTest.java
new file mode 100644
index 00000000..a9302425
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/MeasureTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Lists;
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Function;
+import io.opencensus.common.Functions;
+import io.opencensus.stats.Measure.MeasureDouble;
+import io.opencensus.stats.Measure.MeasureLong;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link Measure}. */
+@RunWith(JUnit4.class)
+public final class MeasureTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testConstants() {
+ assertThat(Measure.NAME_MAX_LENGTH).isEqualTo(255);
+ }
+
+ @Test
+ public void preventTooLongMeasureName() {
+ char[] chars = new char[Measure.NAME_MAX_LENGTH + 1];
+ Arrays.fill(chars, 'a');
+ String longName = String.valueOf(chars);
+ thrown.expect(IllegalArgumentException.class);
+ Measure.MeasureDouble.create(longName, "description", "1");
+ }
+
+ @Test
+ public void preventNonPrintableMeasureName() {
+ thrown.expect(IllegalArgumentException.class);
+ Measure.MeasureDouble.create("\2", "description", "1");
+ }
+
+ @Test
+ public void testMeasureDoubleComponents() {
+ Measure measurement = Measure.MeasureDouble.create("Foo", "The description of Foo", "Mbit/s");
+ assertThat(measurement.getName()).isEqualTo("Foo");
+ assertThat(measurement.getDescription()).isEqualTo("The description of Foo");
+ assertThat(measurement.getUnit()).isEqualTo("Mbit/s");
+ }
+
+ @Test
+ public void testMeasureLongComponents() {
+ Measure measurement = Measure.MeasureLong.create("Bar", "The description of Bar", "1");
+ assertThat(measurement.getName()).isEqualTo("Bar");
+ assertThat(measurement.getDescription()).isEqualTo("The description of Bar");
+ assertThat(measurement.getUnit()).isEqualTo("1");
+ }
+
+ @Test
+ public void testMeasureDoubleEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Measure.MeasureDouble.create("name", "description", "bit/s"),
+ Measure.MeasureDouble.create("name", "description", "bit/s"))
+ .addEqualityGroup(Measure.MeasureDouble.create("name", "description 2", "bit/s"))
+ .testEquals();
+ }
+
+ @Test
+ public void testMeasureLongEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Measure.MeasureLong.create("name", "description", "bit/s"),
+ Measure.MeasureLong.create("name", "description", "bit/s"))
+ .addEqualityGroup(Measure.MeasureLong.create("name", "description 2", "bit/s"))
+ .testEquals();
+ }
+
+ @Test
+ public void testMatch() {
+ List<Measure> measures =
+ Arrays.asList(
+ MeasureDouble.create("measure1", "description", "1"),
+ MeasureLong.create("measure2", "description", "1"));
+ List<String> outputs = Lists.newArrayList();
+ for (Measure measure : measures) {
+ outputs.add(
+ measure.match(
+ new Function<MeasureDouble, String>() {
+ @Override
+ public String apply(MeasureDouble arg) {
+ return "double";
+ }
+ },
+ new Function<MeasureLong, String>() {
+ @Override
+ public String apply(MeasureLong arg) {
+ return "long";
+ }
+ },
+ Functions.<String>throwAssertionError()));
+ }
+ assertThat(outputs).containsExactly("double", "long").inOrder();
+ }
+
+ @Test
+ public void testMeasureDoubleIsNotEqualToMeasureLong() {
+ assertThat(Measure.MeasureDouble.create("name", "description", "bit/s"))
+ .isNotEqualTo(Measure.MeasureLong.create("name", "description", "bit/s"));
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java
new file mode 100644
index 00000000..4bae14a6
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.stats.Measure.MeasureDouble;
+import io.opencensus.tags.Tag;
+import io.opencensus.tags.TagContext;
+import io.opencensus.tags.TagKey;
+import io.opencensus.tags.TagValue;
+import java.util.Collections;
+import java.util.Iterator;
+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 NoopStats}. Tests for {@link NoopStats#newNoopViewManager} are in {@link
+ * NoopViewManagerTest}
+ */
+@RunWith(JUnit4.class)
+public final class NoopStatsTest {
+ private static final Tag TAG = Tag.create(TagKey.create("key"), TagValue.create("value"));
+ private static final MeasureDouble MEASURE =
+ Measure.MeasureDouble.create("my measure", "description", "s");
+
+ private final TagContext tagContext =
+ new TagContext() {
+
+ @Override
+ protected Iterator<Tag> getIterator() {
+ return Collections.<Tag>singleton(TAG).iterator();
+ }
+ };
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void noopStatsComponent() {
+ assertThat(NoopStats.newNoopStatsComponent().getStatsRecorder())
+ .isSameAs(NoopStats.getNoopStatsRecorder());
+ assertThat(NoopStats.newNoopStatsComponent().getViewManager())
+ .isInstanceOf(NoopStats.newNoopViewManager().getClass());
+ }
+
+ @Test
+ public void noopStatsComponent_GetState() {
+ assertThat(NoopStats.newNoopStatsComponent().getState())
+ .isEqualTo(StatsCollectionState.DISABLED);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void noopStatsComponent_SetState_IgnoresInput() {
+ StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent();
+ noopStatsComponent.setState(StatsCollectionState.ENABLED);
+ assertThat(noopStatsComponent.getState()).isEqualTo(StatsCollectionState.DISABLED);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void noopStatsComponent_SetState_DisallowsNull() {
+ StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent();
+ thrown.expect(NullPointerException.class);
+ noopStatsComponent.setState(null);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void noopStatsComponent_DisallowsSetStateAfterGetState() {
+ StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent();
+ noopStatsComponent.setState(StatsCollectionState.DISABLED);
+ noopStatsComponent.getState();
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("State was already read, cannot set state.");
+ noopStatsComponent.setState(StatsCollectionState.ENABLED);
+ }
+
+ @Test
+ public void noopStatsRecorder_PutAttachmentNullKey() {
+ MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap();
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("key");
+ measureMap.putAttachment(null, "value");
+ }
+
+ @Test
+ public void noopStatsRecorder_PutAttachmentNullValue() {
+ MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap();
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value");
+ measureMap.putAttachment("key", null);
+ }
+
+ // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an
+ // exception.
+ @Test
+ public void noopStatsRecorder_Record() {
+ NoopStats.getNoopStatsRecorder().newMeasureMap().put(MEASURE, 5).record(tagContext);
+ }
+
+ // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an
+ // exception.
+ @Test
+ public void noopStatsRecorder_RecordWithCurrentContext() {
+ NoopStats.getNoopStatsRecorder().newMeasureMap().put(MEASURE, 6).record();
+ }
+
+ @Test
+ public void noopStatsRecorder_Record_DisallowNullTagContext() {
+ MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap();
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("tags");
+ measureMap.record(null);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java
new file mode 100644
index 00000000..44c7626f
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.common.Duration;
+import io.opencensus.common.Timestamp;
+import io.opencensus.stats.Aggregation.Sum;
+import io.opencensus.stats.Measure.MeasureDouble;
+import io.opencensus.stats.View.AggregationWindow.Cumulative;
+import io.opencensus.stats.View.AggregationWindow.Interval;
+import io.opencensus.stats.View.Name;
+import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData;
+import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData;
+import io.opencensus.tags.TagKey;
+import java.util.Arrays;
+import java.util.Set;
+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 NoopStats#newNoopViewManager}. */
+@RunWith(JUnit4.class)
+public final class NoopViewManagerTest {
+ private static final MeasureDouble MEASURE =
+ Measure.MeasureDouble.create("my measure", "description", "s");
+ private static final TagKey KEY = TagKey.create("KEY");
+ private static final Name VIEW_NAME = Name.create("my view");
+ private static final String VIEW_DESCRIPTION = "view description";
+ private static final Sum AGGREGATION = Sum.create();
+ private static final Cumulative CUMULATIVE = Cumulative.create();
+ private static final Duration TEN_SECONDS = Duration.create(10, 0);
+ private static final Interval INTERVAL = Interval.create(TEN_SECONDS);
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void noopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSameName() {
+ final View view1 =
+ View.create(
+ VIEW_NAME, "description 1", MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE);
+ final View view2 =
+ View.create(
+ VIEW_NAME, "description 2", MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE);
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ viewManager.registerView(view1);
+
+ try {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("A different view with the same name already exists.");
+ viewManager.registerView(view2);
+ } finally {
+ assertThat(viewManager.getView(VIEW_NAME).getView()).isEqualTo(view1);
+ }
+ }
+
+ @Test
+ public void noopViewManager_RegisterView_AllowRegisteringSameViewTwice() {
+ View view =
+ View.create(
+ VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE);
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ viewManager.registerView(view);
+ viewManager.registerView(view);
+ }
+
+ @Test
+ public void noopViewManager_RegisterView_DisallowNull() {
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ thrown.expect(NullPointerException.class);
+ viewManager.registerView(null);
+ }
+
+ @Test
+ public void noopViewManager_GetView_GettingNonExistentViewReturnsNull() {
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ assertThat(viewManager.getView(VIEW_NAME)).isNull();
+ }
+
+ @Test
+ public void noopViewManager_GetView_Cumulative() {
+ View view =
+ View.create(
+ VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE);
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ viewManager.registerView(view);
+
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+ assertThat(viewData.getView()).isEqualTo(view);
+ assertThat(viewData.getAggregationMap()).isEmpty();
+ assertThat(viewData.getStart()).isEqualTo(Timestamp.create(0, 0));
+ assertThat(viewData.getEnd()).isEqualTo(Timestamp.create(0, 0));
+ assertThat(viewData.getWindowData())
+ .isEqualTo(CumulativeData.create(Timestamp.create(0, 0), Timestamp.create(0, 0)));
+ }
+
+ @Test
+ public void noopViewManager_GetView_Interval() {
+ View view =
+ View.create(
+ VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), INTERVAL);
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ viewManager.registerView(view);
+
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+ assertThat(viewData.getView()).isEqualTo(view);
+ assertThat(viewData.getAggregationMap()).isEmpty();
+ assertThat(viewData.getWindowData()).isEqualTo(IntervalData.create(Timestamp.create(0, 0)));
+ }
+
+ @Test
+ public void noopViewManager_GetView_DisallowNull() {
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ thrown.expect(NullPointerException.class);
+ viewManager.getView(null);
+ }
+
+ @Test
+ public void getAllExportedViews() {
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ assertThat(viewManager.getAllExportedViews()).isEmpty();
+ View cumulativeView1 =
+ View.create(
+ View.Name.create("View 1"),
+ VIEW_DESCRIPTION,
+ MEASURE,
+ AGGREGATION,
+ Arrays.asList(KEY),
+ CUMULATIVE);
+ View cumulativeView2 =
+ View.create(
+ View.Name.create("View 2"),
+ VIEW_DESCRIPTION,
+ MEASURE,
+ AGGREGATION,
+ Arrays.asList(KEY),
+ CUMULATIVE);
+ View intervalView =
+ View.create(
+ View.Name.create("View 3"),
+ VIEW_DESCRIPTION,
+ MEASURE,
+ AGGREGATION,
+ Arrays.asList(KEY),
+ INTERVAL);
+ viewManager.registerView(cumulativeView1);
+ viewManager.registerView(cumulativeView2);
+ viewManager.registerView(intervalView);
+
+ // Only cumulative views should be exported.
+ assertThat(viewManager.getAllExportedViews()).containsExactly(cumulativeView1, cumulativeView2);
+ }
+
+ @Test
+ public void getAllExportedViews_ResultIsUnmodifiable() {
+ ViewManager viewManager = NoopStats.newNoopViewManager();
+ View view1 =
+ View.create(
+ View.Name.create("View 1"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY));
+ viewManager.registerView(view1);
+ Set<View> exported = viewManager.getAllExportedViews();
+
+ View view2 =
+ View.create(
+ View.Name.create("View 2"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY));
+ thrown.expect(UnsupportedOperationException.class);
+ exported.add(view2);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/StatsTest.java b/api/src/test/java/io/opencensus/stats/StatsTest.java
new file mode 100644
index 00000000..4219173a
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/StatsTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link Stats}. */
+@RunWith(JUnit4.class)
+public final class StatsTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void loadStatsManager_UsesProvidedClassLoader() {
+ final RuntimeException toThrow = new RuntimeException("UseClassLoader");
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("UseClassLoader");
+ Stats.loadStatsComponent(
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) {
+ throw toThrow;
+ }
+ });
+ }
+
+ @Test
+ public void loadStatsManager_IgnoresMissingClasses() {
+ ClassLoader classLoader =
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException();
+ }
+ };
+
+ assertThat(Stats.loadStatsComponent(classLoader).getClass().getName())
+ .isEqualTo("io.opencensus.stats.NoopStats$NoopStatsComponent");
+ }
+
+ @Test
+ public void defaultValues() {
+ assertThat(Stats.getStatsRecorder()).isEqualTo(NoopStats.getNoopStatsRecorder());
+ assertThat(Stats.getViewManager()).isInstanceOf(NoopStats.newNoopViewManager().getClass());
+ }
+
+ @Test
+ public void getState() {
+ assertThat(Stats.getState()).isEqualTo(StatsCollectionState.DISABLED);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void setState_IgnoresInput() {
+ Stats.setState(StatsCollectionState.ENABLED);
+ assertThat(Stats.getState()).isEqualTo(StatsCollectionState.DISABLED);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void setState_DisallowsNull() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("state");
+ Stats.setState(null);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java
new file mode 100644
index 00000000..0120ffea
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Duration;
+import io.opencensus.common.Function;
+import io.opencensus.common.Functions;
+import io.opencensus.common.Timestamp;
+import io.opencensus.stats.Aggregation.Count;
+import io.opencensus.stats.Aggregation.Distribution;
+import io.opencensus.stats.Aggregation.LastValue;
+import io.opencensus.stats.Aggregation.Mean;
+import io.opencensus.stats.Aggregation.Sum;
+import io.opencensus.stats.AggregationData.CountData;
+import io.opencensus.stats.AggregationData.DistributionData;
+import io.opencensus.stats.AggregationData.LastValueDataDouble;
+import io.opencensus.stats.AggregationData.LastValueDataLong;
+import io.opencensus.stats.AggregationData.SumDataDouble;
+import io.opencensus.stats.AggregationData.SumDataLong;
+import io.opencensus.stats.View.AggregationWindow;
+import io.opencensus.stats.View.AggregationWindow.Cumulative;
+import io.opencensus.stats.View.AggregationWindow.Interval;
+import io.opencensus.stats.ViewData.AggregationWindowData;
+import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData;
+import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData;
+import io.opencensus.tags.TagKey;
+import io.opencensus.tags.TagValue;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for class {@link ViewData}. */
+@RunWith(JUnit4.class)
+public final class ViewDataTest {
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testCumulativeViewData() {
+ View view = View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE);
+ Timestamp start = Timestamp.fromMillis(1000);
+ Timestamp end = Timestamp.fromMillis(2000);
+ AggregationWindowData windowData = CumulativeData.create(start, end);
+ ViewData viewData = ViewData.create(view, ENTRIES, windowData);
+ assertThat(viewData.getView()).isEqualTo(view);
+ assertThat(viewData.getAggregationMap()).isEqualTo(ENTRIES);
+ assertThat(viewData.getWindowData()).isEqualTo(windowData);
+ }
+
+ @Test
+ public void testIntervalViewData() {
+ View view =
+ View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR);
+ Timestamp end = Timestamp.fromMillis(2000);
+ AggregationWindowData windowData = IntervalData.create(end);
+ ViewData viewData = ViewData.create(view, ENTRIES, windowData);
+ assertThat(viewData.getView()).isEqualTo(view);
+ assertThat(viewData.getAggregationMap()).isEqualTo(ENTRIES);
+ assertThat(viewData.getWindowData()).isEqualTo(windowData);
+ }
+
+ @Test
+ public void testViewDataEquals() {
+ View cumulativeView =
+ View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE);
+ View intervalView =
+ View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR);
+
+ new EqualsTester()
+ .addEqualityGroup(
+ ViewData.create(
+ cumulativeView,
+ ENTRIES,
+ CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))),
+ ViewData.create(
+ cumulativeView,
+ ENTRIES,
+ CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))))
+ .addEqualityGroup(
+ ViewData.create(
+ cumulativeView,
+ ENTRIES,
+ CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(3000))))
+ .addEqualityGroup(
+ ViewData.create(intervalView, ENTRIES, IntervalData.create(Timestamp.fromMillis(2000))),
+ ViewData.create(intervalView, ENTRIES, IntervalData.create(Timestamp.fromMillis(2000))))
+ .addEqualityGroup(
+ ViewData.create(
+ intervalView,
+ Collections.<List<TagValue>, AggregationData>emptyMap(),
+ IntervalData.create(Timestamp.fromMillis(2000))))
+ .testEquals();
+ }
+
+ @Test
+ public void testAggregationWindowDataMatch() {
+ final Timestamp start = Timestamp.fromMillis(1000);
+ final Timestamp end = Timestamp.fromMillis(2000);
+ final AggregationWindowData windowData1 = CumulativeData.create(start, end);
+ final AggregationWindowData windowData2 = IntervalData.create(end);
+ windowData1.match(
+ new Function<CumulativeData, Void>() {
+ @Override
+ public Void apply(CumulativeData windowData) {
+ assertThat(windowData.getStart()).isEqualTo(start);
+ assertThat(windowData.getEnd()).isEqualTo(end);
+ return null;
+ }
+ },
+ new Function<IntervalData, Void>() {
+ @Override
+ public Void apply(IntervalData windowData) {
+ fail("CumulativeData expected.");
+ return null;
+ }
+ },
+ Functions.<Void>throwIllegalArgumentException());
+ windowData2.match(
+ new Function<CumulativeData, Void>() {
+ @Override
+ public Void apply(CumulativeData windowData) {
+ fail("IntervalData expected.");
+ return null;
+ }
+ },
+ new Function<IntervalData, Void>() {
+ @Override
+ public Void apply(IntervalData windowData) {
+ assertThat(windowData.getEnd()).isEqualTo(end);
+ return null;
+ }
+ },
+ Functions.<Void>throwIllegalArgumentException());
+ }
+
+ @Test
+ public void preventWindowAndAggregationWindowDataMismatch() {
+ CumulativeData cumulativeData =
+ CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000));
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(
+ "AggregationWindow and AggregationWindowData types mismatch. "
+ + "AggregationWindow: "
+ + INTERVAL_HOUR.getClass().getSimpleName()
+ + " AggregationWindowData: "
+ + cumulativeData.getClass().getSimpleName());
+ ViewData.create(
+ View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR),
+ ENTRIES,
+ cumulativeData);
+ }
+
+ @Test
+ public void preventWindowAndAggregationWindowDataMismatch2() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("AggregationWindow and AggregationWindowData types mismatch. ");
+ ViewData.create(
+ View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE),
+ ENTRIES,
+ IntervalData.create(Timestamp.fromMillis(1000)));
+ }
+
+ @Test
+ public void preventStartTimeLaterThanEndTime() {
+ thrown.expect(IllegalArgumentException.class);
+ CumulativeData.create(Timestamp.fromMillis(3000), Timestamp.fromMillis(2000));
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_SumDouble_SumLong() {
+ aggregationAndAggregationDataMismatch(
+ createView(Sum.create(), MEASURE_DOUBLE),
+ ImmutableMap.<List<TagValue>, AggregationData>of(
+ Arrays.asList(V1, V2), SumDataLong.create(100)));
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_SumLong_SumDouble() {
+ aggregationAndAggregationDataMismatch(
+ createView(Sum.create(), MEASURE_LONG),
+ ImmutableMap.<List<TagValue>, AggregationData>of(
+ Arrays.asList(V1, V2), SumDataDouble.create(100)));
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_Count_Distribution() {
+ aggregationAndAggregationDataMismatch(createView(Count.create()), ENTRIES);
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_Mean_Distribution() {
+ aggregationAndAggregationDataMismatch(createView(Mean.create()), ENTRIES);
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_Distribution_Count() {
+ aggregationAndAggregationDataMismatch(
+ createView(DISTRIBUTION), ImmutableMap.of(Arrays.asList(V10, V20), CountData.create(100)));
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_LastValueDouble_LastValueLong() {
+ aggregationAndAggregationDataMismatch(
+ createView(LastValue.create(), MEASURE_DOUBLE),
+ ImmutableMap.<List<TagValue>, AggregationData>of(
+ Arrays.asList(V1, V2), LastValueDataLong.create(100)));
+ }
+
+ @Test
+ public void preventAggregationAndAggregationDataMismatch_LastValueLong_LastValueDouble() {
+ aggregationAndAggregationDataMismatch(
+ createView(LastValue.create(), MEASURE_LONG),
+ ImmutableMap.<List<TagValue>, AggregationData>of(
+ Arrays.asList(V1, V2), LastValueDataDouble.create(100)));
+ }
+
+ private static View createView(Aggregation aggregation) {
+ return createView(aggregation, MEASURE_DOUBLE);
+ }
+
+ private static View createView(Aggregation aggregation, Measure measure) {
+ return View.create(NAME, DESCRIPTION, measure, aggregation, TAG_KEYS, CUMULATIVE);
+ }
+
+ private void aggregationAndAggregationDataMismatch(
+ View view, Map<List<TagValue>, ? extends AggregationData> entries) {
+ CumulativeData cumulativeData =
+ CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000));
+ Aggregation aggregation = view.getAggregation();
+ AggregationData aggregationData = entries.values().iterator().next();
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage(
+ "Aggregation and AggregationData types mismatch. "
+ + "Aggregation: "
+ + aggregation.getClass().getSimpleName()
+ + " AggregationData: "
+ + aggregationData.getClass().getSimpleName());
+ ViewData.create(view, entries, cumulativeData);
+ }
+
+ // tag keys
+ private static final TagKey K1 = TagKey.create("k1");
+ private static final TagKey K2 = TagKey.create("k2");
+ private static final List<TagKey> TAG_KEYS = Arrays.asList(K1, K2);
+
+ // tag values
+ private static final TagValue V1 = TagValue.create("v1");
+ private static final TagValue V2 = TagValue.create("v2");
+ private static final TagValue V10 = TagValue.create("v10");
+ private static final TagValue V20 = TagValue.create("v20");
+
+ private static final AggregationWindow CUMULATIVE = Cumulative.create();
+ private static final AggregationWindow INTERVAL_HOUR = Interval.create(Duration.create(3600, 0));
+
+ private static final BucketBoundaries BUCKET_BOUNDARIES =
+ BucketBoundaries.create(Arrays.asList(10.0, 20.0, 30.0, 40.0));
+
+ private static final Aggregation DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES);
+
+ private static final ImmutableMap<List<TagValue>, DistributionData> ENTRIES =
+ ImmutableMap.of(
+ Arrays.asList(V1, V2),
+ DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 0L)),
+ Arrays.asList(V10, V20),
+ DistributionData.create(-5, 6, -20, 5, 100.1, Arrays.asList(5L, 0L, 1L)));
+
+ // name
+ private static final View.Name NAME = View.Name.create("test-view");
+ // description
+ private static final String DESCRIPTION = "test-view-descriptor description";
+ // measure
+ private static final Measure MEASURE_DOUBLE =
+ Measure.MeasureDouble.create("measure1", "measure description", "1");
+ private static final Measure MEASURE_LONG =
+ Measure.MeasureLong.create("measure2", "measure description", "1");
+}
diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java
new file mode 100644
index 00000000..afba1bc0
--- /dev/null
+++ b/api/src/test/java/io/opencensus/stats/ViewTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.common.Duration;
+import io.opencensus.stats.Aggregation.Mean;
+import io.opencensus.stats.View.AggregationWindow.Cumulative;
+import io.opencensus.stats.View.AggregationWindow.Interval;
+import io.opencensus.tags.TagKey;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link View}. */
+@RunWith(JUnit4.class)
+public final class ViewTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testConstants() {
+ assertThat(View.NAME_MAX_LENGTH).isEqualTo(255);
+ }
+
+ @Test
+ public void sortTagKeys() {
+ final View view =
+ View.create(
+ NAME,
+ DESCRIPTION,
+ MEASURE,
+ MEAN,
+ Arrays.asList(
+ TagKey.create("ab"), TagKey.create("a"), TagKey.create("A"), TagKey.create("b")));
+ assertThat(view.getColumns())
+ .containsExactly(
+ TagKey.create("A"), TagKey.create("a"), TagKey.create("ab"), TagKey.create("b"))
+ .inOrder();
+ }
+
+ @Test
+ public void testDistributionView() {
+ final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS);
+ assertThat(view.getName()).isEqualTo(NAME);
+ assertThat(view.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName());
+ assertThat(view.getAggregation()).isEqualTo(MEAN);
+ assertThat(view.getColumns()).containsExactly(BAR, FOO).inOrder();
+ assertThat(view.getWindow()).isEqualTo(Cumulative.create());
+ }
+
+ @Test
+ public void testIntervalView() {
+ final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE));
+ assertThat(view.getName()).isEqualTo(NAME);
+ assertThat(view.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName());
+ assertThat(view.getAggregation()).isEqualTo(MEAN);
+ assertThat(view.getColumns()).containsExactly(BAR, FOO).inOrder();
+ assertThat(view.getWindow()).isEqualTo(Interval.create(MINUTE));
+ }
+
+ @Test
+ public void testViewEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS),
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create()))
+ .addEqualityGroup(
+ View.create(NAME, DESCRIPTION + 2, MEASURE, MEAN, KEYS, Cumulative.create()))
+ .addEqualityGroup(
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)),
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)))
+ .addEqualityGroup(
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(TWO_MINUTES)))
+ .testEquals();
+ }
+
+ @Test
+ public void preventDuplicateColumns() {
+ TagKey key1 = TagKey.create("duplicate");
+ TagKey key2 = TagKey.create("duplicate");
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Columns have duplicate.");
+ View.create(NAME, DESCRIPTION, MEASURE, MEAN, Arrays.asList(key1, key2));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void preventNullViewName() {
+ View.create(null, DESCRIPTION, MEASURE, MEAN, KEYS);
+ }
+
+ @Test
+ public void preventTooLongViewName() {
+ char[] chars = new char[View.NAME_MAX_LENGTH + 1];
+ Arrays.fill(chars, 'a');
+ String longName = String.valueOf(chars);
+ thrown.expect(IllegalArgumentException.class);
+ View.Name.create(longName);
+ }
+
+ @Test
+ public void preventNonPrintableViewName() {
+ thrown.expect(IllegalArgumentException.class);
+ View.Name.create("\2");
+ }
+
+ @Test
+ public void testViewName() {
+ assertThat(View.Name.create("my name").asString()).isEqualTo("my name");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void preventNullNameString() {
+ View.Name.create(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void preventNegativeIntervalDuration() {
+ Interval.create(NEG_TEN_SECONDS);
+ }
+
+ @Test
+ public void testViewNameEquals() {
+ new EqualsTester()
+ .addEqualityGroup(View.Name.create("view-1"), View.Name.create("view-1"))
+ .addEqualityGroup(View.Name.create("view-2"))
+ .testEquals();
+ }
+
+ private static final View.Name NAME = View.Name.create("test-view-name");
+ private static final String DESCRIPTION = "test-view-name description";
+ private static final Measure MEASURE =
+ Measure.MeasureDouble.create("measure", "measure description", "1");
+ private static final TagKey FOO = TagKey.create("foo");
+ private static final TagKey BAR = TagKey.create("bar");
+ private static final List<TagKey> KEYS = Collections.unmodifiableList(Arrays.asList(FOO, BAR));
+ private static final Mean MEAN = Mean.create();
+ private static final Duration MINUTE = Duration.create(60, 0);
+ private static final Duration TWO_MINUTES = Duration.create(120, 0);
+ private static final Duration NEG_TEN_SECONDS = Duration.create(-10, 0);
+}
diff --git a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java
new file mode 100644
index 00000000..65482de1
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Lists;
+import java.util.Iterator;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link InternalUtils}. */
+@RunWith(JUnit4.class)
+public final class InternalUtilsTest {
+
+ @Test
+ public void getTags() {
+ final Iterator<Tag> iterator =
+ Lists.<Tag>newArrayList(Tag.create(TagKey.create("k"), TagValue.create("v"))).iterator();
+ TagContext ctx =
+ new TagContext() {
+ @Override
+ protected Iterator<Tag> getIterator() {
+ return iterator;
+ }
+ };
+ assertThat(InternalUtils.getTags(ctx)).isSameAs(iterator);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java
new file mode 100644
index 00000000..db07520e
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Lists;
+import io.opencensus.internal.NoopScope;
+import io.opencensus.tags.propagation.TagContextBinarySerializer;
+import io.opencensus.tags.propagation.TagContextDeserializationException;
+import io.opencensus.tags.propagation.TagContextSerializationException;
+import java.util.Arrays;
+import java.util.Iterator;
+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 NoopTags}. */
+@RunWith(JUnit4.class)
+public final class NoopTagsTest {
+ private static final TagKey KEY = TagKey.create("key");
+ private static final TagValue VALUE = TagValue.create("value");
+
+ private static final TagContext TAG_CONTEXT =
+ new TagContext() {
+
+ @Override
+ protected Iterator<Tag> getIterator() {
+ return Arrays.<Tag>asList(Tag.create(KEY, VALUE)).iterator();
+ }
+ };
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void noopTagsComponent() {
+ assertThat(NoopTags.newNoopTagsComponent().getTagger()).isSameAs(NoopTags.getNoopTagger());
+ assertThat(NoopTags.newNoopTagsComponent().getTagPropagationComponent())
+ .isSameAs(NoopTags.getNoopTagPropagationComponent());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void noopTagsComponent_SetState_DisallowsNull() {
+ TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent();
+ thrown.expect(NullPointerException.class);
+ noopTagsComponent.setState(null);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void preventSettingStateAfterGettingState_DifferentState() {
+ TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent();
+ noopTagsComponent.setState(TaggingState.DISABLED);
+ noopTagsComponent.getState();
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("State was already read, cannot set state.");
+ noopTagsComponent.setState(TaggingState.ENABLED);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void preventSettingStateAfterGettingState_SameState() {
+ TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent();
+ noopTagsComponent.setState(TaggingState.DISABLED);
+ noopTagsComponent.getState();
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("State was already read, cannot set state.");
+ noopTagsComponent.setState(TaggingState.DISABLED);
+ }
+
+ @Test
+ public void noopTagger() {
+ Tagger noopTagger = NoopTags.getNoopTagger();
+ assertThat(noopTagger.empty()).isSameAs(NoopTags.getNoopTagContext());
+ assertThat(noopTagger.getCurrentTagContext()).isSameAs(NoopTags.getNoopTagContext());
+ assertThat(noopTagger.emptyBuilder()).isSameAs(NoopTags.getNoopTagContextBuilder());
+ assertThat(noopTagger.toBuilder(TAG_CONTEXT)).isSameAs(NoopTags.getNoopTagContextBuilder());
+ assertThat(noopTagger.currentBuilder()).isSameAs(NoopTags.getNoopTagContextBuilder());
+ assertThat(noopTagger.withTagContext(TAG_CONTEXT)).isSameAs(NoopScope.getInstance());
+ }
+
+ @Test
+ public void noopTagger_ToBuilder_DisallowsNull() {
+ Tagger noopTagger = NoopTags.getNoopTagger();
+ thrown.expect(NullPointerException.class);
+ noopTagger.toBuilder(null);
+ }
+
+ @Test
+ public void noopTagger_WithTagContext_DisallowsNull() {
+ Tagger noopTagger = NoopTags.getNoopTagger();
+ thrown.expect(NullPointerException.class);
+ noopTagger.withTagContext(null);
+ }
+
+ @Test
+ public void noopTagContextBuilder() {
+ assertThat(NoopTags.getNoopTagContextBuilder().build()).isSameAs(NoopTags.getNoopTagContext());
+ assertThat(NoopTags.getNoopTagContextBuilder().put(KEY, VALUE).build())
+ .isSameAs(NoopTags.getNoopTagContext());
+ assertThat(NoopTags.getNoopTagContextBuilder().buildScoped()).isSameAs(NoopScope.getInstance());
+ assertThat(NoopTags.getNoopTagContextBuilder().put(KEY, VALUE).buildScoped())
+ .isSameAs(NoopScope.getInstance());
+ }
+
+ @Test
+ public void noopTagContextBuilder_Put_DisallowsNullKey() {
+ TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder();
+ thrown.expect(NullPointerException.class);
+ noopBuilder.put(null, VALUE);
+ }
+
+ @Test
+ public void noopTagContextBuilder_Put_DisallowsNullValue() {
+ TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder();
+ thrown.expect(NullPointerException.class);
+ noopBuilder.put(KEY, null);
+ }
+
+ @Test
+ public void noopTagContextBuilder_Remove_DisallowsNullKey() {
+ TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder();
+ thrown.expect(NullPointerException.class);
+ noopBuilder.remove(null);
+ }
+
+ @Test
+ public void noopTagContext() {
+ assertThat(Lists.newArrayList(NoopTags.getNoopTagContext().getIterator())).isEmpty();
+ }
+
+ @Test
+ public void noopTagPropagationComponent() {
+ assertThat(NoopTags.getNoopTagPropagationComponent().getBinarySerializer())
+ .isSameAs(NoopTags.getNoopTagContextBinarySerializer());
+ }
+
+ @Test
+ public void noopTagContextBinarySerializer()
+ throws TagContextDeserializationException, TagContextSerializationException {
+ assertThat(NoopTags.getNoopTagContextBinarySerializer().toByteArray(TAG_CONTEXT))
+ .isEqualTo(new byte[0]);
+ assertThat(NoopTags.getNoopTagContextBinarySerializer().fromByteArray(new byte[5]))
+ .isEqualTo(NoopTags.getNoopTagContext());
+ }
+
+ @Test
+ public void noopTagContextBinarySerializer_ToByteArray_DisallowsNull()
+ throws TagContextSerializationException {
+ TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer();
+ thrown.expect(NullPointerException.class);
+ noopSerializer.toByteArray(null);
+ }
+
+ @Test
+ public void noopTagContextBinarySerializer_FromByteArray_DisallowsNull()
+ throws TagContextDeserializationException {
+ TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer();
+ thrown.expect(NullPointerException.class);
+ noopSerializer.fromByteArray(null);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java
new file mode 100644
index 00000000..025c7bae
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Lists;
+import com.google.common.testing.EqualsTester;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link TagContext}. */
+@RunWith(JUnit4.class)
+public final class TagContextTest {
+ private static final Tag TAG1 = Tag.create(TagKey.create("key"), TagValue.create("val"));
+ private static final Tag TAG2 = Tag.create(TagKey.create("key2"), TagValue.create("val"));
+
+ @Test
+ public void equals_IgnoresTagOrderAndTagContextClass() {
+ new EqualsTester()
+ .addEqualityGroup(
+ new SimpleTagContext(TAG1, TAG2),
+ new SimpleTagContext(TAG1, TAG2),
+ new SimpleTagContext(TAG2, TAG1),
+ new TagContext() {
+ @Override
+ protected Iterator<Tag> getIterator() {
+ return Lists.newArrayList(TAG1, TAG2).iterator();
+ }
+ })
+ .testEquals();
+ }
+
+ @Test
+ public void equals_HandlesNullIterator() {
+ new EqualsTester()
+ .addEqualityGroup(
+ new SimpleTagContext((List<Tag>) null),
+ new SimpleTagContext((List<Tag>) null),
+ new SimpleTagContext())
+ .testEquals();
+ }
+
+ @Test
+ public void equals_DoesNotIgnoreNullTags() {
+ new EqualsTester()
+ .addEqualityGroup(new SimpleTagContext(TAG1))
+ .addEqualityGroup(new SimpleTagContext(TAG1, null), new SimpleTagContext(null, TAG1))
+ .addEqualityGroup(new SimpleTagContext(TAG1, null, null))
+ .testEquals();
+ }
+
+ @Test
+ public void equals_DoesNotIgnoreDuplicateTags() {
+ new EqualsTester()
+ .addEqualityGroup(new SimpleTagContext(TAG1))
+ .addEqualityGroup(new SimpleTagContext(TAG1, TAG1))
+ .testEquals();
+ }
+
+ @Test
+ public void testToString() {
+ assertThat(new SimpleTagContext().toString()).isEqualTo("TagContext");
+ assertThat(new SimpleTagContext(TAG1, TAG2).toString()).isEqualTo("TagContext");
+ }
+
+ private static final class SimpleTagContext extends TagContext {
+ @Nullable private final List<Tag> tags;
+
+ SimpleTagContext(Tag... tags) {
+ this(Lists.newArrayList(tags));
+ }
+
+ SimpleTagContext(List<Tag> tags) {
+ this.tags = tags == null ? null : Collections.unmodifiableList(Lists.newArrayList(tags));
+ }
+
+ @Override
+ @Nullable
+ protected Iterator<Tag> getIterator() {
+ return tags == null ? null : tags.iterator();
+ }
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java
new file mode 100644
index 00000000..48cf9fd4
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+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;
+
+/** Tests for {@link TagKey}. */
+@RunWith(JUnit4.class)
+public final class TagKeyTest {
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testMaxLength() {
+ assertThat(TagKey.MAX_LENGTH).isEqualTo(255);
+ }
+
+ @Test
+ public void testGetName() {
+ assertThat(TagKey.create("foo").getName()).isEqualTo("foo");
+ }
+
+ @Test
+ public void create_AllowTagKeyNameWithMaxLength() {
+ char[] chars = new char[TagKey.MAX_LENGTH];
+ Arrays.fill(chars, 'k');
+ String key = new String(chars);
+ assertThat(TagKey.create(key).getName()).isEqualTo(key);
+ }
+
+ @Test
+ public void create_DisallowTagKeyNameOverMaxLength() {
+ char[] chars = new char[TagKey.MAX_LENGTH + 1];
+ Arrays.fill(chars, 'k');
+ String key = new String(chars);
+ thrown.expect(IllegalArgumentException.class);
+ TagKey.create(key);
+ }
+
+ @Test
+ public void create_DisallowUnprintableChars() {
+ thrown.expect(IllegalArgumentException.class);
+ TagKey.create("\2ab\3cd");
+ }
+
+ @Test
+ public void createString_DisallowEmpty() {
+ thrown.expect(IllegalArgumentException.class);
+ TagKey.create("");
+ }
+
+ @Test
+ public void testTagKeyEquals() {
+ new EqualsTester()
+ .addEqualityGroup(TagKey.create("foo"), TagKey.create("foo"))
+ .addEqualityGroup(TagKey.create("bar"))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/TagTest.java b/api/src/test/java/io/opencensus/tags/TagTest.java
new file mode 100644
index 00000000..3c899e65
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/TagTest.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.tags;
+
+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;
+
+/** Tests for {@link Tag}. */
+@RunWith(JUnit4.class)
+public final class TagTest {
+
+ @Test
+ public void testGetKey() {
+ assertThat(Tag.create(TagKey.create("k"), TagValue.create("v")).getKey())
+ .isEqualTo(TagKey.create("k"));
+ }
+
+ @Test
+ public void testTagEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Tag.create(TagKey.create("Key"), TagValue.create("foo")),
+ Tag.create(TagKey.create("Key"), TagValue.create("foo")))
+ .addEqualityGroup(Tag.create(TagKey.create("Key"), TagValue.create("bar")))
+ .addEqualityGroup(Tag.create(TagKey.create("Key2"), TagValue.create("foo")))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/TagValueTest.java b/api/src/test/java/io/opencensus/tags/TagValueTest.java
new file mode 100644
index 00000000..9aa42c8c
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/TagValueTest.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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+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;
+
+/** Tests for {@link TagValue}. */
+@RunWith(JUnit4.class)
+public final class TagValueTest {
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testMaxLength() {
+ assertThat(TagValue.MAX_LENGTH).isEqualTo(255);
+ }
+
+ @Test
+ public void testAsString() {
+ assertThat(TagValue.create("foo").asString()).isEqualTo("foo");
+ }
+
+ @Test
+ public void create_AllowTagValueWithMaxLength() {
+ char[] chars = new char[TagValue.MAX_LENGTH];
+ Arrays.fill(chars, 'v');
+ String value = new String(chars);
+ assertThat(TagValue.create(value).asString()).isEqualTo(value);
+ }
+
+ @Test
+ public void create_DisallowTagValueOverMaxLength() {
+ char[] chars = new char[TagValue.MAX_LENGTH + 1];
+ Arrays.fill(chars, 'v');
+ String value = new String(chars);
+ thrown.expect(IllegalArgumentException.class);
+ TagValue.create(value);
+ }
+
+ @Test
+ public void disallowTagValueWithUnprintableChars() {
+ String value = "\2ab\3cd";
+ thrown.expect(IllegalArgumentException.class);
+ TagValue.create(value);
+ }
+
+ @Test
+ public void testTagValueEquals() {
+ new EqualsTester()
+ .addEqualityGroup(TagValue.create("foo"), TagValue.create("foo"))
+ .addEqualityGroup(TagValue.create("bar"))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/TagsTest.java b/api/src/test/java/io/opencensus/tags/TagsTest.java
new file mode 100644
index 00000000..dee517b6
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/TagsTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.tags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 Tags}. */
+@RunWith(JUnit4.class)
+public class TagsTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void loadTagsComponent_UsesProvidedClassLoader() {
+ final RuntimeException toThrow = new RuntimeException("UseClassLoader");
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("UseClassLoader");
+ Tags.loadTagsComponent(
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) {
+ throw toThrow;
+ }
+ });
+ }
+
+ @Test
+ public void loadTagsComponent_IgnoresMissingClasses() {
+ ClassLoader classLoader =
+ new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException();
+ }
+ };
+ assertThat(Tags.loadTagsComponent(classLoader).getClass().getName())
+ .isEqualTo("io.opencensus.tags.NoopTags$NoopTagsComponent");
+ }
+
+ // There is only one test that modifies tagging state in the Tags class, since the state is
+ // global, and it could affect other tests. NoopTagsTest has more thorough tests for tagging
+ // state.
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testState() {
+ // Test that setState ignores its input.
+ Tags.setState(TaggingState.ENABLED);
+ assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED);
+
+ // Test that setState cannot be called after getState.
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("State was already read, cannot set state.");
+ Tags.setState(TaggingState.ENABLED);
+ }
+
+ @Test
+ public void defaultTagger() {
+ assertThat(Tags.getTagger()).isEqualTo(NoopTags.getNoopTagger());
+ }
+
+ @Test
+ public void defaultTagContextSerializer() {
+ assertThat(Tags.getTagPropagationComponent())
+ .isEqualTo(NoopTags.getNoopTagPropagationComponent());
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java
new file mode 100644
index 00000000..750d5d45
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tags.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 TagContextDeserializationException}. */
+@RunWith(JUnit4.class)
+public final class TagContextDeserializationExceptionTest {
+
+ @Test
+ public void createWithMessage() {
+ assertThat(new TagContextDeserializationException("my message").getMessage())
+ .isEqualTo("my message");
+ }
+
+ @Test
+ public void createWithMessageAndCause() {
+ IOException cause = new IOException();
+ TagContextDeserializationException exception =
+ new TagContextDeserializationException("my message", cause);
+ assertThat(exception.getMessage()).isEqualTo("my message");
+ assertThat(exception.getCause()).isEqualTo(cause);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java
new file mode 100644
index 00000000..54e9fab6
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tags.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 TagContextSerializationException}. */
+@RunWith(JUnit4.class)
+public final class TagContextSerializationExceptionTest {
+
+ @Test
+ public void createWithMessage() {
+ assertThat(new TagContextSerializationException("my message").getMessage())
+ .isEqualTo("my message");
+ }
+
+ @Test
+ public void createWithMessageAndCause() {
+ IOException cause = new IOException();
+ TagContextSerializationException exception =
+ new TagContextSerializationException("my message", cause);
+ assertThat(exception.getMessage()).isEqualTo("my message");
+ assertThat(exception.getCause()).isEqualTo(cause);
+ }
+}
diff --git a/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java b/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java
new file mode 100644
index 00000000..c35c5dc4
--- /dev/null
+++ b/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.tags.unsafe;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Lists;
+import io.grpc.Context;
+import io.opencensus.tags.InternalUtils;
+import io.opencensus.tags.Tag;
+import io.opencensus.tags.TagContext;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link ContextUtils}. */
+@RunWith(JUnit4.class)
+public final class ContextUtilsTest {
+ @Test
+ public void testContextKeyName() {
+ // Context.Key.toString() returns the name.
+ assertThat(ContextUtils.TAG_CONTEXT_KEY.toString()).isEqualTo("opencensus-tag-context-key");
+ }
+
+ @Test
+ public void testGetCurrentTagContext_DefaultContext() {
+ TagContext tags = ContextUtils.TAG_CONTEXT_KEY.get();
+ assertThat(tags).isNotNull();
+ assertThat(asList(tags)).isEmpty();
+ }
+
+ @Test
+ public void testGetCurrentTagContext_ContextSetToNull() {
+ Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, null).attach();
+ try {
+ TagContext tags = ContextUtils.TAG_CONTEXT_KEY.get();
+ assertThat(tags).isNotNull();
+ assertThat(asList(tags)).isEmpty();
+ } finally {
+ Context.current().detach(orig);
+ }
+ }
+
+ private static List<Tag> asList(TagContext tags) {
+ return Lists.newArrayList(InternalUtils.getTags(tags));
+ }
+}
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");
+ }
+}