Note: only use this when it is ok to modify the underlying {@link ByteBuffer#array()}.
+ */
+ public abstract boolean decodeList(ByteBuffer spans, Collection out);
+
+ /**
+ * ByteBuffer implementation of {@link #decodeList(byte[])}.
+ *
+ * Note: only use this when it is ok to modify the underlying {@link ByteBuffer#array()}.
+ */
+ public abstract List decodeList(ByteBuffer spans);
+
+ /**
+ * ByteBuffer implementation of {@link #decodeOne(byte[])}
+ *
+ * Note: only use this when it is ok to modify the underlying {@link ByteBuffer#array()}.
+ */
+ @Nullable public abstract Span decodeOne(ByteBuffer span);
+
static List decodeList(SpanBytesDecoder decoder, byte[] spans) {
List out = new ArrayList<>();
if (!decoder.decodeList(spans, out)) return Collections.emptyList();
return out;
}
+
+ static List decodeList(SpanBytesDecoder decoder, ByteBuffer spans) {
+ List out = new ArrayList<>();
+ if (!decoder.decodeList(spans, out)) return Collections.emptyList();
+ return out;
+ }
}
diff --git a/zipkin/src/main/java/zipkin2/internal/Dependencies.java b/zipkin/src/main/java/zipkin2/internal/Dependencies.java
index 6141ed519b1..adf5c937be4 100644
--- a/zipkin/src/main/java/zipkin2/internal/Dependencies.java
+++ b/zipkin/src/main/java/zipkin2/internal/Dependencies.java
@@ -27,7 +27,7 @@
import static zipkin2.internal.ThriftField.TYPE_LIST;
import static zipkin2.internal.ThriftField.TYPE_STOP;
import static zipkin2.internal.ThriftField.TYPE_STRING;
-import static zipkin2.internal.UnsafeBuffer.utf8SizeInBytes;
+import static zipkin2.internal.WriteBuffer.utf8SizeInBytes;
/**
* Internal as only cassandra serializes the start and end timestamps along with link data, and
@@ -45,29 +45,30 @@ public List Read operations do bounds checks, as typically more errors occur reading than writing.
- *
- * Writes are unsafe as they do no bounds checks. This means you should take care to allocate or
+ * Writes are unsafe as they do no bounds checks. This means you should take care to allocate or
* wrap an array at least as big as you need prior to writing. As it is possible to calculate size
* prior to writing, overrunning a buffer is a programming error.
*/
-public final class UnsafeBuffer {
- public static final char[] HEX_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
+public final class WriteBuffer {
+ public interface Writer Originally based on
- * http://stackoverflow.com/questions/8511490/calculating-length-in-utf-8-of-java-string-without-actually-encoding-it
- *
- * Later, ASCII run and malformed surrogate logic borrowed from okio.Utf8
- */
- public static int utf8SizeInBytes(CharSequence string) {
- int sizeInBytes = 0;
- for (int i = 0, len = string.length(); i < len; i++) {
- char ch = string.charAt(i);
- if (ch < 0x80) {
- sizeInBytes++; // 7-bit ASCII character
- // This could be an ASCII run, or possibly entirely ASCII
- while (i < len - 1) {
- ch = string.charAt(i + 1);
- if (ch >= 0x80) break;
- i++;
- sizeInBytes++; // another 7-bit ASCII character
- }
- } else if (ch < 0x800) {
- sizeInBytes += 2; // 11-bit character
- } else if (ch < 0xd800 || ch > 0xdfff) {
- sizeInBytes += 3; // 16-bit character
- } else {
- int low = i + 1 < len ? string.charAt(i + 1) : 0;
- if (ch > 0xdbff || low < 0xdc00 || low > 0xdfff) {
- sizeInBytes++; // A malformed surrogate, which yields '?'.
- } else {
- // A 21-bit character
- sizeInBytes += 4;
- i++;
- }
- }
- }
- return sizeInBytes;
- }
-
- /**
- * Binary search for character width which favors matching lower numbers.
- *
- * Adapted from okio.Buffer
- */
- public static int asciiSizeInBytes(long v) {
- if (v == 0) return 1;
- if (v == Long.MIN_VALUE) return 20;
-
- boolean negative = false;
- if (v < 0) {
- v = -v; // making this positive allows us to compare using less-than
- negative = true;
- }
- int width =
- v < 100000000L
- ? v < 10000L
- ? v < 100L ? v < 10L ? 1 : 2 : v < 1000L ? 3 : 4
- : v < 1000000L ? v < 100000L ? 5 : 6 : v < 10000000L ? 7 : 8
- : v < 1000000000000L
- ? v < 10000000000L ? v < 1000000000L ? 9 : 10 : v < 100000000000L ? 11 : 12
- : v < 1000000000000000L
- ? v < 10000000000000L ? 13 : v < 100000000000000L ? 14 : 15
- : v < 100000000000000000L
- ? v < 10000000000000000L ? 16 : 17
- : v < 1000000000000000000L ? 18 : 19;
- return negative ? width + 1 : width; // conditionally add room for negative sign
- }
-
- /**
- * A base 128 varint encodes 7 bits at a time, this checks how many bytes are needed to represent
- * the value.
- *
- * See https://developers.google.com/protocol-buffers/docs/encoding#varints
- *
- * This logic is the same as {@code com.squareup.wire.ProtoWriter.varint32Size} v2.3.0 which
- * benchmarked faster than loop variants of the frequently copy/pasted VarInt.varIntSize
- */
- public static int varintSizeInBytes(int value) {
- if ((value & (0xffffffff << 7)) == 0) return 1;
- if ((value & (0xffffffff << 14)) == 0) return 2;
- if ((value & (0xffffffff << 21)) == 0) return 3;
- if ((value & (0xffffffff << 28)) == 0) return 4;
- return 5;
- }
-
- /** Like {@link #varintSizeInBytes(int)}, except for uint64. */
- public static int varintSizeInBytes(long v) {
- if ((v & (0xffffffffffffffffL << 7)) == 0) return 1;
- if ((v & (0xffffffffffffffffL << 14)) == 0) return 2;
- if ((v & (0xffffffffffffffffL << 21)) == 0) return 3;
- if ((v & (0xffffffffffffffffL << 28)) == 0) return 4;
- if ((v & (0xffffffffffffffffL << 35)) == 0) return 5;
- if ((v & (0xffffffffffffffffL << 42)) == 0) return 6;
- if ((v & (0xffffffffffffffffL << 49)) == 0) return 7;
- if ((v & (0xffffffffffffffffL << 56)) == 0) return 8;
- if ((v & (0xffffffffffffffffL << 63)) == 0) return 9;
- return 10;
- }
-
static void writeHexByte(byte[] data, int pos, byte b) {
data[pos + 0] = (byte) HEX_DIGITS[(b >> 4) & 0xf];
data[pos + 1] = (byte) HEX_DIGITS[b & 0xf];
}
+ final int pos() {
+ return pos;
+ }
+
public void writeAscii(String v) {
for (int i = 0, length = v.length(); i < length; i++) {
writeByte(v.charAt(i) & 0xff);
@@ -322,7 +148,6 @@ public void writeUtf8(CharSequence string) {
// Adapted from okio.Buffer.writeDecimalLong
public void writeAscii(long v) {
if (v == 0) {
- require(1);
writeByte('0');
return;
}
@@ -369,86 +194,106 @@ void writeLongLe(long v) {
writeByte((byte) ((v >> 56) & 0xff));
}
- long readLongLe() {
- require(8);
- int pos = this.pos;
- this.pos = pos + 8;
- return (buf[pos] & 0xffL)
- | (buf[pos + 1] & 0xffL) << 8
- | (buf[pos + 2] & 0xffL) << 16
- | (buf[pos + 3] & 0xffL) << 24
- | (buf[pos + 4] & 0xffL) << 32
- | (buf[pos + 5] & 0xffL) << 40
- | (buf[pos + 6] & 0xffL) << 48
- | (buf[pos + 7] & 0xffL) << 56;
- }
-
- final byte readByte() {
- require(1);
- return buf[pos++];
- }
-
/**
- * @return the value read. Use {@link #varintSizeInBytes(long)} to tell how many bytes.
- * @throws IllegalArgumentException if more than 64 bits were encoded
+ * This returns the bytes needed to transcode a UTF-16 Java String to UTF-8 bytes.
+ *
+ * Originally based on
+ * http://stackoverflow.com/questions/8511490/calculating-length-in-utf-8-of-java-string-without-actually-encoding-it
+ *
+ * Later, ASCII run and malformed surrogate logic borrowed from okio.Utf8
*/
- // included in the main api as this is used commonly, for example reading proto tags
- int readVarint32() {
- byte b; // negative number implies MSB set
- if ((b = readByte()) >= 0) {
- return b;
- }
- int result = b & 0x7f;
-
- if ((b = readByte()) >= 0) {
- return result | b << 7;
- }
- result |= (b & 0x7f) << 7;
-
- if ((b = readByte()) >= 0) {
- return result | b << 14;
- }
- result |= (b & 0x7f) << 14;
-
- if ((b = readByte()) >= 0) {
- return result | b << 21;
- }
- result |= (b & 0x7f) << 21;
-
- b = readByte();
- if ((b & 0xf0) != 0) {
- throw new IllegalArgumentException("Greater than 32-bit varint at position " + (pos - 1));
+ // TODO: benchmark vs https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/Utf8.java#L240
+ // there seem to be less branches for for strings without surrogates
+ public static int utf8SizeInBytes(CharSequence string) {
+ int sizeInBytes = 0;
+ for (int i = 0, len = string.length(); i < len; i++) {
+ char ch = string.charAt(i);
+ if (ch < 0x80) {
+ sizeInBytes++; // 7-bit ASCII character
+ // This could be an ASCII run, or possibly entirely ASCII
+ while (i < len - 1) {
+ ch = string.charAt(i + 1);
+ if (ch >= 0x80) break;
+ i++;
+ sizeInBytes++; // another 7-bit ASCII character
+ }
+ } else if (ch < 0x800) {
+ sizeInBytes += 2; // 11-bit character
+ } else if (ch < 0xd800 || ch > 0xdfff) {
+ sizeInBytes += 3; // 16-bit character
+ } else {
+ int low = i + 1 < len ? string.charAt(i + 1) : 0;
+ if (ch > 0xdbff || low < 0xdc00 || low > 0xdfff) {
+ sizeInBytes++; // A malformed surrogate, which yields '?'.
+ } else {
+ // A 21-bit character
+ sizeInBytes += 4;
+ i++;
+ }
+ }
}
- return result | b << 28;
+ return sizeInBytes;
}
- long readVarint64() {
- byte b; // negative number implies MSB set
- if ((b = readByte()) >= 0) {
- return b;
- }
+ /**
+ * Binary search for character width which favors matching lower numbers.
+ *
+ * Adapted from okio.Buffer
+ */
+ public static int asciiSizeInBytes(long v) {
+ if (v == 0) return 1;
+ if (v == Long.MIN_VALUE) return 20;
- long result = b & 0x7f;
- for (int i = 1; b < 0 && i < 10; i++) {
- b = readByte();
- if (i == 9 && (b & 0xf0) != 0) {
- throw new IllegalArgumentException("Greater than 64-bit varint at position " + (pos - 1));
- }
- result |= (long) (b & 0x7f) << (i * 7);
+ boolean negative = false;
+ if (v < 0) {
+ v = -v; // making this positive allows us to compare using less-than
+ negative = true;
}
- return result;
+ int width =
+ v < 100000000L
+ ? v < 10000L
+ ? v < 100L ? v < 10L ? 1 : 2 : v < 1000L ? 3 : 4
+ : v < 1000000L ? v < 100000L ? 5 : 6 : v < 10000000L ? 7 : 8
+ : v < 1000000000000L
+ ? v < 10000000000L ? v < 1000000000L ? 9 : 10 : v < 100000000000L ? 11 : 12
+ : v < 1000000000000000L
+ ? v < 10000000000000L ? 13 : v < 100000000000000L ? 14 : 15
+ : v < 100000000000000000L
+ ? v < 10000000000000000L ? 16 : 17
+ : v < 1000000000000000000L ? 18 : 19;
+ return negative ? width + 1 : width; // conditionally add room for negative sign
}
- public interface Writer See https://developers.google.com/protocol-buffers/docs/encoding#varints
+ *
+ * This logic is the same as {@code com.squareup.wire.ProtoWriter.varint32Size} v2.3.0 which
+ * benchmarked faster than loop variants of the frequently copy/pasted VarInt.varIntSize
+ */
+ public static int varintSizeInBytes(int value) {
+ if ((value & (0xffffffff << 7)) == 0) return 1;
+ if ((value & (0xffffffff << 14)) == 0) return 2;
+ if ((value & (0xffffffff << 21)) == 0) return 3;
+ if ((value & (0xffffffff << 28)) == 0) return 4;
+ return 5;
}
- void require(int byteCount) {
- if (pos + byteCount > buf.length) {
- throw new IllegalArgumentException(
- "Truncated: length " + byteCount + " > bytes remaining " + remaining());
- }
+ /** Like {@link #varintSizeInBytes(int)}, except for uint64. */
+ // TODO: benchmark vs https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java#L770
+ // Since trace IDs are random, I guess they cover the entire spectrum of varint sizes and probably would especially benefit from this.
+ public static int varintSizeInBytes(long v) {
+ if ((v & (0xffffffffffffffffL << 7)) == 0) return 1;
+ if ((v & (0xffffffffffffffffL << 14)) == 0) return 2;
+ if ((v & (0xffffffffffffffffL << 21)) == 0) return 3;
+ if ((v & (0xffffffffffffffffL << 28)) == 0) return 4;
+ if ((v & (0xffffffffffffffffL << 35)) == 0) return 5;
+ if ((v & (0xffffffffffffffffL << 42)) == 0) return 6;
+ if ((v & (0xffffffffffffffffL << 49)) == 0) return 7;
+ if ((v & (0xffffffffffffffffL << 56)) == 0) return 8;
+ if ((v & (0xffffffffffffffffL << 63)) == 0) return 9;
+ return 10;
}
}
diff --git a/zipkin/src/test/java/zipkin2/codec/SpanBytesDecoderTest.java b/zipkin/src/test/java/zipkin2/codec/SpanBytesDecoderTest.java
index 679c3e6b641..6f2ef577955 100644
--- a/zipkin/src/test/java/zipkin2/codec/SpanBytesDecoderTest.java
+++ b/zipkin/src/test/java/zipkin2/codec/SpanBytesDecoderTest.java
@@ -43,7 +43,7 @@ public class SpanBytesDecoderTest {
@Test public void niceErrorOnTruncatedSpans_PROTO3() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Truncated: length 66 > bytes remaining 8 reading List from proto3");
+ thrown.expectMessage("Truncated: length 66 > bytes available 8 reading List from proto3");
byte[] encoded = SpanBytesEncoder.PROTO3.encodeList(TRACE);
SpanBytesDecoder.PROTO3.decodeList(Arrays.copyOfRange(encoded, 0, 10));
@@ -51,7 +51,7 @@ public class SpanBytesDecoderTest {
@Test public void niceErrorOnTruncatedSpan_PROTO3() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Truncated: length 179 > bytes remaining 7 reading Span from proto3");
+ thrown.expectMessage("Truncated: length 179 > bytes available 7 reading Span from proto3");
byte[] encoded = SpanBytesEncoder.PROTO3.encode(SPAN);
SpanBytesDecoder.PROTO3.decodeOne(Arrays.copyOfRange(encoded, 0, 10));
@@ -172,7 +172,7 @@ public class SpanBytesDecoderTest {
@Test public void niceErrorOnMalformed_inputSpans_PROTO3() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Truncated: length 101 > bytes remaining 3 reading List from proto3");
+ thrown.expectMessage("Truncated: length 101 > bytes available 3 reading List from proto3");
SpanBytesDecoder.PROTO3.decodeList(new byte[] {'h', 'e', 'l', 'l', 'o'});
}
diff --git a/zipkin/src/test/java/zipkin2/codec/V1SpanBytesDecoderTest.java b/zipkin/src/test/java/zipkin2/codec/V1SpanBytesDecoderTest.java
index 4d66efa0a97..d4af20d699d 100644
--- a/zipkin/src/test/java/zipkin2/codec/V1SpanBytesDecoderTest.java
+++ b/zipkin/src/test/java/zipkin2/codec/V1SpanBytesDecoderTest.java
@@ -44,7 +44,7 @@ public class V1SpanBytesDecoderTest {
@Test public void niceErrorOnTruncatedSpans_THRIFT() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Truncated: length 8 > bytes remaining 2 reading List from TBinary");
+ thrown.expectMessage("Truncated: length 8 > bytes available 2 reading List from TBinary");
byte[] encoded = SpanBytesEncoder.THRIFT.encodeList(TRACE);
SpanBytesDecoder.THRIFT.decodeList(Arrays.copyOfRange(encoded, 0, 10));
@@ -52,7 +52,7 @@ public class V1SpanBytesDecoderTest {
@Test public void niceErrorOnTruncatedSpan_THRIFT() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Truncated: length 8 > bytes remaining 7 reading Span from TBinary");
+ thrown.expectMessage("Truncated: length 8 > bytes available 7 reading Span from TBinary");
byte[] encoded = SpanBytesEncoder.THRIFT.encode(SPAN);
SpanBytesDecoder.THRIFT.decodeOne(Arrays.copyOfRange(encoded, 0, 10));
@@ -161,8 +161,7 @@ public void niceErrorOnMalformed_inputSpans_JSON_V1() {
@Test
public void niceErrorOnMalformed_inputSpans_THRIFT() {
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage(
- "Truncated: length 1701604463 > bytes remaining 0 reading List from TBinary");
+ thrown.expectMessage("Truncated: length 1 > bytes available 0 reading List from TBinary");
SpanBytesDecoder.THRIFT.decodeList(new byte[] {'h', 'e', 'l', 'l', 'o'});
}
diff --git a/zipkin/src/test/java/zipkin2/internal/DependenciesTest.java b/zipkin/src/test/java/zipkin2/internal/DependenciesTest.java
index bc6c60e9b04..7dd9c787696 100644
--- a/zipkin/src/test/java/zipkin2/internal/DependenciesTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/DependenciesTest.java
@@ -24,8 +24,7 @@
import static org.assertj.core.api.Assertions.assertThat;
public final class DependenciesTest {
- @Test
- public void dependenciesRoundTrip() {
+ @Test public void dependenciesRoundTrip() {
DependencyLink ab = DependencyLink.newBuilder().parent("a").child("b").callCount(2L).build();
DependencyLink cd = DependencyLink.newBuilder().parent("c").child("d").errorCount(2L).build();
@@ -33,7 +32,5 @@ public void dependenciesRoundTrip() {
ByteBuffer bytes = dependencies.toThrift();
assertThat(Dependencies.fromThrift(bytes)).isEqualTo(dependencies);
-
- assertThat(bytes.remaining()).isZero();
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/JsonCodecTest.java b/zipkin/src/test/java/zipkin2/internal/JsonCodecTest.java
index 5421518f041..e8fc3e987b3 100644
--- a/zipkin/src/test/java/zipkin2/internal/JsonCodecTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/JsonCodecTest.java
@@ -33,12 +33,12 @@ public class JsonCodecTest {
thrown.expect(AssertionError.class);
thrown.expectMessage("Bug found using FooWriter to write Foo as json. Wrote 1/2 bytes: a");
- class FooWriter implements UnsafeBuffer.Writer {
+ class FooWriter implements WriteBuffer.Writer {
@Override public int sizeInBytes(Object value) {
return 2;
}
- @Override public void write(Object value, UnsafeBuffer buffer) {
+ @Override public void write(Object value, WriteBuffer buffer) {
buffer.writeByte('a');
throw new RuntimeException("buggy");
}
@@ -58,12 +58,12 @@ class Foo {
thrown.expectMessage("Bug found using FooWriter to write Foo as json. Wrote 2/2 bytes: ab");
// pretend there was a bug calculating size, ex it calculated incorrectly as to small
- class FooWriter implements UnsafeBuffer.Writer {
+ class FooWriter implements WriteBuffer.Writer {
@Override public int sizeInBytes(Object value) {
return 2;
}
- @Override public void write(Object value, UnsafeBuffer buffer) {
+ @Override public void write(Object value, WriteBuffer buffer) {
buffer.writeByte('a');
buffer.writeByte('b');
buffer.writeByte('c'); // wrote larger than size!
@@ -84,7 +84,7 @@ class Foo {
Exception error = null;
byte[] bytes = "[\"='".getBytes(UTF_8);
try {
- new JsonCodec.JsonReader(bytes).beginObject();
+ new JsonCodec.JsonReader(ReadBuffer.wrap(bytes)).beginObject();
failBecauseExceptionWasNotThrown(IllegalStateException.class);
} catch (IOException | IllegalStateException e) {
error = e;
diff --git a/zipkin/src/test/java/zipkin2/internal/Proto3FieldsTest.java b/zipkin/src/test/java/zipkin2/internal/Proto3FieldsTest.java
index 2893dc5ca10..028eda5a27a 100644
--- a/zipkin/src/test/java/zipkin2/internal/Proto3FieldsTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/Proto3FieldsTest.java
@@ -35,7 +35,8 @@
import static zipkin2.internal.Proto3Fields.WIRETYPE_VARINT;
public class Proto3FieldsTest {
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeOf
+ byte[] bytes = new byte[2048]; // bigger than needed to test sizeInBytes
+ WriteBuffer buf = WriteBuffer.wrap(bytes);
/** Shows we can reliably look at a byte zero to tell if we are decoding proto3 repeated fields. */
@Test public void field_key_fieldOneLengthDelimited() {
@@ -141,24 +142,24 @@ public class Proto3FieldsTest {
VarintField field = new VarintField(128 << 3 | WIRETYPE_VARINT);
field.write(buf, 0xffffffffffffffffL);
- buf.skip(1); // skip the key
- skipValue(WIRETYPE_VARINT);
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ skipValue(readBuffer, WIRETYPE_VARINT);
}
@Test public void field_skipValue_LENGTH_DELIMITED() {
Utf8Field field = new Utf8Field(128 << 3 | WIRETYPE_LENGTH_DELIMITED);
field.write(buf, "订单维护服务");
- buf.skip(1); // skip the key
- skipValue(WIRETYPE_LENGTH_DELIMITED);
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ skipValue(readBuffer, WIRETYPE_LENGTH_DELIMITED);
}
@Test public void field_skipValue_FIXED64() {
Fixed64Field field = new Fixed64Field(128 << 3 | WIRETYPE_FIXED64);
field.write(buf, 0xffffffffffffffffL);
- buf.skip(1); // skip the key
- skipValue(WIRETYPE_FIXED64);
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ skipValue(readBuffer, WIRETYPE_FIXED64);
}
@Test public void field_skipValue_FIXED32() {
@@ -169,31 +170,29 @@ public class Proto3FieldsTest {
buf.writeByte(0xff);
buf.writeByte(0xff);
- buf.skip(1); // skip the key
- skipValue(WIRETYPE_FIXED32);
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ skipValue(readBuffer, WIRETYPE_FIXED32);
}
@Test public void field_readLengthPrefix_LENGTH_DELIMITED() {
BytesField field = new BytesField(128 << 3 | WIRETYPE_LENGTH_DELIMITED);
field.write(buf, new byte[10]);
- buf.reset();
- buf.skip(1); // skip the key
- assertThat(buf.readVarint32())
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ assertThat(readBuffer.readVarint32())
.isEqualTo(10);
}
@Test public void field_readLengthPrefixAndValue_LENGTH_DELIMITED_truncated() {
BytesField field = new BytesField(128 << 3 | WIRETYPE_LENGTH_DELIMITED);
- buf = UnsafeBuffer.allocate(10);
- buf.writeVarint(100); // much larger than the buffer size
- buf.reset();
+ bytes = new byte[10];
+ WriteBuffer.wrap(bytes).writeVarint(100); // much larger than the buffer size
try {
- field.readLengthPrefixAndValue(buf);
+ field.readLengthPrefixAndValue(ReadBuffer.wrap(bytes));
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Truncated: length 100 > bytes remaining 9");
+ assertThat(e).hasMessage("Truncated: length 100 > bytes available 9");
}
}
@@ -201,14 +200,13 @@ public class Proto3FieldsTest {
Fixed64Field field = new Fixed64Field(128 << 3 | WIRETYPE_FIXED64);
field.write(buf, 0xffffffffffffffffL);
- buf.reset();
- buf.skip(1); // skip the key
- assertThat(field.readValue(buf))
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes, 1 /* skip the key */, bytes.length);
+ assertThat(field.readValue(readBuffer))
.isEqualTo(0xffffffffffffffffL);
}
- void skipValue(int wireType) {
- assertThat(Field.skipValue(buf, wireType))
+ void skipValue(ReadBuffer buffer, int wireType) {
+ assertThat(Field.skipValue(buffer, wireType))
.isTrue();
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/Proto3SpanWriterTest.java b/zipkin/src/test/java/zipkin2/internal/Proto3SpanWriterTest.java
index 03c31de981f..2925951a38d 100644
--- a/zipkin/src/test/java/zipkin2/internal/Proto3SpanWriterTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/Proto3SpanWriterTest.java
@@ -24,31 +24,29 @@
import static zipkin2.internal.Proto3ZipkinFields.SPAN;
public class Proto3SpanWriterTest {
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeOf
-
Proto3SpanWriter writer = new Proto3SpanWriter();
/** proto messages always need a key, so the non-list form is just a single-field */
@Test public void write_startsWithSpanKeyAndLengthPrefix() {
- byte[] buff = writer.write(CLIENT_SPAN);
+ byte[] bytes = writer.write(CLIENT_SPAN);
- assertThat(buff)
+ assertThat(bytes)
.hasSize(writer.sizeInBytes(CLIENT_SPAN))
.startsWith((byte) 10, SPAN.sizeOfValue(CLIENT_SPAN));
}
@Test public void writeList_startsWithSpanKeyAndLengthPrefix() {
- byte[] buff = writer.writeList(asList(CLIENT_SPAN));
+ byte[] bytes = writer.writeList(asList(CLIENT_SPAN));
- assertThat(buff)
+ assertThat(bytes)
.hasSize(writer.sizeInBytes(CLIENT_SPAN))
.startsWith((byte) 10, SPAN.sizeOfValue(CLIENT_SPAN));
}
@Test public void writeList_multiple() {
- byte[] buff = writer.writeList(asList(CLIENT_SPAN, CLIENT_SPAN));
+ byte[] bytes = writer.writeList(asList(CLIENT_SPAN, CLIENT_SPAN));
- assertThat(buff)
+ assertThat(bytes)
.hasSize(writer.sizeInBytes(CLIENT_SPAN) * 2)
.startsWith((byte) 10, SPAN.sizeOfValue(CLIENT_SPAN));
}
@@ -59,9 +57,10 @@ public class Proto3SpanWriterTest {
}
@Test public void writeList_offset_startsWithSpanKeyAndLengthPrefix() {
- writer.writeList(asList(CLIENT_SPAN, CLIENT_SPAN), buf.unwrap(), 0);
+ byte[] bytes = new byte[2048];
+ writer.writeList(asList(CLIENT_SPAN, CLIENT_SPAN), bytes, 0);
- assertThat(buf.unwrap())
+ assertThat(bytes)
.startsWith((byte) 10, SPAN.sizeOfValue(CLIENT_SPAN));
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/Proto3ZipkinFieldsTest.java b/zipkin/src/test/java/zipkin2/internal/Proto3ZipkinFieldsTest.java
index ad3d139ba9a..834c0d79c92 100644
--- a/zipkin/src/test/java/zipkin2/internal/Proto3ZipkinFieldsTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/Proto3ZipkinFieldsTest.java
@@ -35,7 +35,8 @@
import static zipkin2.internal.Proto3ZipkinFields.SPAN;
public class Proto3ZipkinFieldsTest {
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeInBytes
+ byte[] bytes = new byte[2048]; // bigger than needed to test sizeInBytes
+ WriteBuffer buf = WriteBuffer.wrap(bytes);
/** A map entry is an embedded messages: one for field the key and one for the value */
@Test public void tag_sizeInBytes() {
@@ -79,14 +80,14 @@ public class Proto3ZipkinFieldsTest {
@Test public void span_write_startsWithFieldInListOfSpans() {
SPAN.write(buf, spanBuilder().build());
- assertThat(buf.unwrap()).startsWith(
+ assertThat(bytes).startsWith(
0b00001010 /* span key */, 20 /* bytes for length of the span */
);
}
@Test public void span_write_writesIds() {
SPAN.write(buf, spanBuilder().build());
- assertThat(buf.unwrap()).startsWith(
+ assertThat(bytes).startsWith(
0b00001010 /* span key */, 20 /* bytes for length of the span */,
0b00001010 /* trace ID key */, 8 /* bytes for 64-bit trace ID */,
0, 0, 0, 0, 0, 0, 0, 1, // hex trace ID
@@ -154,7 +155,7 @@ public class Proto3ZipkinFieldsTest {
@Test public void span_write_kind() {
SPAN.write(buf, spanBuilder().kind(Span.Kind.PRODUCER).build());
- assertThat(buf.unwrap())
+ assertThat(bytes)
.contains(0b0100000, atIndex(22)) // (field_number << 3) | wire_type = 4 << 3 | 0
.contains(0b0000011, atIndex(23)); // producer's index is 3
}
@@ -162,21 +163,19 @@ public class Proto3ZipkinFieldsTest {
@Test public void span_read_kind_tolerant() {
assertRoundTrip(spanBuilder().kind(Span.Kind.CONSUMER).build());
- buf.reset();
- buf.unwrap()[23] = (byte) (Span.Kind.values().length + 1); // undefined kind
- assertThat(SPAN.read(buf))
+ bytes[23] = (byte) (Span.Kind.values().length + 1); // undefined kind
+ assertThat(SPAN.read(ReadBuffer.wrap(bytes)))
.isEqualTo(spanBuilder().build()); // skips undefined kind instead of dying
- buf.reset();
- buf.unwrap()[23] = 0; // serialized zero
- assertThat(SPAN.read(buf))
+ bytes[23] = 0; // serialized zero
+ assertThat(SPAN.read(ReadBuffer.wrap(bytes)))
.isEqualTo(spanBuilder().build());
}
@Test public void span_write_debug() {
SPAN.write(buf, CLIENT_SPAN.toBuilder().debug(true).build());
- assertThat(buf.unwrap())
+ assertThat(bytes)
.contains(0b01100000, atIndex(buf.pos() - 2)) // (field_number << 3) | wire_type = 12 << 3 | 0
.contains(1, atIndex(buf.pos() - 1)); // true
}
@@ -184,7 +183,7 @@ public class Proto3ZipkinFieldsTest {
@Test public void span_write_shared() {
SPAN.write(buf, CLIENT_SPAN.toBuilder().kind(Span.Kind.SERVER).shared(true).build());
- assertThat(buf.unwrap())
+ assertThat(bytes)
.contains(0b01101000, atIndex(buf.pos() - 2)) // (field_number << 3) | wire_type = 13 << 3 | 0
.contains(1, atIndex(buf.pos() - 1)); // true
}
@@ -195,9 +194,8 @@ static Span.Builder spanBuilder() {
void assertRoundTrip(Span span) {
SPAN.write(buf, span);
- buf.reset();
- assertThat(SPAN.read(buf))
+ assertThat(SPAN.read(ReadBuffer.wrap(bytes)))
.isEqualTo(span);
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/ReadBufferTest.java b/zipkin/src/test/java/zipkin2/internal/ReadBufferTest.java
new file mode 100644
index 00000000000..3b0b77d80ba
--- /dev/null
+++ b/zipkin/src/test/java/zipkin2/internal/ReadBufferTest.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 zipkin2.internal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
+import static zipkin2.TestObjects.UTF_8;
+
+public class ReadBufferTest {
+ @Test public void byteBuffer_limited() {
+ ByteBuffer buf = ByteBuffer.wrap("glove".getBytes(UTF_8));
+ buf.get();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buf.slice());
+ assertThat(readBuffer.readUtf8(readBuffer.available()))
+ .isEqualTo("love");
+ }
+
+ @Test public void readVarint32() {
+ assertReadVarint32(0);
+ assertReadVarint32(0b0011_1111_1111_1111);
+ assertReadVarint32(0xFFFFFFFF);
+ }
+
+ static void assertReadVarint32(int value) {
+ byte[] bytes = new byte[WriteBuffer.varintSizeInBytes(value)];
+ WriteBuffer.wrap(bytes).writeVarint(value);
+
+ assertThat(ReadBuffer.wrap(bytes).readVarint32())
+ .isEqualTo(value);
+ }
+
+ @Test public void readShort_bytes() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02};
+
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes);
+
+ assertThat(readBuffer.readShort()).isEqualTo((short) 0x0102);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readShort_byteBuff() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02};
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readShort()).isEqualTo((short) 0x0102);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readShort_byteBuff_littleEndian() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02};
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readShort()).isEqualTo((short) 0x0102);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readInt_bytes() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04};
+
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes);
+
+ assertThat(readBuffer.readInt()).isEqualTo(0x01020304);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readInt_byteBuff() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04};
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readInt()).isEqualTo(0x01020304);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readInt_byteBuff_littleEndian() {
+ byte[] bytes = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04};
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readInt()).isEqualTo(0x01020304);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLong_bytes() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes);
+
+ assertThat(readBuffer.readLong())
+ .isEqualTo(0x0102030405060708L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLong_byteBuff() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readLong())
+ .isEqualTo(0x0102030405060708L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLong_byteBuff_littleEndian() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readLong())
+ .isEqualTo(0x0102030405060708L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLongLe_bytes() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ReadBuffer readBuffer = ReadBuffer.wrap(bytes);
+
+ assertThat(readBuffer.readLongLe())
+ .isEqualTo(0x0807060504030201L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLongLe_byteBuff() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readLongLe())
+ .isEqualTo(0x0807060504030201L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readLongLe_byteBuff_littleEndian() {
+ byte[] bytes = {
+ (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
+ };
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asReadOnlyBuffer();
+ ReadBuffer readBuffer = ReadBuffer.wrapUnsafe(buffer);
+ assertThat(readBuffer).isInstanceOf(ReadBuffer.Buff.class);
+
+ assertThat(readBuffer.readLongLe())
+ .isEqualTo(0x0807060504030201L);
+ assertThat(readBuffer.available()).isZero();
+ }
+
+ @Test public void readVarint32_malformedTooBig() {
+ byte[] bytes = new byte[8];
+ WriteBuffer.wrap(bytes).writeLongLe(0xffffffffffffL);
+
+ try {
+ ReadBuffer.wrap(bytes).readVarint32();
+ failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+ } catch (IllegalArgumentException e) {
+ assertThat(e)
+ .hasMessage("Greater than 32-bit varint at position 4");
+ }
+ }
+
+ @Test public void readVarint64() {
+ assertReadVarint64(0L);
+ assertReadVarint64(0b0011_1111_1111_1111L);
+ assertReadVarint64(0xffffffffffffffffL);
+ }
+
+ static void assertReadVarint64(long value) {
+ byte[] bytes = new byte[WriteBuffer.varintSizeInBytes(value)];
+ WriteBuffer.wrap(bytes).writeVarint(value);
+
+ assertThat(ReadBuffer.wrap(bytes).readVarint64())
+ .isEqualTo(value);
+ }
+
+ @Test public void readVarint64_malformedTooBig() {
+ byte[] bytes = new byte[16];
+ WriteBuffer buffer = WriteBuffer.wrap(bytes);
+ buffer.writeLongLe(0xffffffffffffffffL);
+ buffer.writeLongLe(0xffffffffffffffffL);
+
+ try {
+ ReadBuffer.wrap(bytes).readVarint64();
+ failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+ } catch (IllegalArgumentException e) {
+ assertThat(e)
+ .hasMessage("Greater than 64-bit varint at position 9");
+ }
+ }
+}
diff --git a/zipkin/src/test/java/zipkin2/internal/V1JsonSpanWriterTest.java b/zipkin/src/test/java/zipkin2/internal/V1JsonSpanWriterTest.java
index 7f6ae0abc21..f95dfae2729 100644
--- a/zipkin/src/test/java/zipkin2/internal/V1JsonSpanWriterTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/V1JsonSpanWriterTest.java
@@ -16,18 +16,18 @@
*/
package zipkin2.internal;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import org.junit.Test;
import zipkin2.Endpoint;
import zipkin2.Span;
import static org.assertj.core.api.Assertions.assertThat;
import static zipkin2.TestObjects.CLIENT_SPAN;
+import static zipkin2.internal.JsonCodec.UTF_8;
public class V1JsonSpanWriterTest {
V1JsonSpanWriter writer = new V1JsonSpanWriter();
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeOf
+ byte[] bytes = new byte[2048]; // bigger than needed to test sizeInBytes
+ WriteBuffer buf = WriteBuffer.wrap(bytes);
@Test
public void sizeInBytes() {
@@ -37,153 +37,149 @@ public void sizeInBytes() {
}
@Test
- public void writesCoreAnnotations_client() throws IOException {
+ public void writesCoreAnnotations_client() {
writer.write(CLIENT_SPAN, buf);
writesCoreAnnotations("cs", "cr");
}
@Test
- public void writesCoreAnnotations_server() throws IOException {
+ public void writesCoreAnnotations_server() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.SERVER).build(), buf);
writesCoreAnnotations("sr", "ss");
}
@Test
- public void writesCoreAnnotations_producer() throws IOException {
+ public void writesCoreAnnotations_producer() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.PRODUCER).build(), buf);
writesCoreAnnotations("ms", "ws");
}
@Test
- public void writesCoreAnnotations_consumer() throws IOException {
+ public void writesCoreAnnotations_consumer() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.CONSUMER).build(), buf);
writesCoreAnnotations("wr", "mr");
}
- void writesCoreAnnotations(String begin, String end) throws UnsupportedEncodingException {
- String json = new String(buf.unwrap(), "UTF-8");
+ void writesCoreAnnotations(String begin, String end) {
+ String json = new String(bytes, UTF_8);
assertThat(json)
.contains("{\"timestamp\":" + CLIENT_SPAN.timestamp() + ",\"value\":\"" + begin + "\"");
assertThat(json)
- .contains(
- "{\"timestamp\":"
- + (CLIENT_SPAN.timestamp() + CLIENT_SPAN.duration())
- + ",\"value\":\""
- + end
- + "\"");
+ .contains("{\"timestamp\":"
+ + (CLIENT_SPAN.timestampAsLong() + CLIENT_SPAN.durationAsLong())
+ + ",\"value\":\"" + end + "\"");
}
@Test
- public void writesCoreSendAnnotations_client() throws IOException {
+ public void writesCoreSendAnnotations_client() {
writer.write(CLIENT_SPAN.toBuilder().duration(null).build(), buf);
writesCoreSendAnnotations("cs");
}
@Test
- public void writesCoreSendAnnotations_server() throws IOException {
+ public void writesCoreSendAnnotations_server() {
writer.write(CLIENT_SPAN.toBuilder().duration(null).kind(Span.Kind.SERVER).build(), buf);
writesCoreSendAnnotations("sr");
}
@Test
- public void writesCoreSendAnnotations_producer() throws IOException {
+ public void writesCoreSendAnnotations_producer() {
writer.write(CLIENT_SPAN.toBuilder().duration(null).kind(Span.Kind.PRODUCER).build(), buf);
writesCoreSendAnnotations("ms");
}
@Test
- public void writesCoreSendAnnotations_consumer() throws IOException {
+ public void writesCoreSendAnnotations_consumer() {
writer.write(CLIENT_SPAN.toBuilder().duration(null).kind(Span.Kind.CONSUMER).build(), buf);
writesCoreSendAnnotations("mr");
}
- void writesCoreSendAnnotations(String begin) throws UnsupportedEncodingException {
- String json = new String(buf.unwrap(), "UTF-8");
+ void writesCoreSendAnnotations(String begin) {
+ String json = new String(bytes, UTF_8);
assertThat(json)
.contains("{\"timestamp\":" + CLIENT_SPAN.timestamp() + ",\"value\":\"" + begin + "\"");
}
@Test
- public void writesAddressBinaryAnnotation_client() throws IOException {
+ public void writesAddressBinaryAnnotation_client() {
writer.write(CLIENT_SPAN.toBuilder().build(), buf);
writesAddressBinaryAnnotation("sa");
}
@Test
- public void writesAddressBinaryAnnotation_server() throws IOException {
+ public void writesAddressBinaryAnnotation_server() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.SERVER).build(), buf);
writesAddressBinaryAnnotation("ca");
}
@Test
- public void writesAddressBinaryAnnotation_producer() throws IOException {
+ public void writesAddressBinaryAnnotation_producer() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.PRODUCER).build(), buf);
writesAddressBinaryAnnotation("ma");
}
@Test
- public void writesAddressBinaryAnnotation_consumer() throws IOException {
+ public void writesAddressBinaryAnnotation_consumer() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.CONSUMER).build(), buf);
writesAddressBinaryAnnotation("ma");
}
- void writesAddressBinaryAnnotation(String address) throws UnsupportedEncodingException {
- String json = new String(buf.unwrap(), "UTF-8");
-
- assertThat(json).contains("{\"key\":\"" + address + "\",\"value\":true,\"endpoint\":");
+ void writesAddressBinaryAnnotation(String address) {
+ assertThat(new String(bytes, UTF_8))
+ .contains("{\"key\":\"" + address + "\",\"value\":true,\"endpoint\":");
}
@Test
- public void writes128BitTraceId() throws UnsupportedEncodingException {
+ public void writes128BitTraceId() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.startsWith("{\"traceId\":\"" + CLIENT_SPAN.traceId() + "\"");
}
@Test
- public void annotationsHaveEndpoints() throws IOException {
+ public void annotationsHaveEndpoints() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains(
"\"value\":\"foo\",\"endpoint\":{\"serviceName\":\"frontend\",\"ipv4\":\"127.0.0.1\"}");
}
@Test
- public void writesTimestampAndDuration() throws IOException {
+ public void writesTimestampAndDuration() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains(
"\"timestamp\":" + CLIENT_SPAN.timestamp() + ",\"duration\":" + CLIENT_SPAN.duration());
}
@Test
- public void skipsTimestampAndDuration_shared() throws IOException {
+ public void skipsTimestampAndDuration_shared() {
writer.write(CLIENT_SPAN.toBuilder().kind(Span.Kind.SERVER).shared(true).build(), buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.doesNotContain(
"\"timestamp\":" + CLIENT_SPAN.timestamp() + ",\"duration\":" + CLIENT_SPAN.duration());
}
@Test
- public void writesEmptySpanName() throws IOException {
+ public void writesEmptySpanName() {
Span span =
Span.newBuilder()
.traceId("7180c278b62e8f6a216a2aea45d08fc9")
@@ -193,11 +189,11 @@ public void writesEmptySpanName() throws IOException {
writer.write(span, buf);
- assertThat(new String(buf.unwrap(), "UTF-8")).contains("\"name\":\"\"");
+ assertThat(new String(bytes, UTF_8)).contains("\"name\":\"\"");
}
@Test
- public void writesEmptyServiceName() throws IOException {
+ public void writesEmptyServiceName() {
Span span =
CLIENT_SPAN
.toBuilder()
@@ -206,15 +202,15 @@ public void writesEmptyServiceName() throws IOException {
writer.write(span, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains("\"value\":\"foo\",\"endpoint\":{\"serviceName\":\"\",\"ipv4\":\"127.0.0.1\"}");
}
@Test
- public void tagsAreBinaryAnnotations() throws IOException {
+ public void tagsAreBinaryAnnotations() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains(
"\"binaryAnnotations\":["
+ "{\"key\":\"clnt/finagle.version\",\"value\":\"6.45.0\",\"endpoint\":{\"serviceName\":\"frontend\",\"ipv4\":\"127.0.0.1\"}},"
diff --git a/zipkin/src/test/java/zipkin2/internal/V1ThriftSpanWriterTest.java b/zipkin/src/test/java/zipkin2/internal/V1ThriftSpanWriterTest.java
index ee32150f45a..fba72174b05 100644
--- a/zipkin/src/test/java/zipkin2/internal/V1ThriftSpanWriterTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/V1ThriftSpanWriterTest.java
@@ -16,7 +16,6 @@
*/
package zipkin2.internal;
-import java.nio.ByteBuffer;
import org.junit.Before;
import org.junit.Test;
import zipkin2.Endpoint;
@@ -38,32 +37,28 @@
public class V1ThriftSpanWriterTest {
Span span = Span.newBuilder().traceId("1").id("2").build();
Endpoint endpoint = Endpoint.newBuilder().serviceName("frontend").ip("1.2.3.4").build();
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeOf
+ byte[] bytes = new byte[2048]; // bigger than needed to test sizeOf
+ WriteBuffer buf = WriteBuffer.wrap(bytes);
V1ThriftSpanWriter writer = new V1ThriftSpanWriter();
- byte[] endpointBytes;
+ byte[] endpointBytes = new byte[ThriftEndpointCodec.sizeInBytes(endpoint)];
- @Before
- public void init() {
- UnsafeBuffer endpointBuffer = UnsafeBuffer.allocate(ThriftEndpointCodec.sizeInBytes(endpoint));
- ThriftEndpointCodec.write(endpoint, endpointBuffer);
- endpointBytes = endpointBuffer.unwrap();
+ @Before public void init() {
+ ThriftEndpointCodec.write(endpoint, WriteBuffer.wrap(endpointBytes, 0));
}
-
@Test
public void endpoint_highPort() {
int highPort = 63840;
Endpoint endpoint = Endpoint.newBuilder().ip("127.0.0.1").port(63840).build();
- UnsafeBuffer endpointBuffer = UnsafeBuffer.allocate(ThriftEndpointCodec.sizeInBytes(endpoint));
- ThriftEndpointCodec.write(endpoint, endpointBuffer);
- byte[] buff = endpointBuffer.unwrap();
+ byte[] buff = new byte[ThriftEndpointCodec.sizeInBytes(endpoint)];
+ ThriftEndpointCodec.write(endpoint, WriteBuffer.wrap(buff, 0));
assertThat(buff)
.containsSequence(TYPE_I32, 0, 1, 127, 0, 0, 1) // ipv4
.containsSequence(TYPE_I16, 0, 2, (highPort >> 8) & 0xFF, highPort & 0xFF); // port
- assertThat(ThriftEndpointCodec.read(ByteBuffer.wrap(buff)).portAsInt())
+ assertThat(ThriftEndpointCodec.read(ReadBuffer.wrap(buff)).portAsInt())
.isEqualTo(highPort);
}
@@ -72,8 +67,8 @@ public void write_startsWithI64Prefix() {
byte[] buff = writer.write(span);
assertThat(buff)
- .hasSize(writer.sizeInBytes(span))
- .startsWith(TYPE_I64, 0, 1); // short value of field number 1
+ .hasSize(writer.sizeInBytes(span))
+ .startsWith(TYPE_I64, 0, 1); // short value of field number 1
}
@Test
@@ -81,9 +76,9 @@ public void writeList_startsWithListPrefix() {
byte[] buff = writer.writeList(asList(span));
assertThat(buff)
- .hasSize(5 + writer.sizeInBytes(span))
- .startsWith( // member type of the list and an integer with the count
- TYPE_STRUCT, 0, 0, 0, 1);
+ .hasSize(5 + writer.sizeInBytes(span))
+ .startsWith( // member type of the list and an integer with the count
+ TYPE_STRUCT, 0, 0, 0, 1);
}
@Test
@@ -91,9 +86,9 @@ public void writeList_startsWithListPrefix_multiple() {
byte[] buff = writer.writeList(asList(span, span));
assertThat(buff)
- .hasSize(5 + writer.sizeInBytes(span) * 2)
- .startsWith( // member type of the list and an integer with the count
- TYPE_STRUCT, 0, 0, 0, 2);
+ .hasSize(5 + writer.sizeInBytes(span) * 2)
+ .startsWith( // member type of the list and an integer with the count
+ TYPE_STRUCT, 0, 0, 0, 2);
}
@Test
@@ -103,21 +98,21 @@ public void writeList_empty() {
@Test
public void writeList_offset_startsWithListPrefix() {
- writer.writeList(asList(span, span), buf.unwrap(), 1);
+ writer.writeList(asList(span, span), bytes, 1);
- assertThat(buf.unwrap())
- .startsWith( // member type of the list and an integer with the count
- 0, TYPE_STRUCT, 0, 0, 0, 2);
+ assertThat(bytes)
+ .startsWith( // member type of the list and an integer with the count
+ 0, TYPE_STRUCT, 0, 0, 0, 2);
}
@Test
public void doesntWriteAnnotationsWhenMissingTimestamp() {
writer.write(span.toBuilder().kind(CLIENT).build(), buf);
- UnsafeBuffer buf2 = UnsafeBuffer.allocate(2048);
- writer.write(span, buf2);
+ byte[] bytes2 = new byte[2048];
+ writer.write(span, WriteBuffer.wrap(bytes2));
- assertThat(buf.unwrap()).containsExactly(buf.unwrap());
+ assertThat(bytes).containsExactly(bytes2);
}
@Test
@@ -144,12 +139,12 @@ void writesCoreAnnotationsNoEndpoint(Span.Kind kind, String begin, String end) {
span = span.toBuilder().kind(kind).timestamp(5).duration(10).build();
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 2) // two annotations
- .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, begin.charAt(0), begin.charAt(1))
- .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15) // timestamp
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, end.charAt(0), end.charAt(1));
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 2) // two annotations
+ .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, begin.charAt(0), begin.charAt(1))
+ .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15) // timestamp
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, end.charAt(0), end.charAt(1));
}
@Test
@@ -176,10 +171,10 @@ void writesBeginAnnotationNoEndpoint(Span.Kind kind, String begin) {
span = span.toBuilder().kind(kind).timestamp(5).build();
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 1) // one annotation
- .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, begin.charAt(0), begin.charAt(1));
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 1) // one annotation
+ .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 2, begin.charAt(0), begin.charAt(1));
}
@Test
@@ -205,42 +200,32 @@ public void writesAddressBinaryAnnotation_consumer() {
void writesAddressBinaryAnnotation(Span.Kind kind, String addr) {
writer.write(span.toBuilder().kind(kind).remoteEndpoint(endpoint).build(), buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
- .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 2, addr.charAt(0), addr.charAt(1)) // key
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 1, 1) // value
- .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 0) // type 0 == boolean
- .containsSequence(endpointBytes);
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
+ .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 2, addr.charAt(0), addr.charAt(1)) // key
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 1, 1) // value
+ .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 0) // type 0 == boolean
+ .containsSequence(endpointBytes);
}
@Test
public void annotationsHaveEndpoints() {
writer.write(span.toBuilder().localEndpoint(endpoint).addAnnotation(5, "foo").build(), buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 1) // one annotation
- .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 3, 'f', 'o', 'o') // value
- .containsSequence(endpointBytes);
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 1) // one annotation
+ .containsSequence(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 3, 'f', 'o', 'o') // value
+ .containsSequence(endpointBytes);
}
@Test
public void writesTimestampAndDuration() {
writer.write(span.toBuilder().timestamp(5).duration(10).build(), buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_I64, 0, 10, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
- .containsSequence(TYPE_I64, 0, 11, 0, 0, 0, 0, 0, 0, 0, 10); // duration
- }
-
- @Test
- public void skipsTimestampAndDuration_shared() {
- writer.write(span.toBuilder().kind(SERVER).timestamp(5).duration(10).shared(true).build(), buf);
-
- UnsafeBuffer buf2 = UnsafeBuffer.allocate(2048);
- writer.write(span.toBuilder().kind(SERVER).build(), buf2);
-
- assertThat(buf.unwrap()).containsExactly(buf.unwrap());
+ assertThat(bytes)
+ .containsSequence(TYPE_I64, 0, 10, 0, 0, 0, 0, 0, 0, 0, 5) // timestamp
+ .containsSequence(TYPE_I64, 0, 11, 0, 0, 0, 0, 0, 0, 0, 10); // duration
}
@Test
@@ -249,30 +234,30 @@ public void writesEmptySpanName() {
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(
- ThriftField.TYPE_STRING, 0, 3, 0, 0, 0, 0); // name (empty is 32 zero bits)
+ assertThat(bytes)
+ .containsSequence(
+ ThriftField.TYPE_STRING, 0, 3, 0, 0, 0, 0); // name (empty is 32 zero bits)
}
@Test
public void writesTraceAndSpanIds() {
writer.write(span, buf);
- assertThat(buf.unwrap())
- .startsWith(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1) // trace ID
- .containsSequence(TYPE_I64, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2); // ID
+ assertThat(bytes)
+ .startsWith(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1) // trace ID
+ .containsSequence(TYPE_I64, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2); // ID
}
@Test
public void writesParentAnd128BitTraceId() {
writer.write(
- Span.newBuilder().traceId("00000000000000010000000000000002").parentId("3").id("4").build(),
- buf);
+ Span.newBuilder().traceId("00000000000000010000000000000002").parentId("3").id("4").build(),
+ buf);
- assertThat(buf.unwrap())
- .startsWith(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2) // trace ID
- .containsSequence(TYPE_I64, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1) // trace ID high
- .containsSequence(TYPE_I64, 0, 5, 0, 0, 0, 0, 0, 0, 0, 3); // parent ID
+ assertThat(bytes)
+ .startsWith(TYPE_I64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2) // trace ID
+ .containsSequence(TYPE_I64, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1) // trace ID high
+ .containsSequence(TYPE_I64, 0, 5, 0, 0, 0, 0, 0, 0, 0, 3); // parent ID
}
/** For finagle compatibility */
@@ -282,9 +267,9 @@ public void writesEmptyAnnotationAndBinaryAnnotations() {
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 0) // empty annotations
- .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 0); // empty binary annotations
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 6, TYPE_STRUCT, 0, 0, 0, 0) // empty annotations
+ .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 0); // empty binary annotations
}
@Test
@@ -293,27 +278,27 @@ public void writesEmptyLocalComponentWhenNoAnnotationsOrTags() {
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
- .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 2, 'l', 'c') // key
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 0) // empty value
- .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 6) // type 6 == string
- .containsSequence(endpointBytes);
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
+ .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 2, 'l', 'c') // key
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 0) // empty value
+ .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 6) // type 6 == string
+ .containsSequence(endpointBytes);
}
@Test
public void writesEmptyServiceName() {
span =
- span.toBuilder()
- .name("foo")
- .localEndpoint(Endpoint.newBuilder().ip("127.0.0.1").build())
- .build();
+ span.toBuilder()
+ .name("foo")
+ .localEndpoint(Endpoint.newBuilder().ip("127.0.0.1").build())
+ .build();
writer.write(span, buf);
- assertThat(buf.unwrap())
- .containsSequence(
- ThriftField.TYPE_STRING, 0, 3, 0, 0, 0, 0); // serviceName (empty is 32 zero bits)
+ assertThat(bytes)
+ .containsSequence(
+ ThriftField.TYPE_STRING, 0, 3, 0, 0, 0, 0); // serviceName (empty is 32 zero bits)
}
/** To match finagle */
@@ -323,17 +308,17 @@ public void writesDebugFalse() {
writer.write(span, buf);
- assertThat(buf.unwrap()).containsSequence(ThriftField.TYPE_BOOL, 0);
+ assertThat(bytes).containsSequence(ThriftField.TYPE_BOOL, 0);
}
@Test
public void tagsAreBinaryAnnotations() {
writer.write(span.toBuilder().putTag("foo", "bar").build(), buf);
- assertThat(buf.unwrap())
- .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
- .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 3, 'f', 'o', 'o') // key
- .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 3, 'b', 'a', 'r') // value
- .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 6); // type 6 == string
+ assertThat(bytes)
+ .containsSequence(TYPE_LIST, 0, 8, TYPE_STRUCT, 0, 0, 0, 1) // one binary annotation
+ .containsSequence(TYPE_STRING, 0, 1, 0, 0, 0, 3, 'f', 'o', 'o') // key
+ .containsSequence(TYPE_STRING, 0, 2, 0, 0, 0, 3, 'b', 'a', 'r') // value
+ .containsSequence(TYPE_I32, 0, 3, 0, 0, 0, 6); // type 6 == string
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/V2SpanWriterTest.java b/zipkin/src/test/java/zipkin2/internal/V2SpanWriterTest.java
index 8c632ed863d..415cb76b198 100644
--- a/zipkin/src/test/java/zipkin2/internal/V2SpanWriterTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/V2SpanWriterTest.java
@@ -16,8 +16,6 @@
*/
package zipkin2.internal;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -27,10 +25,12 @@
import static org.assertj.core.api.Assertions.assertThat;
import static zipkin2.TestObjects.CLIENT_SPAN;
import static zipkin2.TestObjects.TODAY;
+import static zipkin2.TestObjects.UTF_8;
public class V2SpanWriterTest {
V2SpanWriter writer = new V2SpanWriter();
- UnsafeBuffer buf = UnsafeBuffer.allocate(2048); // bigger than needed to test sizeOf
+ byte[] bytes = new byte[2048]; // bigger than needed to test sizeInBytes
+ WriteBuffer buf = WriteBuffer.wrap(bytes);
@Rule public ExpectedException thrown = ExpectedException.none();
@@ -40,21 +40,21 @@ public class V2SpanWriterTest {
.isEqualTo(buf.pos());
}
- @Test public void writes128BitTraceId() throws UnsupportedEncodingException {
+ @Test public void writes128BitTraceId() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.startsWith("{\"traceId\":\"" + CLIENT_SPAN.traceId() + "\"");
}
- @Test public void writesAnnotationWithoutEndpoint() throws IOException {
+ @Test public void writesAnnotationWithoutEndpoint() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains("{\"timestamp\":" + (TODAY + 100) * 1000L + ",\"value\":\"foo\"}");
}
- @Test public void omitsEmptySpanName() throws IOException {
+ @Test public void omitsEmptySpanName() {
Span span = Span.newBuilder()
.traceId("7180c278b62e8f6a216a2aea45d08fc9")
.parentId("6b221d5bc9e6496c")
@@ -63,25 +63,25 @@ public class V2SpanWriterTest {
writer.write(span, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.doesNotContain("name");
}
- @Test public void omitsEmptyServiceName() throws IOException {
+ @Test public void omitsEmptyServiceName() {
Span span = CLIENT_SPAN.toBuilder()
.localEndpoint(Endpoint.newBuilder().ip("127.0.0.1").build())
.build();
writer.write(span, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains("\"localEndpoint\":{\"ipv4\":\"127.0.0.1\"}");
}
- @Test public void tagsAreAMap() throws IOException {
+ @Test public void tagsAreAMap() {
writer.write(CLIENT_SPAN, buf);
- assertThat(new String(buf.unwrap(), "UTF-8"))
+ assertThat(new String(bytes, UTF_8))
.contains("\"tags\":{\"clnt/finagle.version\":\"6.45.0\",\"http.path\":\"/api\"}");
}
}
diff --git a/zipkin/src/test/java/zipkin2/internal/UnsafeBufferTest.java b/zipkin/src/test/java/zipkin2/internal/WriteBufferTest.java
similarity index 52%
rename from zipkin/src/test/java/zipkin2/internal/UnsafeBufferTest.java
rename to zipkin/src/test/java/zipkin2/internal/WriteBufferTest.java
index 22f97f2180c..941191e899b 100644
--- a/zipkin/src/test/java/zipkin2/internal/UnsafeBufferTest.java
+++ b/zipkin/src/test/java/zipkin2/internal/WriteBufferTest.java
@@ -16,17 +16,15 @@
*/
package zipkin2.internal;
-import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static zipkin2.TestObjects.UTF_8;
-public class UnsafeBufferTest {
+public class WriteBufferTest {
// Adapted from http://stackoverflow.com/questions/8511490/calculating-length-in-utf-8-of-java-string-without-actually-encoding-it
@Test public void utf8SizeInBytes() {
for (int codepoint = 0; codepoint <= 0x10FFFF; codepoint++) {
@@ -34,7 +32,7 @@ public class UnsafeBufferTest {
if (Character.isDefined(codepoint)) {
String test = new String(Character.toChars(codepoint));
int expected = test.getBytes(UTF_8).length;
- int actual = UnsafeBuffer.utf8SizeInBytes(test);
+ int actual = WriteBuffer.utf8SizeInBytes(test);
if (actual != expected) {
throw new AssertionError(actual + " length != " + expected + " for " + codepoint);
}
@@ -46,12 +44,12 @@ public class UnsafeBufferTest {
@Test public void utf8_malformed() {
for (int codepoint : Arrays.asList(0xD800, 0xDFFF, 0xD83D)) {
String test = new String(new int[] {'a', codepoint, 'c'}, 0, 3);
- assertThat(UnsafeBuffer.utf8SizeInBytes(test))
+ assertThat(WriteBuffer.utf8SizeInBytes(test))
.isEqualTo(3);
- UnsafeBuffer buffer = UnsafeBuffer.allocate(3);
- buffer.writeUtf8(test);
- assertThat(buffer.unwrap())
+ byte[] bytes = new byte[3];
+ WriteBuffer.wrap(bytes).writeUtf8(test);
+ assertThat(bytes)
.containsExactly('a', '?', 'c');
}
}
@@ -61,12 +59,12 @@ public class UnsafeBufferTest {
char[] array = "\uD83C\uDC00\uD83C\uDC01".toCharArray();
array[array.length - 1] = 'c';
String test = new String(array, 0, array.length - 1);
- assertThat(UnsafeBuffer.utf8SizeInBytes(test))
+ assertThat(WriteBuffer.utf8SizeInBytes(test))
.isEqualTo(5);
- UnsafeBuffer buffer = UnsafeBuffer.allocate(5);
- buffer.writeUtf8(test);
- assertThat(new String(buffer.unwrap(), UTF_8))
+ byte[] bytes = new byte[5];
+ WriteBuffer.wrap(bytes).writeUtf8(test);
+ assertThat(new String(bytes, UTF_8))
.isEqualTo("\uD83C\uDC00?");
}
@@ -75,12 +73,12 @@ public class UnsafeBufferTest {
char[] array = "\uD83C\uDC00\uD83C\uDC01".toCharArray();
array[array.length - 1] = 'c';
String test = new String(array);
- assertThat(UnsafeBuffer.utf8SizeInBytes(test))
+ assertThat(WriteBuffer.utf8SizeInBytes(test))
.isEqualTo(6);
- UnsafeBuffer buffer = UnsafeBuffer.allocate(6);
- buffer.writeUtf8(test);
- assertThat(new String(buffer.unwrap(), UTF_8))
+ byte[] bytes = new byte[6];
+ WriteBuffer.wrap(bytes).writeUtf8(test);
+ assertThat(new String(bytes, UTF_8))
.isEqualTo("\uD83C\uDC00?c");
}
@@ -91,43 +89,42 @@ public class UnsafeBufferTest {
"ю́ cyrillic small letter yu with acute",
"∃y ∀x ¬(x ≺ y)"
)) {
- int encodedSize = UnsafeBuffer.utf8SizeInBytes(string);
+ int encodedSize = WriteBuffer.utf8SizeInBytes(string);
assertThat(encodedSize)
.isEqualTo(string.getBytes(UTF_8).length);
- UnsafeBuffer bufferUtf8 = UnsafeBuffer.allocate(encodedSize);
- bufferUtf8.writeUtf8(string);
- assertThat(new String(bufferUtf8.unwrap(), UTF_8))
+ byte[] bytes = new byte[encodedSize];
+ WriteBuffer.wrap(bytes).writeUtf8(string);
+ assertThat(new String(bytes, UTF_8))
.isEqualTo(string);
}
}
- @Test public void utf8_matchesAscii() throws Exception {
+ @Test public void utf8_matchesAscii() {
String ascii = "86154a4ba6e913854d1e00c0db9010db";
- int encodedSize = UnsafeBuffer.utf8SizeInBytes(ascii);
+ int encodedSize = WriteBuffer.utf8SizeInBytes(ascii);
assertThat(encodedSize)
.isEqualTo(ascii.length());
- UnsafeBuffer bufferAscii = UnsafeBuffer.allocate(encodedSize);
- bufferAscii.writeAscii(ascii);
- assertThat(new String(bufferAscii.unwrap(), "US-ASCII"))
+ byte[] bytes = new byte[encodedSize];
+ WriteBuffer.wrap(bytes).writeAscii(ascii);
+ assertThat(new String(bytes, UTF_8))
.isEqualTo(ascii);
- UnsafeBuffer bufferUtf8 = UnsafeBuffer.allocate(encodedSize);
- bufferUtf8.writeUtf8(ascii);
- assertThat(new String(bufferUtf8.unwrap(), "US-ASCII"))
+ WriteBuffer.wrap(bytes).writeUtf8(ascii);
+ assertThat(new String(bytes, UTF_8))
.isEqualTo(ascii);
}
@Test public void emoji() {
byte[] emojiBytes = {(byte) 0xF0, (byte) 0x9F, (byte) 0x98, (byte) 0x81};
String emoji = new String(emojiBytes, UTF_8);
- assertThat(UnsafeBuffer.utf8SizeInBytes(emoji))
+ assertThat(WriteBuffer.utf8SizeInBytes(emoji))
.isEqualTo(emojiBytes.length);
- UnsafeBuffer buffer = UnsafeBuffer.allocate(emojiBytes.length);
- buffer.writeUtf8(emoji);
- assertThat(buffer.unwrap())
+ byte[] bytes = new byte[emojiBytes.length];
+ WriteBuffer.wrap(bytes).writeUtf8(emoji);
+ assertThat(bytes)
.isEqualTo(emojiBytes);
}
@@ -143,45 +140,45 @@ public class UnsafeBufferTest {
}
static String writeAscii(long v) {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.asciiSizeInBytes(v));
- buffer.writeAscii(v);
- return new String(buffer.unwrap(), UTF_8);
+ byte[] bytes = new byte[WriteBuffer.asciiSizeInBytes(v)];
+ WriteBuffer.wrap(bytes).writeAscii(v);
+ return new String(bytes, UTF_8);
}
// Test creating Buffer for a long string
- @Test public void writeString() throws UnsupportedEncodingException {
- StringBuffer stringBuffer = new StringBuffer();
+ @Test public void writeString() {
+ StringBuilder builder = new StringBuilder();
for (int i = 0; i < 100000; i++) {
- stringBuffer.append("a");
+ builder.append("a");
}
- String string = stringBuffer.toString();
- UnsafeBuffer buffer = UnsafeBuffer.allocate(string.length());
- buffer.writeAscii(string);
- assertThat(new String(buffer.unwrap(), "US-ASCII")).isEqualTo(string);
+ String string = builder.toString();
+ byte[] bytes = new byte[string.length()];
+ WriteBuffer.wrap(bytes).writeAscii(string);
+ assertThat(new String(bytes, UTF_8)).isEqualTo(string);
}
@Test public void unsignedVarintSize_32_largest() {
// largest to encode is a negative number
- assertThat(UnsafeBuffer.varintSizeInBytes(Integer.MIN_VALUE))
+ assertThat(WriteBuffer.varintSizeInBytes(Integer.MIN_VALUE))
.isEqualTo(5);
}
@Test public void unsignedVarintSize_64_largest() {
// largest to encode is a negative number
- assertThat(UnsafeBuffer.varintSizeInBytes(Long.MIN_VALUE))
+ assertThat(WriteBuffer.varintSizeInBytes(Long.MIN_VALUE))
.isEqualTo(10);
}
@Test public void writeLongLe_matchesByteBuffer() {
for (long number : Arrays.asList(Long.MIN_VALUE, 0L, Long.MAX_VALUE)) {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(8);
- buffer.writeLongLe(number);
+ byte[] bytes = new byte[8];
+ WriteBuffer.wrap(bytes).writeLongLe(number);
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putLong(number);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(byteBuffer.array());
}
}
@@ -190,10 +187,10 @@ static String writeAscii(long v) {
@Test public void writeVarint_32() {
int number = 300;
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(number));
- buffer.writeVarint(number);
+ byte[] bytes = new byte[WriteBuffer.varintSizeInBytes(number)];
+ WriteBuffer.wrap(bytes).writeVarint(number);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b1010_1100, 0b0000_0010);
}
@@ -201,100 +198,41 @@ static String writeAscii(long v) {
@Test public void writeVarint_64() {
long number = 300;
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(number));
- buffer.writeVarint(number);
+ byte[] bytes = new byte[WriteBuffer.varintSizeInBytes(number)];
+ WriteBuffer.wrap(bytes).writeVarint(number);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b1010_1100, 0b0000_0010);
}
@Test public void writeVarint_ports() {
// normal case
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(80));
- buffer.writeVarint(80);
+ byte[] bytes = new byte[WriteBuffer.varintSizeInBytes(80)];
+ WriteBuffer.wrap(bytes).writeVarint(80);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b0101_0000);
// largest value to not require more than 2 bytes (14 bits set)
- buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(16383));
- buffer.writeVarint(16383);
+ bytes = new byte[WriteBuffer.varintSizeInBytes(16383)];
+ WriteBuffer.wrap(bytes).writeVarint(16383);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b1111_1111, 0b0111_1111);
// worst case is a byte longer than fixed 16
- buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(65535));
- buffer.writeVarint(65535);
+ bytes = new byte[WriteBuffer.varintSizeInBytes(65535)];
+ WriteBuffer.wrap(bytes).writeVarint(65535);
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b1111_1111, 0b1111_1111, 0b0000_0011);
// most bits
- buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(0xFFFFFFFF));
- buffer.writeVarint(0xFFFFFFFF);
+ bytes = new byte[WriteBuffer.varintSizeInBytes(0xFFFFFFFF)];
+ WriteBuffer.wrap(bytes).writeVarint(0xFFFFFFFF);
// we have a total of 32 bits encoded
- assertThat(buffer.unwrap())
+ assertThat(bytes)
.containsExactly(0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1111);
}
-
- @Test public void readVarint32() {
- assertReadVarint32(0);
- assertReadVarint32(0b0011_1111_1111_1111);
- assertReadVarint32(0xFFFFFFFF);
- }
-
- static void assertReadVarint32(int value) {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(value));
- buffer.writeVarint(value);
- buffer.reset();
-
- assertThat(buffer.readVarint32())
- .isEqualTo(value);
- }
-
- @Test public void readVarint32_malformedTooBig() {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(8);
- buffer.writeLongLe(0xffffffffffffL);
- buffer.reset();
-
- try {
- buffer.readVarint32();
- failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e)
- .hasMessage("Greater than 32-bit varint at position 4");
- }
- }
-
- @Test public void readVarint64() {
- assertReadVarint64(0L);
- assertReadVarint64(0b0011_1111_1111_1111L);
- assertReadVarint64(0xffffffffffffffffL);
- }
-
- static void assertReadVarint64(long value) {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(UnsafeBuffer.varintSizeInBytes(value));
- buffer.writeVarint(value);
- buffer.reset();
-
- assertThat(buffer.readVarint64())
- .isEqualTo(value);
- }
-
- @Test public void readVarint64_malformedTooBig() {
- UnsafeBuffer buffer = UnsafeBuffer.allocate(16);
- buffer.writeLongLe(0xffffffffffffffffL);
- buffer.writeLongLe(0xffffffffffffffffL);
- buffer.reset();
-
- try {
- buffer.readVarint64();
- failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e)
- .hasMessage("Greater than 64-bit varint at position 9");
- }
- }
}
*