diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ComplexEqualsHashCodeBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ComplexEqualsHashCodeBench.java index fd0ebfcf..fbfe7b0d 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ComplexEqualsHashCodeBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ComplexEqualsHashCodeBench.java @@ -58,8 +58,7 @@ public record HashevalJavaRecord( Suit enumSuit, @Nullable TimestampTest subObject, String text, - Bytes bytesField - ){} + Bytes bytesField) {} private final Hasheval hasheval; private final Hasheval hasheval1; @@ -69,42 +68,114 @@ public record HashevalJavaRecord( private final HashevalJavaRecord hashevalJavaRecordDifferent; public ComplexEqualsHashCodeBench() { - hasheval = new Hasheval(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + hasheval = new Hasheval( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "FooBarKKKKHHHHOIOIOI", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); - hasheval1 = new Hasheval(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); + hasheval1 = new Hasheval( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "FooBarKKKKHHHHOIOIOI", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); - hashevalDifferent = new Hasheval(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); + hashevalDifferent = new Hasheval( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "Different", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); - hashevalJavaRecord = new HashevalJavaRecord(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); + hashevalJavaRecord = new HashevalJavaRecord( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "FooBarKKKKHHHHOIOIOI", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); - hashevalJavaRecord1 = new HashevalJavaRecord(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); + hashevalJavaRecord1 = new HashevalJavaRecord( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "FooBarKKKKHHHHOIOIOI", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); - hashevalJavaRecordDifferent = new HashevalJavaRecord(123, 123, 123, - 123, 123, 1.23f, 123L, 123L, - 123L, 123L, 123L, 1.23D, true, - Suit.ACES, new TimestampTest(987L, 123), + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); + hashevalJavaRecordDifferent = new HashevalJavaRecord( + 123, + 123, + 123, + 123, + 123, + 1.23f, + 123L, + 123L, + 123L, + 123L, + 123L, + 1.23D, + true, + Suit.ACES, + new TimestampTest(987L, 123), "Different", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); } @Benchmark @@ -130,6 +201,7 @@ public void benchEquals(Blackhole blackhole) { blackhole.consume(hasheval.equals(hasheval1)); } } + @Benchmark @OperationsPerInvocation(1050) public void benchJavaRecordEquals(Blackhole blackhole) { diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/EqualsHashCodeBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/EqualsHashCodeBench.java index 8705997f..bcc8bb2d 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/EqualsHashCodeBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/EqualsHashCodeBench.java @@ -2,6 +2,7 @@ package com.hedera.pbj.integration.jmh; import com.hedera.pbj.test.proto.pbj.TimestampTest; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -9,14 +10,12 @@ import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Scope; // Add any other JMH annotation imports you use +import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -import java.util.concurrent.TimeUnit; - /* Mac Results @@ -39,7 +38,7 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) public class EqualsHashCodeBench { - public record TimestampStandardRecord(long seconds, int nanos){} + public record TimestampStandardRecord(long seconds, int nanos) {} private final TimestampTest testStamp; private final TimestampTest testStamp1; @@ -80,6 +79,7 @@ public void benchEquals(Blackhole blackhole) { blackhole.consume(testStamp.equals(testStamp1)); } } + @Benchmark @OperationsPerInvocation(1050) public void benchJavaRecordEquals(Blackhole blackhole) { diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/HashBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/HashBench.java index ebdd9530..75bd1f34 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/HashBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/HashBench.java @@ -6,6 +6,8 @@ import com.hedera.pbj.test.proto.pbj.Hasheval; import com.hedera.pbj.test.proto.pbj.Suit; import com.hedera.pbj.test.proto.pbj.TimestampTest; +import java.io.IOException; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -18,9 +20,6 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -import java.io.IOException; -import java.util.concurrent.TimeUnit; - @SuppressWarnings("unused") @State(Scope.Benchmark) @Fork(1) @@ -33,10 +32,24 @@ public class HashBench { public HashBench() { TimestampTest tst = new TimestampTest(987L, 123); - hasheval = new Hasheval(1, -1, 2, 3, -2, - 123f, 7L, -7L, 123L, 234L, - -345L, 456.789D, true, Suit.ACES, tst, "FooBarKKKKHHHHOIOIOI", - Bytes.wrap(new byte[]{1, 2, 3, 4, 5, 6, 7, (byte)255})); + hasheval = new Hasheval( + 1, + -1, + 2, + 3, + -2, + 123f, + 7L, + -7L, + 123L, + 234L, + -345L, + 456.789D, + true, + Suit.ACES, + tst, + "FooBarKKKKHHHHOIOIOI", + Bytes.wrap(new byte[] {1, 2, 3, 4, 5, 6, 7, (byte) 255})); } @Benchmark diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/JsonBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/JsonBench.java index f6ada547..b6d4bcbb 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/JsonBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/JsonBench.java @@ -2,7 +2,6 @@ package com.hedera.pbj.integration.jmh; import com.google.protobuf.GeneratedMessage; -import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import com.hedera.hapi.node.base.Timestamp; @@ -15,6 +14,9 @@ import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.test.proto.pbj.Everything; import com.hederahashgraph.api.proto.java.GetAccountDetailsResponse; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -27,132 +29,139 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; - @SuppressWarnings("unused") @Fork(1) @Warmup(iterations = 2, time = 2) @Measurement(iterations = 5, time = 2) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) -public abstract class JsonBench

{ - - @SuppressWarnings("rawtypes") - @State(Scope.Benchmark) - public static class JsonBenchmarkState

{ - private JsonCodec

pbjJsonCodec; - private Supplier builderSupplier; - // input objects - private P pbjModelObject; - private G googleModelObject; - - // input bytes - private BufferedData jsonDataBuffer; - private String jsonString; - - // output buffers - private BufferedData outDataBuffer; - public void configure(P pbjModelObject, Codec

pbjProtoCodec, JsonCodec

pbjJsonCodec, - ProtobufObjectBench.ProtobufParseFunction googleByteArrayParseMethod, - Supplier builderSupplier) { - try { - this.pbjModelObject = pbjModelObject; - this.pbjJsonCodec = pbjJsonCodec; - this.builderSupplier = builderSupplier; - // write to JSON for parse tests - jsonDataBuffer = BufferedData.allocate(5 * 1024 * 1024); - pbjJsonCodec.write(pbjModelObject, jsonDataBuffer); - jsonDataBuffer.flip(); - // get as string for parse tests - jsonString = jsonDataBuffer.asUtf8String(); - - // write to temp data buffer and then read into byte array - BufferedData tempDataBuffer = BufferedData.allocate(5 * 1024 * 1024); - pbjProtoCodec.write(pbjModelObject, tempDataBuffer); - tempDataBuffer.flip(); - byte[] protoBytes = new byte[(int)tempDataBuffer.length()]; - tempDataBuffer.getBytes(0,protoBytes); - // convert to protobuf - googleModelObject = googleByteArrayParseMethod.parse(protoBytes); - - // input buffers - // output buffers - this.outDataBuffer = BufferedData.allocate(jsonString.length()); - } catch (IOException e) { - e.getStackTrace(); - System.err.flush(); - throw new RuntimeException(e); - } - } - } - - /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - public void parsePbj(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { - benchmarkState.jsonDataBuffer.position(0); - blackhole.consume(benchmarkState.pbjJsonCodec.parse(benchmarkState.jsonDataBuffer)); - } - - @Benchmark - public void parseProtoC(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - var builder = benchmarkState.builderSupplier.get(); - JsonFormat.parser().merge(benchmarkState.jsonString, builder); - blackhole.consume(builder.build()); - } - - /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - public void writePbj(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - benchmarkState.outDataBuffer.reset(); - benchmarkState.pbjJsonCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); - blackhole.consume(benchmarkState.outDataBuffer); - } - - @Benchmark - public void writeProtoC(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws InvalidProtocolBufferException { - blackhole.consume(JsonFormat.printer().print(benchmarkState.googleModelObject)); - } - - /** Custom interface for method references as java.util.Function does not throw IOException */ - public interface ProtobufParseFunction { - G parse(D data) throws IOException; - } - - @State(Scope.Benchmark) - public static class EverythingBench extends JsonBench { - @Setup - public void setup(JsonBenchmarkState benchmarkState) { - benchmarkState.configure(EverythingTestData.EVERYTHING, - Everything.PROTOBUF, - Everything.JSON, - com.hedera.pbj.test.proto.java.Everything::parseFrom, - com.hedera.pbj.test.proto.java.Everything::newBuilder); - } - } - - @State(Scope.Benchmark) - public static class TimeStampBench extends JsonBench { - @Setup - public void setup(JsonBenchmarkState benchmarkState) { - benchmarkState.configure(new Timestamp(5678L, 1234), - Timestamp.PROTOBUF, - Timestamp.JSON, - com.hederahashgraph.api.proto.java.Timestamp::parseFrom, - com.hederahashgraph.api.proto.java.Timestamp::newBuilder); - } - } - - @State(Scope.Benchmark) - public static class AccountDetailsBench extends JsonBench { - @Setup - public void setup(JsonBenchmarkState benchmarkState) { - benchmarkState.configure(AccountDetailsPbj.ACCOUNT_DETAILS, - AccountDetails.PROTOBUF, - AccountDetails.JSON, - GetAccountDetailsResponse.AccountDetails::parseFrom, - GetAccountDetailsResponse.AccountDetails::newBuilder); - } - } +public abstract class JsonBench

{ + + @SuppressWarnings("rawtypes") + @State(Scope.Benchmark) + public static class JsonBenchmarkState

{ + private JsonCodec

pbjJsonCodec; + private Supplier builderSupplier; + // input objects + private P pbjModelObject; + private G googleModelObject; + + // input bytes + private BufferedData jsonDataBuffer; + private String jsonString; + + // output buffers + private BufferedData outDataBuffer; + + public void configure( + P pbjModelObject, + Codec

pbjProtoCodec, + JsonCodec

pbjJsonCodec, + ProtobufObjectBench.ProtobufParseFunction googleByteArrayParseMethod, + Supplier builderSupplier) { + try { + this.pbjModelObject = pbjModelObject; + this.pbjJsonCodec = pbjJsonCodec; + this.builderSupplier = builderSupplier; + // write to JSON for parse tests + jsonDataBuffer = BufferedData.allocate(5 * 1024 * 1024); + pbjJsonCodec.write(pbjModelObject, jsonDataBuffer); + jsonDataBuffer.flip(); + // get as string for parse tests + jsonString = jsonDataBuffer.asUtf8String(); + + // write to temp data buffer and then read into byte array + BufferedData tempDataBuffer = BufferedData.allocate(5 * 1024 * 1024); + pbjProtoCodec.write(pbjModelObject, tempDataBuffer); + tempDataBuffer.flip(); + byte[] protoBytes = new byte[(int) tempDataBuffer.length()]; + tempDataBuffer.getBytes(0, protoBytes); + // convert to protobuf + googleModelObject = googleByteArrayParseMethod.parse(protoBytes); + + // input buffers + // output buffers + this.outDataBuffer = BufferedData.allocate(jsonString.length()); + } catch (IOException e) { + e.getStackTrace(); + System.err.flush(); + throw new RuntimeException(e); + } + } + } + + /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + public void parsePbj(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { + benchmarkState.jsonDataBuffer.position(0); + blackhole.consume(benchmarkState.pbjJsonCodec.parse(benchmarkState.jsonDataBuffer)); + } + + @Benchmark + public void parseProtoC(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + var builder = benchmarkState.builderSupplier.get(); + JsonFormat.parser().merge(benchmarkState.jsonString, builder); + blackhole.consume(builder.build()); + } + + /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + public void writePbj(JsonBenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + benchmarkState.outDataBuffer.reset(); + benchmarkState.pbjJsonCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); + blackhole.consume(benchmarkState.outDataBuffer); + } + + @Benchmark + public void writeProtoC(JsonBenchmarkState benchmarkState, Blackhole blackhole) + throws InvalidProtocolBufferException { + blackhole.consume(JsonFormat.printer().print(benchmarkState.googleModelObject)); + } + + /** Custom interface for method references as java.util.Function does not throw IOException */ + public interface ProtobufParseFunction { + G parse(D data) throws IOException; + } + + @State(Scope.Benchmark) + public static class EverythingBench extends JsonBench { + @Setup + public void setup(JsonBenchmarkState benchmarkState) { + benchmarkState.configure( + EverythingTestData.EVERYTHING, + Everything.PROTOBUF, + Everything.JSON, + com.hedera.pbj.test.proto.java.Everything::parseFrom, + com.hedera.pbj.test.proto.java.Everything::newBuilder); + } + } + + @State(Scope.Benchmark) + public static class TimeStampBench extends JsonBench { + @Setup + public void setup(JsonBenchmarkState benchmarkState) { + benchmarkState.configure( + new Timestamp(5678L, 1234), + Timestamp.PROTOBUF, + Timestamp.JSON, + com.hederahashgraph.api.proto.java.Timestamp::parseFrom, + com.hederahashgraph.api.proto.java.Timestamp::newBuilder); + } + } + + @State(Scope.Benchmark) + public static class AccountDetailsBench + extends JsonBench { + @Setup + public void setup( + JsonBenchmarkState + benchmarkState) { + benchmarkState.configure( + AccountDetailsPbj.ACCOUNT_DETAILS, + AccountDetails.PROTOBUF, + AccountDetails.JSON, + GetAccountDetailsResponse.AccountDetails::parseFrom, + GetAccountDetailsResponse.AccountDetails::newBuilder); + } + } } diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ProtobufObjectBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ProtobufObjectBench.java index c3b90674..10bad6f9 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ProtobufObjectBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/ProtobufObjectBench.java @@ -3,7 +3,6 @@ import com.google.protobuf.CodedOutputStream; import com.google.protobuf.GeneratedMessage; -import com.hedera.hapi.block.stream.protoc.Block; import com.hedera.hapi.node.base.Timestamp; import com.hedera.hapi.node.token.AccountDetails; import com.hedera.pbj.integration.AccountDetailsPbj; @@ -17,6 +16,10 @@ import com.hedera.pbj.runtime.io.stream.WritableStreamingData; import com.hedera.pbj.test.proto.pbj.Everything; import com.hederahashgraph.api.proto.java.GetAccountDetailsResponse; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -30,272 +33,287 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.concurrent.TimeUnit; -import java.util.zip.GZIPInputStream; - @SuppressWarnings("unused") @Fork(1) @Warmup(iterations = 3, time = 2) @Measurement(iterations = 7, time = 2) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) -public abstract class ProtobufObjectBench

{ - /** we repeat all operations 1000 times so that measured times are nig enough */ - private static final int OPERATION_COUNT = 1000; +public abstract class ProtobufObjectBench

{ + /** we repeat all operations 1000 times so that measured times are nig enough */ + private static final int OPERATION_COUNT = 1000; + + @State(Scope.Benchmark) + public static class BenchmarkState

{ + private Codec

pbjCodec; + private ProtobufParseFunction googleByteArrayParseMethod; + private ProtobufParseFunction googleByteBufferParseMethod; + private ProtobufParseFunction googleInputStreamParseMethod; + // input objects + private P pbjModelObject; + private G googleModelObject; + + // input bytes + private byte[] protobuf; + private ByteBuffer protobufByteBuffer; + private BufferedData protobufDataBuffer; + private ByteBuffer protobufByteBufferDirect; + private BufferedData protobufDataBufferDirect; + private NonSynchronizedByteArrayInputStream bin; + + // output buffers + private NonSynchronizedByteArrayOutputStream bout; + private BufferedData outDataBuffer; + private BufferedData outDataBufferDirect; + private ByteBuffer bbout; + private ByteBuffer bboutDirect; + + public void configure( + P pbjModelObject, + Codec

pbjCodec, + ProtobufParseFunction googleByteArrayParseMethod, + ProtobufParseFunction googleByteBufferParseMethod, + ProtobufParseFunction googleInputStreamParseMethod) { + try { + this.pbjModelObject = pbjModelObject; + this.pbjCodec = pbjCodec; + this.googleByteArrayParseMethod = googleByteArrayParseMethod; + this.googleByteBufferParseMethod = googleByteBufferParseMethod; + this.googleInputStreamParseMethod = googleInputStreamParseMethod; + // write to temp data buffer and then read into byte array + BufferedData tempDataBuffer = BufferedData.allocate(5 * 1024 * 1024); + pbjCodec.write(pbjModelObject, tempDataBuffer); + tempDataBuffer.flip(); + this.protobuf = new byte[(int) tempDataBuffer.remaining()]; + tempDataBuffer.readBytes(this.protobuf); + // start by parsing using protoc + this.googleModelObject = googleByteArrayParseMethod.parse(this.protobuf); + + // input buffers + this.protobufByteBuffer = ByteBuffer.wrap(this.protobuf); + this.protobufDataBuffer = BufferedData.wrap(this.protobuf); + this.protobufByteBufferDirect = ByteBuffer.allocateDirect(this.protobuf.length); + this.protobufByteBufferDirect.put(this.protobuf); + this.protobufDataBufferDirect = BufferedData.wrap(this.protobufByteBufferDirect); + this.bin = new NonSynchronizedByteArrayInputStream(this.protobuf); + ReadableStreamingData din = new ReadableStreamingData(this.bin); + // output buffers + this.bout = new NonSynchronizedByteArrayOutputStream(); + WritableStreamingData dout = new WritableStreamingData(this.bout); + this.outDataBuffer = BufferedData.allocate(this.protobuf.length); + this.outDataBufferDirect = BufferedData.allocateOffHeap(this.protobuf.length); + this.bbout = ByteBuffer.allocate(this.protobuf.length); + this.bboutDirect = ByteBuffer.allocateDirect(this.protobuf.length); + } catch (IOException e) { + e.getStackTrace(); + System.err.flush(); + throw new RuntimeException(e); + } + } + } + + /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parsePbjByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.protobufDataBuffer.resetPosition(); + blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBuffer)); + } + } + + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parsePbjByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.protobufDataBuffer.resetPosition(); + blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBuffer)); + } + } - @State(Scope.Benchmark) - public static class BenchmarkState

{ - private Codec

pbjCodec; - private ProtobufParseFunction googleByteArrayParseMethod; - private ProtobufParseFunction googleByteBufferParseMethod; - private ProtobufParseFunction googleInputStreamParseMethod; - // input objects - private P pbjModelObject; - private G googleModelObject; + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parsePbjByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) + throws ParseException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.protobufDataBufferDirect.resetPosition(); + blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBufferDirect)); + } + } - // input bytes - private byte[] protobuf; - private ByteBuffer protobufByteBuffer; - private BufferedData protobufDataBuffer; - private ByteBuffer protobufByteBufferDirect; - private BufferedData protobufDataBufferDirect; - private NonSynchronizedByteArrayInputStream bin; + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parsePbjInputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.bin.resetPosition(); + blackhole.consume(benchmarkState.pbjCodec.parse(new ReadableStreamingData(benchmarkState.bin))); + } + } - // output buffers - private NonSynchronizedByteArrayOutputStream bout; - private BufferedData outDataBuffer; - private BufferedData outDataBufferDirect; - private ByteBuffer bbout; - private ByteBuffer bboutDirect; - public void configure(P pbjModelObject, Codec

pbjCodec, - ProtobufParseFunction googleByteArrayParseMethod, - ProtobufParseFunction googleByteBufferParseMethod, - ProtobufParseFunction googleInputStreamParseMethod) { - try { - this.pbjModelObject = pbjModelObject; - this.pbjCodec = pbjCodec; - this.googleByteArrayParseMethod = googleByteArrayParseMethod; - this.googleByteBufferParseMethod = googleByteBufferParseMethod; - this.googleInputStreamParseMethod = googleInputStreamParseMethod; - // write to temp data buffer and then read into byte array - BufferedData tempDataBuffer = BufferedData.allocate(5 * 1024 * 1024); - pbjCodec.write(pbjModelObject, tempDataBuffer); - tempDataBuffer.flip(); - this.protobuf = new byte[(int) tempDataBuffer.remaining()]; - tempDataBuffer.readBytes(this.protobuf); - // start by parsing using protoc - this.googleModelObject = googleByteArrayParseMethod.parse(this.protobuf); + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parseProtoCByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + blackhole.consume(benchmarkState.googleByteArrayParseMethod.parse(benchmarkState.protobuf)); + } + } - // input buffers - this.protobufByteBuffer = ByteBuffer.wrap(this.protobuf); - this.protobufDataBuffer = BufferedData.wrap(this.protobuf); - this.protobufByteBufferDirect = ByteBuffer.allocateDirect(this.protobuf.length); - this.protobufByteBufferDirect.put(this.protobuf); - this.protobufDataBufferDirect = BufferedData.wrap(this.protobufByteBufferDirect); - this.bin = new NonSynchronizedByteArrayInputStream(this.protobuf); - ReadableStreamingData din = new ReadableStreamingData(this.bin); - // output buffers - this.bout = new NonSynchronizedByteArrayOutputStream(); - WritableStreamingData dout = new WritableStreamingData(this.bout); - this.outDataBuffer = BufferedData.allocate(this.protobuf.length); - this.outDataBufferDirect = BufferedData.allocateOffHeap(this.protobuf.length); - this.bbout = ByteBuffer.allocate(this.protobuf.length); - this.bboutDirect = ByteBuffer.allocateDirect(this.protobuf.length); - } catch (IOException e) { - e.getStackTrace(); - System.err.flush(); - throw new RuntimeException(e); - } - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parseProtoCByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) + throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.protobufByteBufferDirect.position(0); + blackhole.consume( + benchmarkState.googleByteBufferParseMethod.parse(benchmarkState.protobufByteBufferDirect)); + } + } - /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parsePbjByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.protobufDataBuffer.resetPosition(); - blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBuffer)); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parseProtoCByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + blackhole.consume(benchmarkState.googleByteBufferParseMethod.parse(benchmarkState.protobufByteBuffer)); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parsePbjByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.protobufDataBuffer.resetPosition(); - blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBuffer)); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void parseProtoCInputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.bin.resetPosition(); + blackhole.consume(benchmarkState.googleInputStreamParseMethod.parse(benchmarkState.bin)); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parsePbjByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) - throws ParseException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.protobufDataBufferDirect.resetPosition(); - blackhole.consume(benchmarkState.pbjCodec.parse(benchmarkState.protobufDataBufferDirect)); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parsePbjInputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws ParseException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.bin.resetPosition(); - blackhole.consume(benchmarkState.pbjCodec.parse(new ReadableStreamingData(benchmarkState.bin))); - } - } + /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writePbjByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.outDataBuffer.reset(); + benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); + blackhole.consume(benchmarkState.outDataBuffer); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parseProtoCByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - blackhole.consume(benchmarkState.googleByteArrayParseMethod.parse(benchmarkState.protobuf)); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parseProtoCByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.protobufByteBufferDirect.position(0); - blackhole.consume(benchmarkState.googleByteBufferParseMethod.parse(benchmarkState.protobufByteBufferDirect)); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parseProtoCByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - blackhole.consume(benchmarkState.googleByteBufferParseMethod.parse(benchmarkState.protobufByteBuffer)); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void parseProtoCInputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.bin.resetPosition(); - blackhole.consume(benchmarkState.googleInputStreamParseMethod.parse(benchmarkState.bin)); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writePbjByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.outDataBuffer.reset(); + benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); + blackhole.consume(benchmarkState.outDataBuffer); + } + } - /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writePbjByteArray(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.outDataBuffer.reset(); - benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); - blackhole.consume(benchmarkState.outDataBuffer); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writePbjByteDirect(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.outDataBufferDirect.reset(); + benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBufferDirect); + blackhole.consume(benchmarkState.outDataBufferDirect); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writePbjByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.outDataBuffer.reset(); - benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBuffer); - blackhole.consume(benchmarkState.outDataBuffer); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writePbjByteDirect(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.outDataBufferDirect.reset(); - benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, benchmarkState.outDataBufferDirect); - blackhole.consume(benchmarkState.outDataBufferDirect); - } - } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writePbjOutputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.bout.reset(); - benchmarkState.pbjCodec.write(benchmarkState.pbjModelObject, new WritableStreamingData(benchmarkState.bout)); - blackhole.consume(benchmarkState.bout.toByteArray()); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writePbjOutputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.bout.reset(); + benchmarkState.pbjCodec.write( + benchmarkState.pbjModelObject, new WritableStreamingData(benchmarkState.bout)); + blackhole.consume(benchmarkState.bout.toByteArray()); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writeProtoCByteArray(BenchmarkState benchmarkState, Blackhole blackhole) { - for (int i = 0; i < OPERATION_COUNT; i++) { - blackhole.consume(benchmarkState.googleModelObject.toByteArray()); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writeProtoCByteArray(BenchmarkState benchmarkState, Blackhole blackhole) { + for (int i = 0; i < OPERATION_COUNT; i++) { + blackhole.consume(benchmarkState.googleModelObject.toByteArray()); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writeProtoCByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - CodedOutputStream cout = CodedOutputStream.newInstance(benchmarkState.bbout); - benchmarkState.googleModelObject.writeTo(cout); - blackhole.consume(benchmarkState.bbout); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writeProtoCByteBuffer(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + CodedOutputStream cout = CodedOutputStream.newInstance(benchmarkState.bbout); + benchmarkState.googleModelObject.writeTo(cout); + blackhole.consume(benchmarkState.bbout); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writeProtoCByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - CodedOutputStream cout = CodedOutputStream.newInstance(benchmarkState.bboutDirect); - benchmarkState.googleModelObject.writeTo(cout); - blackhole.consume(benchmarkState.bbout); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writeProtoCByteBufferDirect(BenchmarkState benchmarkState, Blackhole blackhole) + throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + CodedOutputStream cout = CodedOutputStream.newInstance(benchmarkState.bboutDirect); + benchmarkState.googleModelObject.writeTo(cout); + blackhole.consume(benchmarkState.bbout); + } + } - @Benchmark - @OperationsPerInvocation(OPERATION_COUNT) - public void writeProtoCOutputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { - for (int i = 0; i < OPERATION_COUNT; i++) { - benchmarkState.bout.reset(); - benchmarkState.googleModelObject.writeTo(benchmarkState.bout); - blackhole.consume(benchmarkState.bout.toByteArray()); - } - } + @Benchmark + @OperationsPerInvocation(OPERATION_COUNT) + public void writeProtoCOutputStream(BenchmarkState benchmarkState, Blackhole blackhole) throws IOException { + for (int i = 0; i < OPERATION_COUNT; i++) { + benchmarkState.bout.reset(); + benchmarkState.googleModelObject.writeTo(benchmarkState.bout); + blackhole.consume(benchmarkState.bout.toByteArray()); + } + } - /** Custom interface for method references as java.util.Function does not throw IOException */ - public interface ProtobufParseFunction { - G parse(D data) throws IOException; - } + /** Custom interface for method references as java.util.Function does not throw IOException */ + public interface ProtobufParseFunction { + G parse(D data) throws IOException; + } - @State(Scope.Benchmark) - public static class EverythingBench extends ProtobufObjectBench { - @Setup - public void setup(BenchmarkState benchmarkState) { - benchmarkState.configure(EverythingTestData.EVERYTHING, - Everything.PROTOBUF, - com.hedera.pbj.test.proto.java.Everything::parseFrom, - com.hedera.pbj.test.proto.java.Everything::parseFrom, - com.hedera.pbj.test.proto.java.Everything::parseFrom); - } - } + @State(Scope.Benchmark) + public static class EverythingBench + extends ProtobufObjectBench { + @Setup + public void setup(BenchmarkState benchmarkState) { + benchmarkState.configure( + EverythingTestData.EVERYTHING, + Everything.PROTOBUF, + com.hedera.pbj.test.proto.java.Everything::parseFrom, + com.hedera.pbj.test.proto.java.Everything::parseFrom, + com.hedera.pbj.test.proto.java.Everything::parseFrom); + } + } - @State(Scope.Benchmark) - public static class TimeStampBench extends ProtobufObjectBench { - @Setup - public void setup(BenchmarkState benchmarkState) { - benchmarkState.configure(new Timestamp(5678L, 1234), - Timestamp.PROTOBUF, - com.hederahashgraph.api.proto.java.Timestamp::parseFrom, - com.hederahashgraph.api.proto.java.Timestamp::parseFrom, - com.hederahashgraph.api.proto.java.Timestamp::parseFrom); - } - } + @State(Scope.Benchmark) + public static class TimeStampBench + extends ProtobufObjectBench { + @Setup + public void setup(BenchmarkState benchmarkState) { + benchmarkState.configure( + new Timestamp(5678L, 1234), + Timestamp.PROTOBUF, + com.hederahashgraph.api.proto.java.Timestamp::parseFrom, + com.hederahashgraph.api.proto.java.Timestamp::parseFrom, + com.hederahashgraph.api.proto.java.Timestamp::parseFrom); + } + } - @State(Scope.Benchmark) - public static class AccountDetailsBench extends ProtobufObjectBench { - @Setup - public void setup(BenchmarkState benchmarkState) { - benchmarkState.configure(AccountDetailsPbj.ACCOUNT_DETAILS, - AccountDetails.PROTOBUF, - GetAccountDetailsResponse.AccountDetails::parseFrom, - GetAccountDetailsResponse.AccountDetails::parseFrom, - GetAccountDetailsResponse.AccountDetails::parseFrom); - } - } + @State(Scope.Benchmark) + public static class AccountDetailsBench + extends ProtobufObjectBench< + com.hedera.hapi.node.token.AccountDetails, GetAccountDetailsResponse.AccountDetails> { + @Setup + public void setup( + BenchmarkState + benchmarkState) { + benchmarkState.configure( + AccountDetailsPbj.ACCOUNT_DETAILS, + AccountDetails.PROTOBUF, + GetAccountDetailsResponse.AccountDetails::parseFrom, + GetAccountDetailsResponse.AccountDetails::parseFrom, + GetAccountDetailsResponse.AccountDetails::parseFrom); + } + } } diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/SampleBlockBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/SampleBlockBench.java index 59c32d12..f836bb2f 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/SampleBlockBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/SampleBlockBench.java @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.jmh; import com.google.protobuf.CodedOutputStream; -import com.hedera.hapi.block.stream.BlockItem; import com.hedera.hapi.block.stream.protoc.Block; import com.hedera.pbj.integration.NonSynchronizedByteArrayInputStream; import com.hedera.pbj.integration.NonSynchronizedByteArrayOutputStream; @@ -10,16 +10,14 @@ import com.hedera.pbj.runtime.io.buffer.Bytes; import com.hedera.pbj.runtime.io.stream.ReadableStreamingData; import com.hedera.pbj.runtime.io.stream.WritableStreamingData; -import java.util.Comparator; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; - import java.io.BufferedInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPInputStream; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; /** * Benchmarks for parsing and writing a sample block using PBJ and Google Protobuf. @@ -32,176 +30,177 @@ @BenchmarkMode(Mode.AverageTime) @State(Scope.Benchmark) public class SampleBlockBench { - // test block - private static final com.hedera.hapi.block.stream.Block TEST_BLOCK; - private static final Block TEST_BLOCK_GOOGLE; - // input bytes - private static final byte[] TEST_BLOCK_PROTOBUF_BYTES; - private static final ByteBuffer PROTOBUF_BYTE_BUFFER; - private static final BufferedData PROTOBUF_DATA_BUFFER; - private static final ByteBuffer PROTOBUF_BYTE_BUFFER_DIRECT; - private static final BufferedData PROTOBUF_DATA_BUFFER_DIRECT; - private static final NonSynchronizedByteArrayInputStream PROTOBUF_INPUT_STREAM; - // load test block from resources - static { - // load the protobuf bytes - try (var in = new BufferedInputStream(new GZIPInputStream( - Objects.requireNonNull(SampleBlockBench.class.getResourceAsStream("/000000000000000000000000000000497558.blk.gz"))))) { - TEST_BLOCK_PROTOBUF_BYTES = in.readAllBytes(); - } catch (IOException e) { - throw new RuntimeException(e); - } - // load using PBJ - try { - TEST_BLOCK = com.hedera.hapi.block.stream.Block.PROTOBUF.parse(Bytes.wrap(TEST_BLOCK_PROTOBUF_BYTES)); - } catch (ParseException e) { - throw new RuntimeException(e); - } - // load using google protoc as well - try { - TEST_BLOCK_GOOGLE = Block.parseFrom(TEST_BLOCK_PROTOBUF_BYTES); - } catch (IOException e) { - throw new RuntimeException(e); - } - // input buffers - PROTOBUF_BYTE_BUFFER = ByteBuffer.wrap(TEST_BLOCK_PROTOBUF_BYTES); - PROTOBUF_DATA_BUFFER = BufferedData.wrap(TEST_BLOCK_PROTOBUF_BYTES); - PROTOBUF_BYTE_BUFFER_DIRECT = ByteBuffer.allocateDirect(TEST_BLOCK_PROTOBUF_BYTES.length); - PROTOBUF_BYTE_BUFFER_DIRECT.put(TEST_BLOCK_PROTOBUF_BYTES); - PROTOBUF_DATA_BUFFER_DIRECT = BufferedData.wrap(PROTOBUF_BYTE_BUFFER_DIRECT); - PROTOBUF_INPUT_STREAM = new NonSynchronizedByteArrayInputStream(TEST_BLOCK_PROTOBUF_BYTES); - ReadableStreamingData din = new ReadableStreamingData(PROTOBUF_INPUT_STREAM); - } - - // output buffers - private final NonSynchronizedByteArrayOutputStream bout = new NonSynchronizedByteArrayOutputStream(); - private final BufferedData outDataBuffer = BufferedData.allocate(TEST_BLOCK_PROTOBUF_BYTES.length); - private final BufferedData outDataBufferDirect = BufferedData.allocateOffHeap(TEST_BLOCK_PROTOBUF_BYTES.length); - private final ByteBuffer bbout = ByteBuffer.allocate(TEST_BLOCK_PROTOBUF_BYTES.length); - private final ByteBuffer bboutDirect = ByteBuffer.allocateDirect(TEST_BLOCK_PROTOBUF_BYTES.length); - - /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - public void parsePbjByteArray(Blackhole blackhole) throws ParseException { - PROTOBUF_DATA_BUFFER.resetPosition(); - blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER)); - } - - @Benchmark - public void parsePbjByteBuffer(Blackhole blackhole) throws ParseException { - PROTOBUF_DATA_BUFFER.resetPosition(); - blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER)); - } - - @Benchmark - public void parsePbjByteBufferDirect(Blackhole blackhole) - throws ParseException { - PROTOBUF_DATA_BUFFER_DIRECT.resetPosition(); - blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER_DIRECT)); - } - - @Benchmark - public void parsePbjInputStream(Blackhole blackhole) throws ParseException { - PROTOBUF_INPUT_STREAM.resetPosition(); - blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(new ReadableStreamingData(PROTOBUF_INPUT_STREAM))); - } - - @Benchmark - public void parseProtoCByteArray(Blackhole blackhole) throws IOException { - blackhole.consume(Block.parseFrom(TEST_BLOCK_PROTOBUF_BYTES)); - } - - @Benchmark - public void parseProtoCByteBufferDirect(Blackhole blackhole) throws IOException { - PROTOBUF_BYTE_BUFFER_DIRECT.position(0); - blackhole.consume(Block.parseFrom(PROTOBUF_BYTE_BUFFER_DIRECT)); - } - - @Benchmark - public void parseProtoCByteBuffer(Blackhole blackhole) throws IOException { - blackhole.consume(Block.parseFrom(PROTOBUF_BYTE_BUFFER)); - } - - @Benchmark - public void parseProtoCInputStream(Blackhole blackhole) throws IOException { - PROTOBUF_INPUT_STREAM.resetPosition(); - blackhole.consume(Block.parseFrom(PROTOBUF_INPUT_STREAM)); - } - - /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ - @Benchmark - public void writePbjByteArray(Blackhole blackhole) throws IOException { - outDataBuffer.reset(); - com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBuffer); - blackhole.consume(outDataBuffer); - } - - /** Added as should be same as above but creates new byte[] and does extra measure. But this is used a lot */ - @Benchmark - public void writePbjToBytes(Blackhole blackhole) { - final Bytes bytes = com.hedera.hapi.block.stream.Block.PROTOBUF.toBytes(TEST_BLOCK); - blackhole.consume(bytes); - } - - @Benchmark - public void writePbjByteBuffer(Blackhole blackhole) throws IOException { - outDataBuffer.reset(); - com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBuffer); - blackhole.consume(outDataBuffer); - } - - @Benchmark - public void writePbjByteDirect(Blackhole blackhole) throws IOException { - outDataBufferDirect.reset(); - com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBufferDirect); - blackhole.consume(outDataBufferDirect); - } - - @Benchmark - public void writePbjOutputStream(Blackhole blackhole) throws IOException { - bout.reset(); - com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, new WritableStreamingData(bout)); - blackhole.consume(bout.toByteArray()); - } - - @Benchmark - public void writeProtoCByteArray(Blackhole blackhole) { - blackhole.consume(TEST_BLOCK_GOOGLE.toByteArray()); - } - - @Benchmark - public void writeProtoCByteBuffer(Blackhole blackhole) throws IOException { - CodedOutputStream cout = CodedOutputStream.newInstance(bbout); - TEST_BLOCK_GOOGLE.writeTo(cout); - blackhole.consume(bbout); - } - - @Benchmark - public void writeProtoCByteBufferDirect(Blackhole blackhole) throws IOException { - CodedOutputStream cout = CodedOutputStream.newInstance(bboutDirect); - TEST_BLOCK_GOOGLE.writeTo(cout); - blackhole.consume(bbout); - } - - @Benchmark - public void writeProtoCOutputStream(Blackhole blackhole) throws IOException { - bout.reset(); - TEST_BLOCK_GOOGLE.writeTo(bout); - blackhole.consume(bout.toByteArray()); - } - - /** - * Handy test main method for performance profiling - * - * @param args no args needed - */ - public static void main(String[] args) { - for (int i = 0; i < 1000; i++) { - final Bytes result = com.hedera.hapi.block.stream.Block.PROTOBUF.toBytes(TEST_BLOCK); -// TEST_BLOCK_GOOGLE.toByteArray(); - } -// var biggsetItem = TEST_BLOCK.items().stream().sorted(Comparator.comparingLong(BlockItem.PROTOBUF::measureRecord)).toList().getLast(); -// final Bytes result = com.hedera.hapi.block.stream.BlockItem.PROTOBUF.toBytes(biggsetItem); - - } + // test block + private static final com.hedera.hapi.block.stream.Block TEST_BLOCK; + private static final Block TEST_BLOCK_GOOGLE; + // input bytes + private static final byte[] TEST_BLOCK_PROTOBUF_BYTES; + private static final ByteBuffer PROTOBUF_BYTE_BUFFER; + private static final BufferedData PROTOBUF_DATA_BUFFER; + private static final ByteBuffer PROTOBUF_BYTE_BUFFER_DIRECT; + private static final BufferedData PROTOBUF_DATA_BUFFER_DIRECT; + private static final NonSynchronizedByteArrayInputStream PROTOBUF_INPUT_STREAM; + // load test block from resources + static { + // load the protobuf bytes + try (var in = new BufferedInputStream(new GZIPInputStream(Objects.requireNonNull( + SampleBlockBench.class.getResourceAsStream("/000000000000000000000000000000497558.blk.gz"))))) { + TEST_BLOCK_PROTOBUF_BYTES = in.readAllBytes(); + } catch (IOException e) { + throw new RuntimeException(e); + } + // load using PBJ + try { + TEST_BLOCK = com.hedera.hapi.block.stream.Block.PROTOBUF.parse(Bytes.wrap(TEST_BLOCK_PROTOBUF_BYTES)); + } catch (ParseException e) { + throw new RuntimeException(e); + } + // load using google protoc as well + try { + TEST_BLOCK_GOOGLE = Block.parseFrom(TEST_BLOCK_PROTOBUF_BYTES); + } catch (IOException e) { + throw new RuntimeException(e); + } + // input buffers + PROTOBUF_BYTE_BUFFER = ByteBuffer.wrap(TEST_BLOCK_PROTOBUF_BYTES); + PROTOBUF_DATA_BUFFER = BufferedData.wrap(TEST_BLOCK_PROTOBUF_BYTES); + PROTOBUF_BYTE_BUFFER_DIRECT = ByteBuffer.allocateDirect(TEST_BLOCK_PROTOBUF_BYTES.length); + PROTOBUF_BYTE_BUFFER_DIRECT.put(TEST_BLOCK_PROTOBUF_BYTES); + PROTOBUF_DATA_BUFFER_DIRECT = BufferedData.wrap(PROTOBUF_BYTE_BUFFER_DIRECT); + PROTOBUF_INPUT_STREAM = new NonSynchronizedByteArrayInputStream(TEST_BLOCK_PROTOBUF_BYTES); + ReadableStreamingData din = new ReadableStreamingData(PROTOBUF_INPUT_STREAM); + } + + // output buffers + private final NonSynchronizedByteArrayOutputStream bout = new NonSynchronizedByteArrayOutputStream(); + private final BufferedData outDataBuffer = BufferedData.allocate(TEST_BLOCK_PROTOBUF_BYTES.length); + private final BufferedData outDataBufferDirect = BufferedData.allocateOffHeap(TEST_BLOCK_PROTOBUF_BYTES.length); + private final ByteBuffer bbout = ByteBuffer.allocate(TEST_BLOCK_PROTOBUF_BYTES.length); + private final ByteBuffer bboutDirect = ByteBuffer.allocateDirect(TEST_BLOCK_PROTOBUF_BYTES.length); + + /** Same as parsePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + public void parsePbjByteArray(Blackhole blackhole) throws ParseException { + PROTOBUF_DATA_BUFFER.resetPosition(); + blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER)); + } + + @Benchmark + public void parsePbjByteBuffer(Blackhole blackhole) throws ParseException { + PROTOBUF_DATA_BUFFER.resetPosition(); + blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER)); + } + + @Benchmark + public void parsePbjByteBufferDirect(Blackhole blackhole) throws ParseException { + PROTOBUF_DATA_BUFFER_DIRECT.resetPosition(); + blackhole.consume(com.hedera.hapi.block.stream.Block.PROTOBUF.parse(PROTOBUF_DATA_BUFFER_DIRECT)); + } + + @Benchmark + public void parsePbjInputStream(Blackhole blackhole) throws ParseException { + PROTOBUF_INPUT_STREAM.resetPosition(); + blackhole.consume( + com.hedera.hapi.block.stream.Block.PROTOBUF.parse(new ReadableStreamingData(PROTOBUF_INPUT_STREAM))); + } + + @Benchmark + public void parseProtoCByteArray(Blackhole blackhole) throws IOException { + blackhole.consume(Block.parseFrom(TEST_BLOCK_PROTOBUF_BYTES)); + } + + @Benchmark + public void parseProtoCByteBufferDirect(Blackhole blackhole) throws IOException { + PROTOBUF_BYTE_BUFFER_DIRECT.position(0); + blackhole.consume(Block.parseFrom(PROTOBUF_BYTE_BUFFER_DIRECT)); + } + + @Benchmark + public void parseProtoCByteBuffer(Blackhole blackhole) throws IOException { + blackhole.consume(Block.parseFrom(PROTOBUF_BYTE_BUFFER)); + } + + @Benchmark + public void parseProtoCInputStream(Blackhole blackhole) throws IOException { + PROTOBUF_INPUT_STREAM.resetPosition(); + blackhole.consume(Block.parseFrom(PROTOBUF_INPUT_STREAM)); + } + + /** Same as writePbjByteBuffer because DataBuffer.wrap(byte[]) uses ByteBuffer today, added this because makes result plotting easier */ + @Benchmark + public void writePbjByteArray(Blackhole blackhole) throws IOException { + outDataBuffer.reset(); + com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBuffer); + blackhole.consume(outDataBuffer); + } + + /** Added as should be same as above but creates new byte[] and does extra measure. But this is used a lot */ + @Benchmark + public void writePbjToBytes(Blackhole blackhole) { + final Bytes bytes = com.hedera.hapi.block.stream.Block.PROTOBUF.toBytes(TEST_BLOCK); + blackhole.consume(bytes); + } + + @Benchmark + public void writePbjByteBuffer(Blackhole blackhole) throws IOException { + outDataBuffer.reset(); + com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBuffer); + blackhole.consume(outDataBuffer); + } + + @Benchmark + public void writePbjByteDirect(Blackhole blackhole) throws IOException { + outDataBufferDirect.reset(); + com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, outDataBufferDirect); + blackhole.consume(outDataBufferDirect); + } + + @Benchmark + public void writePbjOutputStream(Blackhole blackhole) throws IOException { + bout.reset(); + com.hedera.hapi.block.stream.Block.PROTOBUF.write(TEST_BLOCK, new WritableStreamingData(bout)); + blackhole.consume(bout.toByteArray()); + } + + @Benchmark + public void writeProtoCByteArray(Blackhole blackhole) { + blackhole.consume(TEST_BLOCK_GOOGLE.toByteArray()); + } + + @Benchmark + public void writeProtoCByteBuffer(Blackhole blackhole) throws IOException { + CodedOutputStream cout = CodedOutputStream.newInstance(bbout); + TEST_BLOCK_GOOGLE.writeTo(cout); + blackhole.consume(bbout); + } + + @Benchmark + public void writeProtoCByteBufferDirect(Blackhole blackhole) throws IOException { + CodedOutputStream cout = CodedOutputStream.newInstance(bboutDirect); + TEST_BLOCK_GOOGLE.writeTo(cout); + blackhole.consume(bbout); + } + + @Benchmark + public void writeProtoCOutputStream(Blackhole blackhole) throws IOException { + bout.reset(); + TEST_BLOCK_GOOGLE.writeTo(bout); + blackhole.consume(bout.toByteArray()); + } + + /** + * Handy test main method for performance profiling + * + * @param args no args needed + */ + public static void main(String[] args) { + for (int i = 0; i < 1000; i++) { + final Bytes result = com.hedera.hapi.block.stream.Block.PROTOBUF.toBytes(TEST_BLOCK); + // TEST_BLOCK_GOOGLE.toByteArray(); + } + // var biggsetItem = + // TEST_BLOCK.items().stream().sorted(Comparator.comparingLong(BlockItem.PROTOBUF::measureRecord)).toList().getLast(); + // final Bytes result = com.hedera.hapi.block.stream.BlockItem.PROTOBUF.toBytes(biggsetItem); + + } } diff --git a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/VarIntBench.java b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/VarIntBench.java index 4ae4a8f2..1fab7834 100644 --- a/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/VarIntBench.java +++ b/pbj-integration-tests/src/jmh/java/com/hedera/pbj/integration/jmh/VarIntBench.java @@ -9,15 +9,14 @@ import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.hedera.pbj.runtime.io.stream.ReadableStreamingData; -import java.io.InputStream; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; - import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.*; import java.util.Random; import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; @SuppressWarnings("unused") @State(Scope.Benchmark) @@ -28,233 +27,232 @@ @BenchmarkMode(Mode.AverageTime) public class VarIntBench { - ByteBuffer buffer = ByteBuffer.allocate(256*1024); - final ByteBuffer bufferDirect = ByteBuffer.allocateDirect(256*1024); - final BufferedData dataBuffer = BufferedData.wrap(buffer); - final BufferedData dataBufferDirect = BufferedData.wrap(bufferDirect); - - Bytes bytes = Bytes.EMPTY; + ByteBuffer buffer = ByteBuffer.allocate(256 * 1024); + final ByteBuffer bufferDirect = ByteBuffer.allocateDirect(256 * 1024); + final BufferedData dataBuffer = BufferedData.wrap(buffer); + final BufferedData dataBufferDirect = BufferedData.wrap(bufferDirect); - InputStream bais = null; - ReadableStreamingData rsd = null; + Bytes bytes = Bytes.EMPTY; - InputStream baisNonSync = null; - ReadableStreamingData rsdNonSync = null; + InputStream bais = null; + ReadableStreamingData rsd = null; - private final int[] offsets = new int[1201]; + InputStream baisNonSync = null; + ReadableStreamingData rsdNonSync = null; - public VarIntBench() { - try { - CodedOutputStream cout = CodedOutputStream.newInstance(buffer); - Random random = new Random(9387498731984L); - int pos = 0; - offsets[pos++] = 0; - for (int i = 0; i < 600; i++) { - cout.writeUInt64NoTag(random.nextLong(0,128)); - offsets[pos++] = cout.getTotalBytesWritten(); - } - for (int i = 0; i < 150; i++) { - cout.writeUInt64NoTag(random.nextLong(128,256)); - offsets[pos++] = cout.getTotalBytesWritten(); - } - for (int i = 0; i < 150; i++) { - cout.writeUInt64NoTag(random.nextLong(256, Integer.MAX_VALUE)); - offsets[pos++] = cout.getTotalBytesWritten(); - } - for (int i = 0; i < 150; i++) { - cout.writeUInt64NoTag(random.nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE)); - offsets[pos++] = cout.getTotalBytesWritten(); - } - for (int i = 0; i < 150; i++) { - cout.writeUInt64NoTag(random.nextLong(0, Long.MAX_VALUE)); - offsets[pos++] = cout.getTotalBytesWritten(); - } - cout.flush(); - // copy to direct buffer - buffer.flip(); - bufferDirect.put(buffer); - byte[] bts = new byte[buffer.limit()]; - for (int i = 0; i < buffer.limit(); i++) { - bts[i] = buffer.get(i); - } - bytes = Bytes.wrap(bts); - bais = new ByteArrayInputStream(bts.clone()); - rsd = new ReadableStreamingData(bais); - baisNonSync = new NonSynchronizedByteArrayInputStream(bts.clone()); - rsdNonSync = new ReadableStreamingData(baisNonSync); - } catch (IOException e){ - e.printStackTrace(); - } - } + private final int[] offsets = new int[1201]; - @Benchmark - @OperationsPerInvocation(1200) - public void dataBufferRead(Blackhole blackhole) throws IOException { - dataBuffer.reset(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(dataBuffer.readVarLong(false)); - } - } + public VarIntBench() { + try { + CodedOutputStream cout = CodedOutputStream.newInstance(buffer); + Random random = new Random(9387498731984L); + int pos = 0; + offsets[pos++] = 0; + for (int i = 0; i < 600; i++) { + cout.writeUInt64NoTag(random.nextLong(0, 128)); + offsets[pos++] = cout.getTotalBytesWritten(); + } + for (int i = 0; i < 150; i++) { + cout.writeUInt64NoTag(random.nextLong(128, 256)); + offsets[pos++] = cout.getTotalBytesWritten(); + } + for (int i = 0; i < 150; i++) { + cout.writeUInt64NoTag(random.nextLong(256, Integer.MAX_VALUE)); + offsets[pos++] = cout.getTotalBytesWritten(); + } + for (int i = 0; i < 150; i++) { + cout.writeUInt64NoTag(random.nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE)); + offsets[pos++] = cout.getTotalBytesWritten(); + } + for (int i = 0; i < 150; i++) { + cout.writeUInt64NoTag(random.nextLong(0, Long.MAX_VALUE)); + offsets[pos++] = cout.getTotalBytesWritten(); + } + cout.flush(); + // copy to direct buffer + buffer.flip(); + bufferDirect.put(buffer); + byte[] bts = new byte[buffer.limit()]; + for (int i = 0; i < buffer.limit(); i++) { + bts[i] = buffer.get(i); + } + bytes = Bytes.wrap(bts); + bais = new ByteArrayInputStream(bts.clone()); + rsd = new ReadableStreamingData(bais); + baisNonSync = new NonSynchronizedByteArrayInputStream(bts.clone()); + rsdNonSync = new ReadableStreamingData(baisNonSync); + } catch (IOException e) { + e.printStackTrace(); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void dataBufferGet(Blackhole blackhole) throws IOException { - dataBuffer.reset(); - int offset = 0; - for (int i = 0; i < 1200; i++) { - blackhole.consume(dataBuffer.getVarLong(offsets[offset++], false)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataBufferRead(Blackhole blackhole) throws IOException { + dataBuffer.reset(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(dataBuffer.readVarLong(false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void dataBufferDirectRead(Blackhole blackhole) throws IOException { - dataBufferDirect.reset(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(dataBufferDirect.readVarLong(false)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataBufferGet(Blackhole blackhole) throws IOException { + dataBuffer.reset(); + int offset = 0; + for (int i = 0; i < 1200; i++) { + blackhole.consume(dataBuffer.getVarLong(offsets[offset++], false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void dataBytesGet(Blackhole blackhole) throws IOException { - int offset = 0; - for (int i = 0; i < 1200; i++) { - blackhole.consume(bytes.getVarLong(offsets[offset++], false)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataBufferDirectRead(Blackhole blackhole) throws IOException { + dataBufferDirect.reset(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(dataBufferDirect.readVarLong(false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void dataSyncInputStreamRead(Blackhole blackhole) throws IOException { - bais.reset(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(rsd.readVarLong(false)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataBytesGet(Blackhole blackhole) throws IOException { + int offset = 0; + for (int i = 0; i < 1200; i++) { + blackhole.consume(bytes.getVarLong(offsets[offset++], false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void dataNonSyncInputStreamRead(Blackhole blackhole) throws IOException { - baisNonSync.reset(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(rsdNonSync.readVarLong(false)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataSyncInputStreamRead(Blackhole blackhole) throws IOException { + bais.reset(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(rsd.readVarLong(false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void richardGet(Blackhole blackhole) throws MalformedProtobufException { - int offset = 0; - buffer.clear(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(getVarLongRichard(offsets[offset++], buffer)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void dataNonSyncInputStreamRead(Blackhole blackhole) throws IOException { + baisNonSync.reset(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(rsdNonSync.readVarLong(false)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void googleRead(Blackhole blackhole) throws IOException { - buffer.clear(); - final CodedInputStream codedInputStream = CodedInputStream.newInstance(buffer); - for (int i = 0; i < 1200; i++) { - blackhole.consume(codedInputStream.readRawVarint64()); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void richardGet(Blackhole blackhole) throws MalformedProtobufException { + int offset = 0; + buffer.clear(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(getVarLongRichard(offsets[offset++], buffer)); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void googleDirecRead(Blackhole blackhole) throws IOException { - bufferDirect.clear(); - final CodedInputStream codedInputStream = CodedInputStream.newInstance(bufferDirect); - for (int i = 0; i < 1200; i++) { - blackhole.consume(codedInputStream.readRawVarint64()); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void googleRead(Blackhole blackhole) throws IOException { + buffer.clear(); + final CodedInputStream codedInputStream = CodedInputStream.newInstance(buffer); + for (int i = 0; i < 1200; i++) { + blackhole.consume(codedInputStream.readRawVarint64()); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void googleSlowPathRead(Blackhole blackhole) throws MalformedProtobufException { - buffer.clear(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(readRawVarint64SlowPath(buffer)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void googleDirecRead(Blackhole blackhole) throws IOException { + bufferDirect.clear(); + final CodedInputStream codedInputStream = CodedInputStream.newInstance(bufferDirect); + for (int i = 0; i < 1200; i++) { + blackhole.consume(codedInputStream.readRawVarint64()); + } + } - @Benchmark - @OperationsPerInvocation(1200) - public void googleSlowPathDirectRead(Blackhole blackhole) throws MalformedProtobufException { - bufferDirect.clear(); - for (int i = 0; i < 1200; i++) { - blackhole.consume(readRawVarint64SlowPath(bufferDirect)); - } - } + @Benchmark + @OperationsPerInvocation(1200) + public void googleSlowPathRead(Blackhole blackhole) throws MalformedProtobufException { + buffer.clear(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(readRawVarint64SlowPath(buffer)); + } + } - private static long readRawVarint64SlowPath(ByteBuffer buf) throws MalformedProtobufException { - long result = 0; - for (int shift = 0; shift < 64; shift += 7) { - final byte b = buf.get(); - result |= (long) (b & 0x7F) << shift; - if ((b & 0x80) == 0) { - return result; - } - } - throw new MalformedProtobufException("Malformed varInt"); - } + @Benchmark + @OperationsPerInvocation(1200) + public void googleSlowPathDirectRead(Blackhole blackhole) throws MalformedProtobufException { + bufferDirect.clear(); + for (int i = 0; i < 1200; i++) { + blackhole.consume(readRawVarint64SlowPath(bufferDirect)); + } + } + private static long readRawVarint64SlowPath(ByteBuffer buf) throws MalformedProtobufException { + long result = 0; + for (int shift = 0; shift < 64; shift += 7) { + final byte b = buf.get(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + } + throw new MalformedProtobufException("Malformed varInt"); + } - private static final int VARINT_CONTINUATION_MASK = 0b1000_0000; - private static final int VARINT_DATA_MASK = 0b0111_1111; - private static final int NUM_BITS_PER_VARINT_BYTE = 7; + private static final int VARINT_CONTINUATION_MASK = 0b1000_0000; + private static final int VARINT_DATA_MASK = 0b0111_1111; + private static final int NUM_BITS_PER_VARINT_BYTE = 7; - public static long getVarLongRichard(int offset, ByteBuffer buf) throws MalformedProtobufException { - // Protobuf encodes smaller integers with fewer bytes than larger integers. It takes a full byte - // to encode 7 bits of information. So, if all 64 bits of a long are in use (for example, if the - // leading bit is 1, or even all bits are 1) then it will take 10 bytes to transmit what would - // have otherwise been 8 bytes of data! - // - // Thus, at most, reading a varint should involve reading 10 bytes of data. - // - // The leading bit of each byte is a continuation bit. If set, another byte will follow. - // If we read 10 bytes in sequence with a continuation bit set, then we have a malformed - // byte stream. - // The bytes come least to most significant 7 bits. So the first byte we read represents - // the lowest 7 bytes, then the next byte is the next highest 7 bytes, etc. + public static long getVarLongRichard(int offset, ByteBuffer buf) throws MalformedProtobufException { + // Protobuf encodes smaller integers with fewer bytes than larger integers. It takes a full byte + // to encode 7 bits of information. So, if all 64 bits of a long are in use (for example, if the + // leading bit is 1, or even all bits are 1) then it will take 10 bytes to transmit what would + // have otherwise been 8 bytes of data! + // + // Thus, at most, reading a varint should involve reading 10 bytes of data. + // + // The leading bit of each byte is a continuation bit. If set, another byte will follow. + // If we read 10 bytes in sequence with a continuation bit set, then we have a malformed + // byte stream. + // The bytes come least to most significant 7 bits. So the first byte we read represents + // the lowest 7 bytes, then the next byte is the next highest 7 bytes, etc. - // The final value. - long value = 0; - // The amount to shift the bits we read by before AND with the value - int shift = -NUM_BITS_PER_VARINT_BYTE; + // The final value. + long value = 0; + // The amount to shift the bits we read by before AND with the value + int shift = -NUM_BITS_PER_VARINT_BYTE; - // This method works with heap byte buffers only - final byte[] arr = buf.array(); - final int arrOffset = buf.arrayOffset() + offset; + // This method works with heap byte buffers only + final byte[] arr = buf.array(); + final int arrOffset = buf.arrayOffset() + offset; - int i = 0; - for (; i < 10; i++) { - // Use UnsafeUtil instead of arr[arrOffset + i] to avoid array range checks - byte b = UnsafeUtils.getArrayByteNoChecks(arr, arrOffset + i); - value |= (long) (b & 0x7F) << (shift += NUM_BITS_PER_VARINT_BYTE); + int i = 0; + for (; i < 10; i++) { + // Use UnsafeUtil instead of arr[arrOffset + i] to avoid array range checks + byte b = UnsafeUtils.getArrayByteNoChecks(arr, arrOffset + i); + value |= (long) (b & 0x7F) << (shift += NUM_BITS_PER_VARINT_BYTE); - if (b >= 0) { - return value; - } - } - // If we read 10 in a row all with the leading continuation bit set, then throw a malformed - // protobuf exception - throw new MalformedProtobufException("Malformed var int"); - } + if (b >= 0) { + return value; + } + } + // If we read 10 in a row all with the leading continuation bit set, then throw a malformed + // protobuf exception + throw new MalformedProtobufException("Malformed var int"); + } - public static void main(String[] args) throws Exception { - final Blackhole blackhole = new Blackhole( - "Today's password is swordfish. I understand instantiating Blackholes directly is dangerous."); - final VarIntBench bench = new VarIntBench(); - bench.dataBufferRead(blackhole); - bench.dataBufferGet(blackhole); - bench.dataBufferDirectRead(blackhole); - bench.dataBytesGet(blackhole); - bench.dataSyncInputStreamRead(blackhole); - bench.dataNonSyncInputStreamRead(blackhole); - bench.googleRead(blackhole); - } + public static void main(String[] args) throws Exception { + final Blackhole blackhole = new Blackhole( + "Today's password is swordfish. I understand instantiating Blackholes directly is dangerous."); + final VarIntBench bench = new VarIntBench(); + bench.dataBufferRead(blackhole); + bench.dataBufferGet(blackhole); + bench.dataBufferDirectRead(blackhole); + bench.dataBytesGet(blackhole); + bench.dataSyncInputStreamRead(blackhole); + bench.dataNonSyncInputStreamRead(blackhole); + bench.googleRead(blackhole); + } } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsPbj.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsPbj.java index 84a82b78..f6699b55 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsPbj.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsPbj.java @@ -7,7 +7,6 @@ import com.hedera.hapi.node.token.GrantedNftAllowance; import com.hedera.hapi.node.token.GrantedTokenAllowance; import com.hedera.pbj.runtime.io.buffer.Bytes; - import java.util.List; import java.util.Random; @@ -22,112 +21,128 @@ public class AccountDetailsPbj { /** * Sample test object for JMH benchmarks */ - public static final AccountDetails ACCOUNT_DETAILS = - new AccountDetails.Builder() - .accountId(new AccountID.Builder() - .shardNum(0) - .realmNum(0) - .accountNum(posLong()) - .build()) - .contractAccountId(randomHex(64)) - .deleted(false) - .proxyAccountId(new AccountID.Builder() - .shardNum(0) - .realmNum(0) - .accountNum(posLong()) - .alias(randomBytes(32)) - .build()) - .proxyReceived(RANDOM.nextLong()) - .key(new Key.Builder() - .keyList(new KeyList.Builder() - .keys(List.of( - new Key.Builder() - .ed25519(randomBytes(32)) - .build(), - new Key.Builder() - .ecdsa384(randomBytes(48)) - .build(), - new Key.Builder() - .contractID(new ContractID.Builder() - .shardNum(0) - .realmNum(0) - .contractNum(posLong()) - .build()) - .build() - )) - .build()) - .build()) - .balance(RANDOM.nextLong()) - .receiverSigRequired(true) - .expirationTime(new Timestamp.Builder() - .nanos(RANDOM.nextInt(0, Integer.MAX_VALUE)) - .seconds(RANDOM.nextLong(0, Long.MAX_VALUE)) - .build()) - .autoRenewPeriod(new Duration.Builder() - .seconds(RANDOM.nextLong(0, Long.MAX_VALUE)) + public static final AccountDetails ACCOUNT_DETAILS = new AccountDetails.Builder() + .accountId(new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) + .build()) + .contractAccountId(randomHex(64)) + .deleted(false) + .proxyAccountId(new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) + .alias(randomBytes(32)) + .build()) + .proxyReceived(RANDOM.nextLong()) + .key(new Key.Builder() + .keyList(new KeyList.Builder() + .keys(List.of( + new Key.Builder().ed25519(randomBytes(32)).build(), + new Key.Builder().ecdsa384(randomBytes(48)).build(), + new Key.Builder() + .contractID(new ContractID.Builder() + .shardNum(0) + .realmNum(0) + .contractNum(posLong()) + .build()) + .build())) .build()) - .tokenRelationships(List.of( - new TokenRelationship.Builder() - .balance(RANDOM.nextLong(1, Long.MAX_VALUE)) - .decimals(RANDOM.nextInt(0, Integer.MAX_VALUE)) - .automaticAssociation(true) - .symbol(randomHex(3)) - .tokenId(new TokenID(posLong(),posLong(),posLong())) + .build()) + .balance(RANDOM.nextLong()) + .receiverSigRequired(true) + .expirationTime(new Timestamp.Builder() + .nanos(RANDOM.nextInt(0, Integer.MAX_VALUE)) + .seconds(RANDOM.nextLong(0, Long.MAX_VALUE)) + .build()) + .autoRenewPeriod(new Duration.Builder() + .seconds(RANDOM.nextLong(0, Long.MAX_VALUE)) + .build()) + .tokenRelationships(List.of( + new TokenRelationship.Builder() + .balance(RANDOM.nextLong(1, Long.MAX_VALUE)) + .decimals(RANDOM.nextInt(0, Integer.MAX_VALUE)) + .automaticAssociation(true) + .symbol(randomHex(3)) + .tokenId(new TokenID(posLong(), posLong(), posLong())) + .build(), + new TokenRelationship.Builder() + .balance(RANDOM.nextLong(1, Long.MAX_VALUE)) + .decimals(RANDOM.nextInt(0, Integer.MAX_VALUE)) + .automaticAssociation(true) + .symbol(randomHex(3)) + .tokenId(new TokenID(posLong(), posLong(), posLong())) + .build())) + .memo(randomHex(80)) + .ownedNfts(RANDOM.nextLong(10, Integer.MAX_VALUE)) + .maxAutomaticTokenAssociations(RANDOM.nextInt(10, Integer.MAX_VALUE)) + .alias(randomBytes(32)) + .ledgerId(randomBytes(32)) + .grantedCryptoAllowances(List.of( + new GrantedCryptoAllowance( + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) .build(), - new TokenRelationship.Builder() - .balance(RANDOM.nextLong(1, Long.MAX_VALUE)) - .decimals(RANDOM.nextInt(0, Integer.MAX_VALUE)) - .automaticAssociation(true) - .symbol(randomHex(3)) - .tokenId(new TokenID(posLong(),posLong(),posLong())) - .build() - )) - .memo(randomHex(80)) - .ownedNfts(RANDOM.nextLong(10, Integer.MAX_VALUE)) - .maxAutomaticTokenAssociations(RANDOM.nextInt(10, Integer.MAX_VALUE)) - .alias(randomBytes(32)) - .ledgerId(randomBytes(32)) - .grantedCryptoAllowances(List.of( - new GrantedCryptoAllowance(new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) - .build() - ,posLong()), - new GrantedCryptoAllowance(new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) - .build() - ,posLong()) - )) - .grantedNftAllowances(List.of( - new GrantedNftAllowance(new TokenID.Builder() - .shardNum(0).realmNum(0).tokenNum(posLong()) - .build() - ,new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) + posLong()), + new GrantedCryptoAllowance( + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) + .build(), + posLong()))) + .grantedNftAllowances(List.of( + new GrantedNftAllowance( + new TokenID.Builder() + .shardNum(0) + .realmNum(0) + .tokenNum(posLong()) + .build(), + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) .build()), - new GrantedNftAllowance(new TokenID.Builder() - .shardNum(0).realmNum(0).tokenNum(posLong()) - .build() - ,new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) - .build()) - )) - .grantedTokenAllowances(List.of( - new GrantedTokenAllowance(new TokenID.Builder() - .shardNum(0).realmNum(0).tokenNum(posLong()) - .build() - ,new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) + new GrantedNftAllowance( + new TokenID.Builder() + .shardNum(0) + .realmNum(0) + .tokenNum(posLong()) + .build(), + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) + .build()))) + .grantedTokenAllowances(List.of( + new GrantedTokenAllowance( + new TokenID.Builder() + .shardNum(0) + .realmNum(0) + .tokenNum(posLong()) + .build(), + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) + .build(), + posLong()), + new GrantedTokenAllowance( + new TokenID.Builder() + .shardNum(0) + .realmNum(0) + .tokenNum(posLong()) .build(), - posLong()), - new GrantedTokenAllowance(new TokenID.Builder() - .shardNum(0).realmNum(0).tokenNum(posLong()) - .build() - ,new AccountID.Builder() - .shardNum(0).realmNum(0).accountNum(posLong()) + new AccountID.Builder() + .shardNum(0) + .realmNum(0) + .accountNum(posLong()) .build(), - posLong()) - )) - .build(); + posLong()))) + .build(); /** * Empty constructor @@ -149,7 +164,7 @@ private static Bytes randomBytes(int size) { private static String randomHex(int size) { final StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { - sb.append(Integer.toHexString(RANDOM.nextInt(0,15))); + sb.append(Integer.toHexString(RANDOM.nextInt(0, 15))); } return sb.toString(); } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsWriter.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsWriter.java index df389188..27112f7d 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsWriter.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/AccountDetailsWriter.java @@ -1,11 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration; +import static com.hedera.pbj.integration.AccountDetailsPbj.ACCOUNT_DETAILS; + import com.hedera.hapi.node.token.AccountDetails; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hederahashgraph.api.proto.java.GetAccountDetailsResponse; import java.util.Arrays; -import static com.hedera.pbj.integration.AccountDetailsPbj.ACCOUNT_DETAILS; /** * Testing main class for profiling parser and writer performance @@ -27,7 +28,7 @@ public AccountDetailsWriter() { * @throws Exception if there was a problem */ public static void main(String[] args) throws Exception { - final BufferedData outDataBuffer = BufferedData.allocate(1024*1024); + final BufferedData outDataBuffer = BufferedData.allocate(1024 * 1024); for (int i = 0; i < 10_000_000; i++) { outDataBuffer.reset(); @@ -52,12 +53,13 @@ public static void main2(String[] args) throws Exception { final byte[] protobuf = new byte[(int) tempDataBuffer.remaining()]; tempDataBuffer.readBytes(protobuf); // write out with protoc - final GetAccountDetailsResponse.AccountDetails accountDetailsProtoC = GetAccountDetailsResponse.AccountDetails.parseFrom(protobuf); -// -// final ByteBuffer bbout = ByteBuffer.allocate(1024*1024); + final GetAccountDetailsResponse.AccountDetails accountDetailsProtoC = + GetAccountDetailsResponse.AccountDetails.parseFrom(protobuf); + // + // final ByteBuffer bbout = ByteBuffer.allocate(1024*1024); for (int i = 0; i < 10_000_000; i++) { -// bbout.clear(); + // bbout.clear(); final byte[] writtenData = accountDetailsProtoC.toByteArray(); if (writtenData.length != protobuf.length) { System.out.println("writtenData = " + Arrays.toString(writtenData)); diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingTestData.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingTestData.java index 1cf9f05a..5c2d378f 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingTestData.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingTestData.java @@ -40,39 +40,37 @@ public EverythingTestData() { .doubleNumber(135581531681.1535151) .booleanField(true) .enumSuit(Suit.SPADES) - .subObject(new TimestampTest.Builder().seconds(5155135L).nanos(44513).build()) + .subObject( + new TimestampTest.Builder().seconds(5155135L).nanos(44513).build()) .text("Hello Everything!") - .bytesField(Bytes.wrap(new byte[]{12,29,19,120,127,0,-127})) - .int32NumberList(IntStream.range(0,10).boxed().toList()) - .sint32NumberList(IntStream.range(-10,10).boxed().toList()) - .uint32NumberList(IntStream.range(0,100).boxed().toList()) - .fixed32NumberList(IntStream.range(0,25).boxed().toList()) - .sfixed32NumberList(IntStream.range(-10,25).boxed().toList()) - .floatNumberList(List.of(513.51f,55535351.3545841f,0f,-1f)) - .floatNumberList(List.of(513.51f,55535351.3545841f,0f,-1f)) - .int64NumberList(LongStream.range(0,10).boxed().toList()) - .sint64NumberList(LongStream.range(-10,10).boxed().toList()) - .uint64NumberList(LongStream.range(0,10).boxed().toList()) - .fixed64NumberList(LongStream.range(0,10).boxed().toList()) - .sfixed64NumberList(LongStream.range(-10,10).boxed().toList()) - .doubleNumberList(List.of(513.51,55535351.3545841,0d,-1d)) + .bytesField(Bytes.wrap(new byte[] {12, 29, 19, 120, 127, 0, -127})) + .int32NumberList(IntStream.range(0, 10).boxed().toList()) + .sint32NumberList(IntStream.range(-10, 10).boxed().toList()) + .uint32NumberList(IntStream.range(0, 100).boxed().toList()) + .fixed32NumberList(IntStream.range(0, 25).boxed().toList()) + .sfixed32NumberList(IntStream.range(-10, 25).boxed().toList()) + .floatNumberList(List.of(513.51f, 55535351.3545841f, 0f, -1f)) + .floatNumberList(List.of(513.51f, 55535351.3545841f, 0f, -1f)) + .int64NumberList(LongStream.range(0, 10).boxed().toList()) + .sint64NumberList(LongStream.range(-10, 10).boxed().toList()) + .uint64NumberList(LongStream.range(0, 10).boxed().toList()) + .fixed64NumberList(LongStream.range(0, 10).boxed().toList()) + .sfixed64NumberList(LongStream.range(-10, 10).boxed().toList()) + .doubleNumberList(List.of(513.51, 55535351.3545841, 0d, -1d)) .booleanList(List.of(true, false, true, true, false)) .enumSuitList(List.of(Suit.ACES, Suit.CLUBS, Suit.DIAMONDS)) .subObjectList(List.of( new TimestampTest.Builder().seconds(5155135L).nanos(44513).build(), new TimestampTest.Builder().seconds(486486).nanos(31315).build(), - new TimestampTest.Builder().seconds(0).nanos(58).build() - )) + new TimestampTest.Builder().seconds(0).nanos(58).build())) .textList(List.of( "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ", "ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम, अयोध्या के महाराज दशरथ के बड़े सपुत्र थे।", - "A quick brown fox jumps over the lazy dog" - )) + "A quick brown fox jumps over the lazy dog")) .bytesExampleList(List.of( - Bytes.wrap(new byte[]{12,29,19,120,127,0,-127}), - Bytes.wrap(new byte[]{13,15,65,98,-65}), - Bytes.wrap(new byte[]{127,0,-127}) - )) + Bytes.wrap(new byte[] {12, 29, 19, 120, 127, 0, -127}), + Bytes.wrap(new byte[] {13, 15, 65, 98, -65}), + Bytes.wrap(new byte[] {127, 0, -127}))) .int32Boxed(1234) .uint32Boxed(Integer.MAX_VALUE) .floatBoxed(15834.213581f) @@ -80,7 +78,7 @@ public EverythingTestData() { .uint64Boxed(2451326663131L) .doubleBoxed(135581531681.1535151) .boolBoxed(true) - .bytesBoxed(Bytes.wrap(new byte[]{13,15,65,98,-65})) + .bytesBoxed(Bytes.wrap(new byte[] {13, 15, 65, 98, -65})) .stringBoxed("Hello Everything!") .doubleNumberOneOf(29292.299d) .innerEverything(new InnerEverything.Builder() @@ -98,39 +96,45 @@ public EverythingTestData() { .doubleNumber(135581531681.1535151) .booleanField(true) .enumSuit(Suit.SPADES) - .subObject(new TimestampTest.Builder().seconds(5155135L).nanos(44513).build()) + .subObject(new TimestampTest.Builder() + .seconds(5155135L) + .nanos(44513) + .build()) .text("Hello Everything!") - .bytesField(Bytes.wrap(new byte[]{12,29,19,120,127,0,-127})) - .int32NumberList(IntStream.range(0,10).boxed().toList()) - .sint32NumberList(IntStream.range(-10,10).boxed().toList()) - .uint32NumberList(IntStream.range(0,100).boxed().toList()) - .fixed32NumberList(IntStream.range(0,25).boxed().toList()) - .sfixed32NumberList(IntStream.range(-10,25).boxed().toList()) - .floatNumberList(List.of(513.51f,55535351.3545841f,0f,-1f)) - .floatNumberList(List.of(513.51f,55535351.3545841f,0f,-1f)) - .int64NumberList(LongStream.range(0,10).boxed().toList()) - .sint64NumberList(LongStream.range(-10,10).boxed().toList()) - .uint64NumberList(LongStream.range(0,10).boxed().toList()) - .fixed64NumberList(LongStream.range(0,10).boxed().toList()) - .sfixed64NumberList(LongStream.range(-10,10).boxed().toList()) - .doubleNumberList(List.of(513.51,55535351.3545841,0d,-1d)) + .bytesField(Bytes.wrap(new byte[] {12, 29, 19, 120, 127, 0, -127})) + .int32NumberList(IntStream.range(0, 10).boxed().toList()) + .sint32NumberList(IntStream.range(-10, 10).boxed().toList()) + .uint32NumberList(IntStream.range(0, 100).boxed().toList()) + .fixed32NumberList(IntStream.range(0, 25).boxed().toList()) + .sfixed32NumberList(IntStream.range(-10, 25).boxed().toList()) + .floatNumberList(List.of(513.51f, 55535351.3545841f, 0f, -1f)) + .floatNumberList(List.of(513.51f, 55535351.3545841f, 0f, -1f)) + .int64NumberList(LongStream.range(0, 10).boxed().toList()) + .sint64NumberList(LongStream.range(-10, 10).boxed().toList()) + .uint64NumberList(LongStream.range(0, 10).boxed().toList()) + .fixed64NumberList(LongStream.range(0, 10).boxed().toList()) + .sfixed64NumberList(LongStream.range(-10, 10).boxed().toList()) + .doubleNumberList(List.of(513.51, 55535351.3545841, 0d, -1d)) .booleanList(List.of(true, false, true, true, false)) .enumSuitList(List.of(Suit.ACES, Suit.CLUBS, Suit.DIAMONDS)) .subObjectList(List.of( - new TimestampTest.Builder().seconds(5155135L).nanos(44513).build(), - new TimestampTest.Builder().seconds(486486).nanos(31315).build(), - new TimestampTest.Builder().seconds(0).nanos(58).build() - )) + new TimestampTest.Builder() + .seconds(5155135L) + .nanos(44513) + .build(), + new TimestampTest.Builder() + .seconds(486486) + .nanos(31315) + .build(), + new TimestampTest.Builder().seconds(0).nanos(58).build())) .textList(List.of( "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ", "ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम, अयोध्या के महाराज दशरथ के बड़े सपुत्र थे।", - "A quick brown fox jumps over the lazy dog" - )) + "A quick brown fox jumps over the lazy dog")) .bytesExampleList(List.of( - Bytes.wrap(new byte[]{12,29,19,120,127,0,-127}), - Bytes.wrap(new byte[]{13,15,65,98,-65}), - Bytes.wrap(new byte[]{127,0,-127}) - )) + Bytes.wrap(new byte[] {12, 29, 19, 120, 127, 0, -127}), + Bytes.wrap(new byte[] {13, 15, 65, 98, -65}), + Bytes.wrap(new byte[] {127, 0, -127}))) .int32Boxed(1234) .uint32Boxed(Integer.MAX_VALUE) .floatBoxed(15834.213581f) @@ -138,7 +142,7 @@ public EverythingTestData() { .uint64Boxed(2451326663131L) .doubleBoxed(135581531681.1535151) .boolBoxed(true) - .bytesBoxed(Bytes.wrap(new byte[]{13,15,65,98,-65})) + .bytesBoxed(Bytes.wrap(new byte[] {13, 15, 65, 98, -65})) .stringBoxed("Hello Everything!") .doubleNumberOneOf(29292.299d) .build()) diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingWriterPerfTest.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingWriterPerfTest.java index c0b9d674..1a911ed7 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingWriterPerfTest.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/EverythingWriterPerfTest.java @@ -26,7 +26,7 @@ public EverythingWriterPerfTest() { * @throws Exception Thrown if there was a problem */ public static void main(String[] args) throws Exception { - final BufferedData outDataBuffer = BufferedData.allocate(1024*1024); + final BufferedData outDataBuffer = BufferedData.allocate(1024 * 1024); for (int i = 0; i < 10_000_000; i++) { outDataBuffer.reset(); @@ -52,12 +52,13 @@ public static void main2(String[] args) throws Exception { final byte[] protobuf = new byte[(int) tempDataBuffer.remaining()]; tempDataBuffer.readBytes(protobuf); // write out with protoc - final GetAccountDetailsResponse.AccountDetails accountDetailsProtoC = GetAccountDetailsResponse.AccountDetails.parseFrom(protobuf); -// -// final ByteBuffer bbout = ByteBuffer.allocate(1024*1024); + final GetAccountDetailsResponse.AccountDetails accountDetailsProtoC = + GetAccountDetailsResponse.AccountDetails.parseFrom(protobuf); + // + // final ByteBuffer bbout = ByteBuffer.allocate(1024*1024); for (int i = 0; i < 10_000_000; i++) { -// bbout.clear(); + // bbout.clear(); final byte[] writtenData = accountDetailsProtoC.toByteArray(); if (writtenData.length != protobuf.length) { System.out.println("writtenData = " + HexFormat.of().formatHex(writtenData)); diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayInputStream.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayInputStream.java index f54ee6fe..27889de9 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayInputStream.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayInputStream.java @@ -104,7 +104,7 @@ public long skip(long n) { k = n < 0 ? 0 : n; } - pos += (int)k; + pos += (int) k; return k; } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayOutputStream.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayOutputStream.java index ec57068b..0cac3d96 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayOutputStream.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/NonSynchronizedByteArrayOutputStream.java @@ -107,6 +107,5 @@ public byte[] toByteArray() { * {@inheritDoc} */ @Override - public void close() { - } + public void close() {} } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/Elapsed.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/Elapsed.java index f3a583e3..1a5e9f6c 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/Elapsed.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/Elapsed.java @@ -2,7 +2,6 @@ package com.hedera.pbj.integration.fuzz; import com.hedera.pbj.runtime.test.Sneaky; - import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; @@ -12,10 +11,7 @@ * @param nanos the time the code took to run, in nanos * @param the return type of the code, or Void for Runnables. */ -public final record Elapsed( - T result, - long nanos -) { +public final record Elapsed(T result, long nanos) { /** * Measure the time the provided Callable takes to run. @@ -41,7 +37,10 @@ public static Elapsed time(final Callable callable) { * @return an Elapsed record with the time. The result is set to null. */ public static Elapsed time(final Runnable runnable) { - return time(() -> { runnable.run(); return null; }); + return time(() -> { + runnable.run(); + return null; + }); } /** @@ -59,5 +58,4 @@ public static Elapsed time(final Runnable runnable) { public String format() { return TimeUnit.SECONDS.convert(nanos(), TimeUnit.NANOSECONDS) + " seconds"; } - } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTest.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTest.java index 2640b942..2d6fced9 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTest.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTest.java @@ -2,7 +2,6 @@ package com.hedera.pbj.integration.fuzz; import com.hedera.pbj.runtime.Codec; - import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -48,10 +47,7 @@ public FuzzTest() { * @return the result of the fuzz test */ public static FuzzTestResult fuzzTest( - final T object, - final double threshold, - final Random random, - final Class protocModelClass) { + final T object, final double threshold, final Random random, final Class protocModelClass) { final long startNanoTime = System.nanoTime(); final Function protocParser = getProtocParser(protocModelClass); @@ -61,13 +57,7 @@ public static FuzzTestResult fuzzTest( if (repeatCount == 0) { // Certain objects result in zero-size payload, so there's nothing to test. // Mark it as passed. - return new FuzzTestResult<>( - object, - true, - Map.of(), - repeatCount, - System.nanoTime() - startNanoTime - ); + return new FuzzTestResult<>(object, true, Map.of(), repeatCount, System.nanoTime() - startNanoTime); } final Map resultCounts = IntStream.range(0, repeatCount) @@ -83,8 +73,7 @@ public static FuzzTestResult fuzzTest( statsMap.getOrDefault(SingleFuzzTestResult.DESERIALIZATION_FAILED, 0.) >= threshold, statsMap, repeatCount, - System.nanoTime() - startNanoTime - ); + System.nanoTime() - startNanoTime); } private static Function getProtocParser(Class protocModelClass) { @@ -99,8 +88,9 @@ public static FuzzTestResult fuzzTest( } }; } catch (NoSuchMethodException e) { - throw new FuzzTestException("Protoc model " + protocModelClass.getName() - + " doesn't have the parseFrom(InputStream) method", e); + throw new FuzzTestException( + "Protoc model " + protocModelClass.getName() + " doesn't have the parseFrom(InputStream) method", + e); } return protocParser; } @@ -117,12 +107,9 @@ private static int estimateRepeatCount(final T object, final Codec codec) } private static Map computePercentageMap( - final Map resultCounts, - final int repeatCount) { + final Map resultCounts, final int repeatCount) { return resultCounts.entrySet().stream() .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> entry.getValue().doubleValue() / (double) repeatCount) - ); + Map.Entry::getKey, entry -> entry.getValue().doubleValue() / (double) repeatCount)); } } diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTestResult.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTestResult.java index 36f9ab23..86d518e5 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTestResult.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/FuzzTestResult.java @@ -17,12 +17,7 @@ * @param the type of the object for which the test was run */ public record FuzzTestResult( - T object, - boolean passed, - Map percentageMap, - int repeatCount, - long nanoDuration -) { + T object, boolean passed, Map percentageMap, int repeatCount, long nanoDuration) { /** A number format for percentage values. */ private static final NumberFormat PERCENTAGE_FORMAT = NumberFormat.getPercentInstance(); diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTest.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTest.java index 9f53eeb1..c2065e12 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTest.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTest.java @@ -3,7 +3,6 @@ import com.hedera.pbj.runtime.Codec; import com.hedera.pbj.runtime.io.buffer.BufferedData; - import java.io.InputStream; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; @@ -32,9 +31,9 @@ public final class SingleFuzzTest { * When set to true, the test will print debugging info to System.out, * including payloads, for every single run. This may produce a lot of console output. */ - private final static boolean debug = false; + private static final boolean debug = false; /** A thread-safe counter for the next ID which is also the number of test runs performed so far. */ - private final static AtomicInteger TEST_ID_GENERATOR = new AtomicInteger(0); + private static final AtomicInteger TEST_ID_GENERATOR = new AtomicInteger(0); /** * Empty constructor @@ -86,8 +85,7 @@ private static void tryProtocParser( final Object deserializedObject, final Function protocParser, Exception pbjException, - boolean doThrow - ) { + boolean doThrow) { dataBuffer.reset(); try { Object protocObject = protocParser.apply(dataBuffer.toInputStream()); @@ -95,8 +93,7 @@ private static void tryProtocParser( System.out.println(prefix + "NOTE: Protoc was able to parse this payload w/o exceptions as " + protocObject + " , but PBJ errored out with " - + pbjException - ); + + pbjException); } } catch (Exception ex) { // Protoc didn't like the bytes. @@ -108,10 +105,8 @@ private static void tryProtocParser( + ", while PBJ didn't for original object: " + originalObject + " and fuzzBytes " + dataBuffer - + " that PBJ parsed as: " + deserializedObject - , - ex - ); + + " that PBJ parsed as: " + deserializedObject, + ex); } } } @@ -166,10 +161,7 @@ private static int estimateNumberOfBytesToModify(final Random random, final int * @param the type of the input object */ public static SingleFuzzTestResult fuzzTest( - final T object, - final Codec codec, - final Random random, - final Function protocParser) { + final T object, final Codec codec, final Random random, final Function protocParser) { // Generate a unique test ID prefix for this particular run to tag debugging output: final String prefix = SingleFuzzTest.class.getSimpleName() + " " + TEST_ID_GENERATOR.getAndIncrement() + ": "; @@ -257,10 +249,7 @@ private static void modifyBufferedData(final Random random, final int size, fina * @return a BufferedData buffer with the object written to it */ private static BufferedData createBufferedData( - final T object, - final Codec codec, - final int size, - final String prefix) { + final T object, final Codec codec, final int size, final String prefix) { final BufferedData dataBuffer; try { dataBuffer = write(object, codec, size); @@ -270,4 +259,4 @@ private static BufferedData createBufferedData( } return dataBuffer; } -} \ No newline at end of file +} diff --git a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTestResult.java b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTestResult.java index bf4eaabf..d7ad8b06 100644 --- a/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTestResult.java +++ b/pbj-integration-tests/src/main/java/com/hedera/pbj/integration/fuzz/SingleFuzzTestResult.java @@ -68,5 +68,4 @@ public enum SingleFuzzTestResult { * reveal any. */ RESERIALIZATION_PASSED; - } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToNegativeTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToNegativeTest.java index 11faa73d..f22b116e 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToNegativeTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToNegativeTest.java @@ -5,12 +5,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - import java.io.File; import java.net.URL; import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; class CompareToNegativeTest { @@ -19,25 +18,28 @@ class CompareToNegativeTest { @Test void testNonComparableSubObj() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> - getCompileFilesIn("non_compilable_comparable_sub_obj.proto")); - assertEquals("Field NonComparableSubObj.subObject specified in `pbj.comparable` option must implement `Comparable` interface but it doesn't.", + IllegalArgumentException exception = assertThrows( + IllegalArgumentException.class, () -> getCompileFilesIn("non_compilable_comparable_sub_obj.proto")); + assertEquals( + "Field NonComparableSubObj.subObject specified in `pbj.comparable` option must implement `Comparable` interface but it doesn't.", exception.getMessage()); } @Test void testRepeatedField() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> - getCompileFilesIn("non_compilable_comparable_repeated.proto")); - assertEquals("Field `int32List` specified in `pbj.comparable` option is repeated. Repeated fields are not supported by this option.", + IllegalArgumentException exception = assertThrows( + IllegalArgumentException.class, () -> getCompileFilesIn("non_compilable_comparable_repeated.proto")); + assertEquals( + "Field `int32List` specified in `pbj.comparable` option is repeated. Repeated fields are not supported by this option.", exception.getMessage()); } @Test void testNonComparableOneOfField() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> - getCompileFilesIn("non_compilable_comparable_oneOf.proto")); - assertEquals("Field NonComparableSubObj.subObject specified in `pbj.comparable` option must implement `Comparable` interface but it doesn't.", + IllegalArgumentException exception = assertThrows( + IllegalArgumentException.class, () -> getCompileFilesIn("non_compilable_comparable_oneOf.proto")); + assertEquals( + "Field NonComparableSubObj.subObject specified in `pbj.comparable` option must implement `Comparable` interface but it doesn't.", exception.getMessage()); } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToTest.java index f4f7419e..6efed902 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/CompareToTest.java @@ -22,11 +22,9 @@ import com.hedera.pbj.test.proto.pbj.LimitedComparableTestWithOneOf; import com.hedera.pbj.test.proto.pbj.StringValueComparableTest; import com.hedera.pbj.test.proto.pbj.UnsignedComparableTest; -import org.junit.jupiter.api.Test; - import java.util.ArrayList; - import java.util.random.RandomGenerator; +import org.junit.jupiter.api.Test; /** * Unit test for {@link ComparableTest} and {@link LimitedComparableTest} objects. @@ -41,115 +39,116 @@ void testCompareTo_int32() { new ComparableTest(2, 0.0, false, null, null, null, null), new ComparableTest(3, 0.0, false, null, null, null, null)); } + @Test void testCompareTo_double() { assertComparables( new ComparableTest(1, 0.0, false, null, null, null, null), new ComparableTest(2, 1.5, false, null, null, null, null), - new ComparableTest(3, 2.66, false, null, null, null, null) - ); + new ComparableTest(3, 2.66, false, null, null, null, null)); } + @Test void testCompareTo_bool() { assertComparables( new ComparableTest(0, 0.0, false, null, null, null, null), - new ComparableTest(0, 0.0, true, null, null, null, null) - ); + new ComparableTest(0, 0.0, true, null, null, null, null)); } + @Test void testCompareTo_string() { assertComparables( new ComparableTest(0, 0.0, false, "a", null, null, null), new ComparableTest(0, 0.0, false, "b", null, null, null), - new ComparableTest(0, 0.0, false, "c", null, null, null) - ); + new ComparableTest(0, 0.0, false, "c", null, null, null)); } + @Test void testCompareTo_bytes() { assertComparables( new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("a")), new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("aa")), - new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("aaa")) - ); + new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("aaa"))); } + @Test void testCompareTo_bytes_same_lenth() { - assertComparables( + assertComparables( new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("aba")), new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("abb")), - new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("abc")) - ); + new ComparableTest(0, 0.0, false, null, null, null, Bytes.wrap("abc"))); } + @Test - void testCompareTo_enum(){ + void testCompareTo_enum() { assertComparables( new ComparableTest(0, 0.0, false, null, ComparableEnum.ONE, null, null), new ComparableTest(0, 0.0, false, null, ComparableEnum.TWO, null, null), - new ComparableTest(0, 0.0, false, null, ComparableEnum.THREE, null, null) - ); + new ComparableTest(0, 0.0, false, null, ComparableEnum.THREE, null, null)); } + @Test - void testCompareTo_subObject(){ + void testCompareTo_subObject() { assertComparables( new ComparableTest(0, 0.0, false, null, null, new ComparableSubObj(1), null), - new ComparableTest(0, 0.0, false, null, null, new ComparableSubObj(2), null), - new ComparableTest(0, 0.0, false, null, null, new ComparableSubObj(3), null) - ); + new ComparableTest(0, 0.0, false, null, null, new ComparableSubObj(2), null), + new ComparableTest(0, 0.0, false, null, null, new ComparableSubObj(3), null)); } + @Test - void compareTo_mixed() { - assertComparables( - new ComparableTest(1, 0.0, false, null, null, new ComparableSubObj(1), null), - new ComparableTest(1, 0.0, false, null, null, new ComparableSubObj(2), null), - new ComparableTest(2, 0.0, false, null, null, new ComparableSubObj(1), null), - new ComparableTest(2, 0.0, false, null, null, new ComparableSubObj(2), null) - ); - } - @Test - void compareTo_StringValue() { - assertComparables( - new StringValueComparableTest(null), - new StringValueComparableTest("a"), - new StringValueComparableTest("b"), - new StringValueComparableTest("c") - ); - } - @Test - void compareTo_BoolValue() { - assertComparables( - new BoolValueComparableTest(null), - new BoolValueComparableTest(false), - new BoolValueComparableTest(true) - ); - } - @Test - void compareTo_Int32Value() { - assertComparables( - new Int32ValueComparableTest(null, null), - new Int32ValueComparableTest(1, null), - new Int32ValueComparableTest(2, null), - new Int32ValueComparableTest(3, null) - ); - } - @Test - void compareTo_Uint32Value() { - assertComparables( - new Int32ValueComparableTest(null, null), - new Int32ValueComparableTest(null, 0), - new Int32ValueComparableTest(null, 3), - new Int32ValueComparableTest(null, -2), - new Int32ValueComparableTest(null, -1) - ); - } + void compareTo_mixed() { + assertComparables( + new ComparableTest(1, 0.0, false, null, null, new ComparableSubObj(1), null), + new ComparableTest(1, 0.0, false, null, null, new ComparableSubObj(2), null), + new ComparableTest(2, 0.0, false, null, null, new ComparableSubObj(1), null), + new ComparableTest(2, 0.0, false, null, null, new ComparableSubObj(2), null)); + } + + @Test + void compareTo_StringValue() { + assertComparables( + new StringValueComparableTest(null), + new StringValueComparableTest("a"), + new StringValueComparableTest("b"), + new StringValueComparableTest("c")); + } + + @Test + void compareTo_BoolValue() { + assertComparables( + new BoolValueComparableTest(null), + new BoolValueComparableTest(false), + new BoolValueComparableTest(true)); + } + + @Test + void compareTo_Int32Value() { + assertComparables( + new Int32ValueComparableTest(null, null), + new Int32ValueComparableTest(1, null), + new Int32ValueComparableTest(2, null), + new Int32ValueComparableTest(3, null)); + } + + @Test + void compareTo_Uint32Value() { + assertComparables( + new Int32ValueComparableTest(null, null), + new Int32ValueComparableTest(null, 0), + new Int32ValueComparableTest(null, 3), + new Int32ValueComparableTest(null, -2), + new Int32ValueComparableTest(null, -1)); + } + @Test void compareTo_Int64Value() { assertComparables( new Int64ValueComparableTest(null, null), new Int64ValueComparableTest(1L, null), new Int64ValueComparableTest(2L, null), - new Int64ValueComparableTest(3L, null) - ); + new Int64ValueComparableTest(3L, null)); } + @Test void compareTo_UInt64Value() { assertComparables( @@ -157,9 +156,9 @@ void compareTo_UInt64Value() { new Int64ValueComparableTest(null, 0L), new Int64ValueComparableTest(null, 3L), new Int64ValueComparableTest(null, -2L), - new Int64ValueComparableTest(null, -1L) - ); + new Int64ValueComparableTest(null, -1L)); } + @Test void compareTo_FloatValue() { assertComparables( @@ -168,6 +167,7 @@ void compareTo_FloatValue() { new FloatValueComparableTest(2.5f), new FloatValueComparableTest(7.7f)); } + @Test void compareTo_DoubleValue() { assertComparables( @@ -176,6 +176,7 @@ void compareTo_DoubleValue() { new DoubleValueComparableTest(2.5), new DoubleValueComparableTest(7.7)); } + @Test void compareTo_ByteValue() { assertComparables( @@ -184,6 +185,7 @@ void compareTo_ByteValue() { new BytesValueComparableTest(Bytes.wrap("b")), new BytesValueComparableTest(Bytes.wrap("c"))); } + @Test void comareTo_unsigned() { assertComparables( @@ -195,70 +197,72 @@ void comareTo_unsigned() { new UnsignedComparableTest(0, 0L), new UnsignedComparableTest(0, 3L), new UnsignedComparableTest(0, -2L), - new UnsignedComparableTest(0, -1L) - ); + new UnsignedComparableTest(0, -1L)); } + @Test - void limitedCompareTo_nonComparableOneOf() { + void limitedCompareTo_nonComparableOneOf() { // This code is only here to be compiled. OneOf field is not listed in `pbj.comparable` option - // and therefore it has `OneOf` type, not `ComparableOneOf`. - new LimitedComparableTestWithOneOf(0, new OneOf<>(LimitedComparableTestWithOneOf.OneOfExampleOneOfType.ONE_OF_SUB_OBJECT, new ComparableSubObj(1))); - } - - @Test - void limitedCompareTo_int32() { - assertComparables( - new LimitedComparableTest(1, 0L, false, null, null, null), - new LimitedComparableTest(2, 0L, false, null, null, null), - new LimitedComparableTest(3, 0L, false, null, null, null)); - } - - @Test - void limitedCompareTo_text() { - assertComparables( - new LimitedComparableTest(0, 0L, false, "1", null, null), - new LimitedComparableTest(0, 0L, false, "2", null, null), - new LimitedComparableTest(0, 0L, false, "3", null, null)); - } - - @Test - void limitedCompareTo_subObj() { - assertComparables( - new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(1)), - new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(2)), - new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(3))); - } - - @Test - void limitedCompareTo_mixed() { + // and therefore it has `OneOf` type, not `ComparableOneOf`. + new LimitedComparableTestWithOneOf( + 0, + new OneOf<>( + LimitedComparableTestWithOneOf.OneOfExampleOneOfType.ONE_OF_SUB_OBJECT, + new ComparableSubObj(1))); + } + + @Test + void limitedCompareTo_int32() { + assertComparables( + new LimitedComparableTest(1, 0L, false, null, null, null), + new LimitedComparableTest(2, 0L, false, null, null, null), + new LimitedComparableTest(3, 0L, false, null, null, null)); + } + + @Test + void limitedCompareTo_text() { + assertComparables( + new LimitedComparableTest(0, 0L, false, "1", null, null), + new LimitedComparableTest(0, 0L, false, "2", null, null), + new LimitedComparableTest(0, 0L, false, "3", null, null)); + } + + @Test + void limitedCompareTo_subObj() { + assertComparables( + new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(1)), + new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(2)), + new LimitedComparableTest(0, 0L, false, null, null, new ComparableSubObj(3))); + } + + @Test + void limitedCompareTo_mixed() { // note that only field 1, 4 and 6 are comparable, others are ignored - assertComparables( - new LimitedComparableTest(1, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(1)), - new LimitedComparableTest(1, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(2)), - new LimitedComparableTest(1, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(1)), - new LimitedComparableTest(1, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(2)), - new LimitedComparableTest(2, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(1)), - new LimitedComparableTest(2, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(2)), - new LimitedComparableTest(2, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(1)), - new LimitedComparableTest(2, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(2)) - ); - } - - @Test - void oneOfCompareTo() { - assertComparables( - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT1_ONE_OF, "a"), - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT1_ONE_OF, "b"), - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT2_ONE_OF, "a"), - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT2_ONE_OF, "b"), - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.SUB_OBJECT, new ComparableSubObj(1)), - createOneOf(ComparableOneOfTest.OneofExampleOneOfType.SUB_OBJECT, new ComparableSubObj(2)) - ); - } - - private ComparableOneOfTest createOneOf(ComparableOneOfTest.OneofExampleOneOfType type, Comparable value) { - return new ComparableOneOfTest(new ComparableOneOf<>(type, value)); - } + assertComparables( + new LimitedComparableTest(1, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(1)), + new LimitedComparableTest(1, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(2)), + new LimitedComparableTest(1, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(1)), + new LimitedComparableTest(1, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(2)), + new LimitedComparableTest(2, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(1)), + new LimitedComparableTest(2, nextLong(), nextBoolean(), "1", nextEnum(), new ComparableSubObj(2)), + new LimitedComparableTest(2, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(1)), + new LimitedComparableTest(2, nextLong(), nextBoolean(), "2", nextEnum(), new ComparableSubObj(2))); + } + + @Test + void oneOfCompareTo() { + assertComparables( + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT1_ONE_OF, "a"), + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT1_ONE_OF, "b"), + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT2_ONE_OF, "a"), + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.TEXT2_ONE_OF, "b"), + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.SUB_OBJECT, new ComparableSubObj(1)), + createOneOf(ComparableOneOfTest.OneofExampleOneOfType.SUB_OBJECT, new ComparableSubObj(2))); + } + + private ComparableOneOfTest createOneOf(ComparableOneOfTest.OneofExampleOneOfType type, Comparable value) { + return new ComparableOneOfTest(new ComparableOneOf<>(type, value)); + } private static long nextLong() { return RandomGenerator.getDefault().nextLong(); diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ExtendedUtf8MessageWithStringTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ExtendedUtf8MessageWithStringTest.java index 64987db4..b6c31b30 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ExtendedUtf8MessageWithStringTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ExtendedUtf8MessageWithStringTest.java @@ -1,79 +1,82 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalByteBuffer; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer2; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.google.protobuf.CodedOutputStream; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.test.NoToStringWrapper; import com.hedera.pbj.test.proto.pbj.MessageWithString; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import java.nio.ByteBuffer; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalByteBuffer; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer2; -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Unit Test for MessageWithString model object. Generate based on protobuf schema. */ public final class ExtendedUtf8MessageWithStringTest { - @ParameterizedTest + @ParameterizedTest @MethodSource("createModelTestArguments") - public void testMessageWithStringAgainstProtoC(final NoToStringWrapper modelObjWrapper) throws Exception { - final MessageWithString modelObj = modelObjWrapper.getValue(); - // get reusable thread buffers - final BufferedData dataBuffer = getThreadLocalDataBuffer(); - final BufferedData dataBuffer2 = getThreadLocalDataBuffer2(); - final ByteBuffer byteBuffer = getThreadLocalByteBuffer(); - - // model to bytes with PBJ - MessageWithString.PROTOBUF.write(modelObj,dataBuffer); - // clamp limit to bytes written - dataBuffer.limit(dataBuffer.position()); - - // copy bytes to ByteBuffer - dataBuffer.resetPosition(); - dataBuffer.readBytes(byteBuffer); - byteBuffer.flip(); - - // read proto bytes with ProtoC to make sure it is readable and no parse exceptions are thrown - final com.hedera.pbj.test.proto.java.MessageWithString protoCModelObj = com.hedera.pbj.test.proto.java.MessageWithString.parseFrom(byteBuffer); - - // read proto bytes with PBJ parser - dataBuffer.resetPosition(); - final MessageWithString modelObj2 = MessageWithString.PROTOBUF.parse(dataBuffer); - - // check the read back object is equal to written original one - //assertEquals(modelObj.toString(), modelObj2.toString()); - assertEquals(modelObj, modelObj2); - - // model to bytes with ProtoC writer - byteBuffer.clear(); - final CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteBuffer); - protoCModelObj.writeTo(codedOutput); - codedOutput.flush(); - byteBuffer.flip(); - // copy to a data buffer - dataBuffer2.writeBytes(byteBuffer); - dataBuffer2.flip(); - - // compare written bytes - assertEquals(dataBuffer, dataBuffer2); - - // parse those bytes again with PBJ - dataBuffer2.resetPosition(); - final MessageWithString modelObj3 = MessageWithString.PROTOBUF.parse(dataBuffer2); - assertEquals(modelObj, modelObj3); + public void testMessageWithStringAgainstProtoC(final NoToStringWrapper modelObjWrapper) + throws Exception { + final MessageWithString modelObj = modelObjWrapper.getValue(); + // get reusable thread buffers + final BufferedData dataBuffer = getThreadLocalDataBuffer(); + final BufferedData dataBuffer2 = getThreadLocalDataBuffer2(); + final ByteBuffer byteBuffer = getThreadLocalByteBuffer(); + + // model to bytes with PBJ + MessageWithString.PROTOBUF.write(modelObj, dataBuffer); + // clamp limit to bytes written + dataBuffer.limit(dataBuffer.position()); + + // copy bytes to ByteBuffer + dataBuffer.resetPosition(); + dataBuffer.readBytes(byteBuffer); + byteBuffer.flip(); + + // read proto bytes with ProtoC to make sure it is readable and no parse exceptions are thrown + final com.hedera.pbj.test.proto.java.MessageWithString protoCModelObj = + com.hedera.pbj.test.proto.java.MessageWithString.parseFrom(byteBuffer); + + // read proto bytes with PBJ parser + dataBuffer.resetPosition(); + final MessageWithString modelObj2 = MessageWithString.PROTOBUF.parse(dataBuffer); + + // check the read back object is equal to written original one + // assertEquals(modelObj.toString(), modelObj2.toString()); + assertEquals(modelObj, modelObj2); + + // model to bytes with ProtoC writer + byteBuffer.clear(); + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteBuffer); + protoCModelObj.writeTo(codedOutput); + codedOutput.flush(); + byteBuffer.flip(); + // copy to a data buffer + dataBuffer2.writeBytes(byteBuffer); + dataBuffer2.flip(); + + // compare written bytes + assertEquals(dataBuffer, dataBuffer2); + + // parse those bytes again with PBJ + dataBuffer2.resetPosition(); + final MessageWithString modelObj3 = MessageWithString.PROTOBUF.parse(dataBuffer2); + assertEquals(modelObj, modelObj3); } - - /** + + /** * List of all valid arguments for testing, built as a static list, so we can reuse it. */ public static final List ARGUMENTS; - + /** * Create a stream of all test permutations of the MessageWithString class we are testing. This is reused by other tests * as well that have model objects with fields of this type. @@ -81,12 +84,12 @@ public void testMessageWithStringAgainstProtoC(final NoToStringWrapper> createModelTestArguments() { - return ARGUMENTS.stream().map(NoToStringWrapper::new); + return ARGUMENTS.stream().map(NoToStringWrapper::new); } - - /** Simple multi-line text test block */ - private static final String SAMPLE_TEXT_BLOCK = """ + /** Simple multi-line text test block */ + private static final String SAMPLE_TEXT_BLOCK = + """ To be, or not to be, that is the question: Whether ’tis nobler in the mind to suffer The slings and arrows of outrageous fortune, @@ -102,8 +105,9 @@ public static Stream> createModelTestArgume Must give us pause—there’s the respect That makes calamity of so long life…"""; - /** UTF-8 language test block containing pangrams in a bunch of languages */ - private static final String UTF8_LANGUAGES_TEXT_BLOCK_1 = """ + /** UTF-8 language test block containing pangrams in a bunch of languages */ + private static final String UTF8_LANGUAGES_TEXT_BLOCK_1 = + """ English : A quick brown fox jumps over the lazy dog Arabic : صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ Arabic : نصٌّ حكيمٌ لهُ سِرٌّ قاطِعٌ وَذُو شَأنٍ عَظيمٍ مكتوبٌ على ثوبٍ أخضرَ ومُغلفٌ بجلدٍ أزرق @@ -130,8 +134,9 @@ public static Stream> createModelTestArgume Japanese : あめ つち ほし そら / やま かは みね たに / くも きり むろ こけ / ひと いぬ うへ すゑ / ゆわ さる おふ せよ / えのえを なれ ゐて """; - /** UTF-8 language test block containing pangrams in a bunch of languages, continued */ - private static final String UTF8_LANGUAGES_TEXT_BLOCK_2 = """ + /** UTF-8 language test block containing pangrams in a bunch of languages, continued */ + private static final String UTF8_LANGUAGES_TEXT_BLOCK_2 = + """ Japanese : あめ つち ほし そら / やま かは みね たに / くも きり むろ こけ / ひと いぬ うへ すゑ / ゆわ さる おふ せよ / えのえを なれ ゐて Japanese : 天 地 星 空 / 山 川 峰 谷 / 雲 霧 室 苔 / 人 犬 上 末 / 硫黄 猿 生ふ 為よ / 榎の 枝を 馴れ 居て Japanese : いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす(ん) @@ -161,8 +166,9 @@ public static Stream> createModelTestArgume Welsh : Parciais fy jac codi baw hud llawn dŵr ger tŷ Mabon. """; - /** Example Unicode Math symbols */ - private static final String MATH_SYMBOLS = """ + /** Example Unicode Math symbols */ + private static final String MATH_SYMBOLS = + """ U+220x ∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ U+221x ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ U+222x ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ @@ -196,7 +202,9 @@ public static Stream> createModelTestArgume U+2AEx ⫠ ⫡ ⫢ ⫣ ⫤ ⫥ ⫦ ⫧ ⫨ ⫩ ⫪ ⫫ ⫬ ⫭ ⫮ ⫯ U+2AFx ⫰ ⫱ ⫲ ⫳ ⫴ ⫵ ⫶ ⫷ ⫸ ⫹ ⫺ ⫻ ⫼ ⫽ ⫾ ⫿ """; - private static final String ARROW_SYMBOLS = """ + + private static final String ARROW_SYMBOLS = + """ U+219x ← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ U+21Ax ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ U+21Bx ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ @@ -213,32 +221,27 @@ public static Stream> createModelTestArgume U+296x ⥠ ⥡ ⥢ ⥣ ⥤ ⥥ ⥦ ⥧ ⥨ ⥩ ⥪ ⥫ ⥬ ⥭ ⥮ ⥯ U+297x ⥰ ⥱ ⥲ ⥳ ⥴ ⥵ ⥶ ⥷ ⥸ ⥹ ⥺ ⥻ ⥼ ⥽ ⥾ ⥿ """; - /** string type test cases */ - public static final List EXTENDED_STRING_TESTS_LIST = List.of( - "", - "Dude", - "©«", - "\n", - "I need some HBAR to run work on Hedera!", - "I need some ℏ to run work on Hedera!", - SAMPLE_TEXT_BLOCK, - UTF8_LANGUAGES_TEXT_BLOCK_1, - UTF8_LANGUAGES_TEXT_BLOCK_2, - MATH_SYMBOLS, - ARROW_SYMBOLS - ); - - - static { - final var aTestStringList = EXTENDED_STRING_TESTS_LIST; - // work out the longest of all the lists of args as that is how many test cases we need - final int maxValues = IntStream.of( - aTestStringList.size() - ).max().getAsInt(); - // create new stream of model objects using lists above as constructor params - ARGUMENTS = IntStream.range(0,maxValues) - .mapToObj(i -> new MessageWithString( - aTestStringList.get(Math.min(i, aTestStringList.size()-1)) - )).toList(); - } + /** string type test cases */ + public static final List EXTENDED_STRING_TESTS_LIST = List.of( + "", + "Dude", + "©«", + "\n", + "I need some HBAR to run work on Hedera!", + "I need some ℏ to run work on Hedera!", + SAMPLE_TEXT_BLOCK, + UTF8_LANGUAGES_TEXT_BLOCK_1, + UTF8_LANGUAGES_TEXT_BLOCK_2, + MATH_SYMBOLS, + ARROW_SYMBOLS); + + static { + final var aTestStringList = EXTENDED_STRING_TESTS_LIST; + // work out the longest of all the lists of args as that is how many test cases we need + final int maxValues = IntStream.of(aTestStringList.size()).max().getAsInt(); + // create new stream of model objects using lists above as constructor params + ARGUMENTS = IntStream.range(0, maxValues) + .mapToObj(i -> new MessageWithString(aTestStringList.get(Math.min(i, aTestStringList.size() - 1)))) + .toList(); + } } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/FieldsNonNullTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/FieldsNonNullTest.java index fc086b02..9f2944cf 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/FieldsNonNullTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/FieldsNonNullTest.java @@ -1,6 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + import com.hedera.hapi.node.base.FeeSchedule; import com.hedera.hapi.node.base.TransactionFeeSchedule; import com.hedera.pbj.runtime.io.buffer.Bytes; @@ -8,10 +12,6 @@ import com.hedera.pbj.test.proto.pbj.MessageWithString; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - public class FieldsNonNullTest { @Test void testBytesNeverNull() { @@ -71,7 +71,9 @@ void testRepeatedNeverNull() { assertNotNull(msg.transactionFeeSchedule()); assertTrue(msg.transactionFeeSchedule().isEmpty()); - msg = FeeSchedule.newBuilder().transactionFeeSchedule((TransactionFeeSchedule[])null).build(); + msg = FeeSchedule.newBuilder() + .transactionFeeSchedule((TransactionFeeSchedule[]) null) + .build(); assertNotNull(msg.transactionFeeSchedule()); assertTrue(msg.transactionFeeSchedule().isEmpty()); } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/HashEqualsTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/HashEqualsTest.java index edf02637..482220fe 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/HashEqualsTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/HashEqualsTest.java @@ -5,10 +5,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import org.junit.jupiter.api.Test; - import com.hedera.pbj.test.proto.pbj.TimestampTest; import com.hedera.pbj.test.proto.pbj.TimestampTest2; +import org.junit.jupiter.api.Test; class HashEqualsTest { @Test diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/JsonCodecTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/JsonCodecTest.java index 7097e1ea..39b83917 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/JsonCodecTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/JsonCodecTest.java @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.google.protobuf.ByteString; import com.google.protobuf.util.JsonFormat; import com.hedera.hapi.node.base.Key; @@ -12,13 +14,10 @@ import com.hedera.pbj.runtime.io.stream.WritableStreamingData; import com.hedera.pbj.test.proto.pbj.Everything; import com.hederahashgraph.api.proto.java.GetAccountDetailsResponse; -import org.junit.jupiter.api.Test; - import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.util.HexFormat; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; /** * Base set of tests to make sure that JSON is round tripped correctly with ProtoC Generated code @@ -47,11 +46,12 @@ public void simpleTimestampTest() throws Exception { System.out.println("pbjJson = " + pbjJson); assertEquals(protoCJson, pbjJson); } + @Test public void simpleKeyTest() throws Exception { // build with protoc com.hederahashgraph.api.proto.java.Key keyProtoC = com.hederahashgraph.api.proto.java.Key.newBuilder() - .setECDSA384(ByteString.copyFrom(new byte[]{0,1,2,3})) + .setECDSA384(ByteString.copyFrom(new byte[] {0, 1, 2, 3})) .build(); // write to JSON with protoc String protoCJson = JsonFormat.printer().print(keyProtoC); @@ -59,7 +59,9 @@ public void simpleKeyTest() throws Exception { // parse with pbj Key tPbj = Key.JSON.parse(BufferedData.wrap(protoCJson.getBytes(StandardCharsets.UTF_8))); // check - assertEquals(HexFormat.of().formatHex(keyProtoC.getECDSA384().toByteArray()), tPbj.ecdsa384().toHex()); + assertEquals( + HexFormat.of().formatHex(keyProtoC.getECDSA384().toByteArray()), + tPbj.ecdsa384().toHex()); // write with pbj ByteArrayOutputStream bout = new ByteArrayOutputStream(); WritableStreamingData out = new WritableStreamingData(bout); @@ -82,7 +84,8 @@ public void accountDetailsTest() throws Exception { // write to JSON with protoC String protoCJson = JsonFormat.printer().print(accountDetailsProtoC); // parse with pbj - AccountDetails accountDetailsPbj2 = AccountDetails.JSON.parse(BufferedData.wrap(protoCJson.getBytes(StandardCharsets.UTF_8))); + AccountDetails accountDetailsPbj2 = + AccountDetails.JSON.parse(BufferedData.wrap(protoCJson.getBytes(StandardCharsets.UTF_8))); // check assertEquals(accountDetailsPbj, accountDetailsPbj2); // write with pbj @@ -106,7 +109,8 @@ public void everythingTest() throws Exception { String protoCJson = JsonFormat.printer().print(accountDetailsProtoC); System.out.println("protoCJson = " + protoCJson); // parse with pbj - Everything everythingPbj2 = Everything.JSON.parse(BufferedData.wrap(protoCJson.getBytes(StandardCharsets.UTF_8))); + Everything everythingPbj2 = + Everything.JSON.parse(BufferedData.wrap(protoCJson.getBytes(StandardCharsets.UTF_8))); // check assertEquals(everythingPbj, everythingPbj2); // write with pbj @@ -115,6 +119,4 @@ public void everythingTest() throws Exception { String pbjJson = bout.toString(); assertEquals(protoCJson, pbjJson); } - - } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MalformedMessageTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MalformedMessageTest.java index a6f9e233..d195fb1b 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MalformedMessageTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MalformedMessageTest.java @@ -8,12 +8,11 @@ import com.hedera.pbj.test.proto.pbj.Everything; import com.hedera.pbj.test.proto.pbj.TimestampTest; import com.hedera.pbj.test.proto.pbj.codec.EverythingProtoCodec; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import java.io.IOException; import java.nio.ByteBuffer; import java.util.random.RandomGenerator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class MalformedMessageTest { @@ -66,12 +65,9 @@ private BufferedData prepareTestData(final ByteBuffer byteBuffer) throws IOExcep final BufferedData data = BufferedData.wrap(byteBuffer); byte[] bytes = new byte[8]; rng.nextBytes(bytes); - final TimestampTest bytesTest = TimestampTest.newBuilder() - .seconds(System.currentTimeMillis()) - .build(); - final Everything obj = Everything.newBuilder() - .subObject(bytesTest) - .build(); + final TimestampTest bytesTest = + TimestampTest.newBuilder().seconds(System.currentTimeMillis()).build(); + final Everything obj = Everything.newBuilder().subObject(bytesTest).build(); codec.write(obj, data); data.flip(); return data; diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxDepthTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxDepthTest.java index 711299a1..f9b6c8ef 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxDepthTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxDepthTest.java @@ -1,13 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.hedera.pbj.runtime.ParseException; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.test.proto.pbj.MessageWithMessage; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class MaxDepthTest { @Test void testMaxDepth_depth0() throws Exception { diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxSizeTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxSizeTest.java index 04743dfc..9c63f740 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxSizeTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/MaxSizeTest.java @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.hedera.pbj.runtime.ParseException; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.io.buffer.Bytes; @@ -8,13 +10,12 @@ import com.hedera.pbj.test.proto.pbj.MessageWithString; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class MaxSizeTest { @Test void testBytesMaxSize() throws Exception { final Bytes bytes = Bytes.wrap("test string long enough to hold Integer.MAX_VALUE as VarInt"); - final MessageWithBytes msg = MessageWithBytes.newBuilder().bytesField(bytes).build(); + final MessageWithBytes msg = + MessageWithBytes.newBuilder().bytesField(bytes).build(); final BufferedData data = BufferedData.allocate(MessageWithBytes.PROTOBUF.measureRecord(msg)); MessageWithBytes.PROTOBUF.write(msg, data); @@ -31,7 +32,8 @@ void testBytesMaxSize() throws Exception { @Test void testStringMaxSize() throws Exception { final String string = "test string long enough to hold Integer.MAX_VALUE as VarInt"; - final MessageWithString msg = MessageWithString.newBuilder().aTestString(string).build(); + final MessageWithString msg = + MessageWithString.newBuilder().aTestString(string).build(); final BufferedData data = BufferedData.allocate(MessageWithString.PROTOBUF.measureRecord(msg)); MessageWithString.PROTOBUF.write(msg, data); diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ParserNeverWrapsTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ParserNeverWrapsTest.java index a269a210..3b2a0712 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ParserNeverWrapsTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/ParserNeverWrapsTest.java @@ -1,15 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + import com.hedera.pbj.runtime.Codec; import com.hedera.pbj.runtime.io.WritableSequentialData; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.hedera.pbj.runtime.test.UncheckedThrowingFunction; import com.hedera.pbj.test.proto.pbj.MessageWithBytes; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - import java.io.IOException; import java.io.UncheckedIOException; import java.nio.ByteBuffer; @@ -19,10 +20,8 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class ParserNeverWrapsTest { @@ -75,8 +74,7 @@ private static record WrapTestData( Function, T> parser, Runnable resetter, Supplier getter, - BiConsumer setter - ) { + BiConsumer setter) { static WrapTestData createByteArrayBufferedData(int size) { // The current implementation creates ByteArrayBufferedData: final BufferedData seq = BufferedData.allocate(size); @@ -88,8 +86,7 @@ static WrapTestData createByteArrayBufferedData(int size) { (pos, bytes) -> { seq.position(pos); seq.writeBytes(bytes); - } - ); + }); } static WrapTestData createDirectBufferedData(int size) { @@ -103,8 +100,7 @@ static WrapTestData createDirectBufferedData(int size) { (pos, bytes) -> { seq.position(pos); seq.writeBytes(bytes); - } - ); + }); } static WrapTestData createBytes(int size) { @@ -122,8 +118,7 @@ static WrapTestData createBytes(int size) { for (int i = 0; i < arr.length; i++) { byteArray[pos + i] = arr[i]; } - } - ); + }); } } @@ -131,8 +126,7 @@ static Stream> provideWrapTestArguments() { return Stream.of( WrapTestData::createByteArrayBufferedData, WrapTestData::createDirectBufferedData, - WrapTestData::createBytes - ); + WrapTestData::createBytes); } @ParameterizedTest diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/SampleFuzzTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/SampleFuzzTest.java index 03832cc0..5a201121 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/SampleFuzzTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/SampleFuzzTest.java @@ -1,6 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + import com.hedera.hapi.node.base.tests.AccountIDTest; import com.hedera.hapi.node.base.tests.ContractIDTest; import com.hedera.pbj.integration.fuzz.Elapsed; @@ -17,17 +20,13 @@ import com.hedera.pbj.test.proto.pbj.tests.TimestampTestSeconds2Test; import com.hedera.pbj.test.proto.pbj.tests.TimestampTestSecondsTest; import com.hedera.pbj.test.proto.pbj.tests.TimestampTestTest; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - import java.text.NumberFormat; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assumptions.assumeFalse; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; /** * This is a sample fuzz test just to demonstrate the usage of the FuzzTest class. @@ -103,33 +102,20 @@ public class SampleFuzzTest { TimestampTest2Test.class, TimestampTestSeconds2Test.class, TimestampTestSecondsTest.class, - TimestampTestTest.class - ); + TimestampTestTest.class); - private static record FuzzTestParams( - T object, - Class

protocModelClass - ) { - } + private static record FuzzTestParams(T object, Class

protocModelClass) {} private static Stream> testCases() { - return MODEL_TEST_CLASSES.stream() - .flatMap(clz -> { - final Class protocModelClass = FuzzUtil.getStaticFieldValue(clz, "PROTOC_MODEL_CLASS"); - - return FuzzUtil.>getStaticFieldValue(clz, "ARGUMENTS") - .stream() - .map(object -> new FuzzTestParams<>( - object, - protocModelClass - )); - }); + return MODEL_TEST_CLASSES.stream().flatMap(clz -> { + final Class protocModelClass = FuzzUtil.getStaticFieldValue(clz, "PROTOC_MODEL_CLASS"); + + return FuzzUtil.>getStaticFieldValue(clz, "ARGUMENTS").stream() + .map(object -> new FuzzTestParams<>(object, protocModelClass)); + }); } - private static record ResultStats( - double passRate, - double deserializationFailedMean - ) { + private static record ResultStats(double passRate, double deserializationFailedMean) { private static final NumberFormat PERCENTAGE_FORMAT = NumberFormat.getPercentInstance(); static { @@ -153,8 +139,7 @@ String format() { void fuzzTest() { assumeFalse( this.getClass().desiredAssertionStatus(), - "Fuzz tests run with assertions disabled only. Use the fuzzTest Gradle target." - ); + "Fuzz tests run with assertions disabled only. Use the fuzzTest Gradle target."); final Random random = buildRandom(); @@ -162,32 +147,24 @@ void fuzzTest() { final List> results = testCases() // Note that we must run this stream sequentially to enable // reproducing the tests for a given random seed. - .map(testCase -> FuzzTest.fuzzTest( - testCase.object(), - THRESHOLD, - random, - testCase.protocModelClass())) - .peek(result -> { if (debug) System.out.println(result.format()); }) + .map(testCase -> + FuzzTest.fuzzTest(testCase.object(), THRESHOLD, random, testCase.protocModelClass())) + .peek(result -> { + if (debug) System.out.println(result.format()); + }) .collect(Collectors.toList()); return results.stream() .map(result -> new ResultStats( - result.passed() ? 1. : 0., - result.percentageMap().getOrDefault(SingleFuzzTestResult.DESERIALIZATION_FAILED, 0.) - ) - ) - .reduce( - (r1, r2) -> new ResultStats( - r1.passRate() + r2.passRate(), - r1.deserializationFailedMean() + r2.deserializationFailedMean()) - ) + result.passed() ? 1. : 0., + result.percentageMap().getOrDefault(SingleFuzzTestResult.DESERIALIZATION_FAILED, 0.))) + .reduce((r1, r2) -> new ResultStats( + r1.passRate() + r2.passRate(), + r1.deserializationFailedMean() + r2.deserializationFailedMean())) .map(stats -> new ResultStats( - stats.passRate() / (double) results.size(), - stats.deserializationFailedMean() / (double) results.size() - ) - ) + stats.passRate() / (double) results.size(), + stats.deserializationFailedMean() / (double) results.size())) .orElse(new ResultStats(0., 0.)); - }); final String statsMessage = elapsedResultStats.result().format(); @@ -199,17 +176,15 @@ void fuzzTest() { } private Random buildRandom() { - final boolean useRandomSeed - = Boolean.valueOf(System.getProperty("com.hedera.pbj.integration.test.fuzz.useRandomSeed")); + final boolean useRandomSeed = + Boolean.valueOf(System.getProperty("com.hedera.pbj.integration.test.fuzz.useRandomSeed")); final long seed = useRandomSeed ? new Random().nextLong() : FIXED_RANDOM_SEED; System.out.println("Fuzz tests are configured to use a " + (useRandomSeed ? "RANDOM" : "FIXED") + " seed for `new Random(seed)`, and the seed value for this run is: " - + seed - ); + + seed); return new Random(seed); } - } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TestHashFunctions.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TestHashFunctions.java index 48be11a6..a8e08099 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TestHashFunctions.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TestHashFunctions.java @@ -3,8 +3,6 @@ import com.hedera.pbj.test.proto.pbj.Hasheval; import com.hedera.pbj.test.proto.pbj.TimestampTest; -import org.junit.jupiter.params.ParameterizedTest; -import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -14,8 +12,8 @@ public final class TestHashFunctions { public static int hash1(Hasheval hashEval) { try { - byte[] hash = MessageDigest.getInstance("SHA-256").digest( - Hasheval.PROTOBUF.toBytes(hashEval).toByteArray()); + byte[] hash = MessageDigest.getInstance("SHA-256") + .digest(Hasheval.PROTOBUF.toBytes(hashEval).toByteArray()); int res = hash[0] << 24 | hash[1] << 16 | hash[2] << 8 | hash[3]; return processForBetterDistribution(res); } catch (NoSuchAlgorithmException e) { @@ -82,7 +80,8 @@ public static int hash2(Hasheval hashEval) { result = 31 * result + hashEval.text().hashCode(); } if (hashEval.bytesField() != Hasheval.DEFAULT.bytesField()) { - result = 31 * result + (hashEval.bytesField() == null ? 0 : hashEval.bytesField().hashCode()); + result = 31 * result + + (hashEval.bytesField() == null ? 0 : hashEval.bytesField().hashCode()); } return processForBetterDistribution(result); diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TimestampTestTest.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TimestampTestTest.java index 4b5b5255..28fcecf0 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TimestampTestTest.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TimestampTestTest.java @@ -1,105 +1,105 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static com.hedera.pbj.runtime.ProtoTestTools.INTEGER_TESTS_LIST; +import static com.hedera.pbj.runtime.ProtoTestTools.LONG_TESTS_LIST; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalByteBuffer; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer2; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.google.protobuf.CodedOutputStream; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.test.NoToStringWrapper; import com.hedera.pbj.test.proto.pbj.TimestampTest; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import java.nio.ByteBuffer; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; -import static com.hedera.pbj.runtime.ProtoTestTools.INTEGER_TESTS_LIST; -import static com.hedera.pbj.runtime.ProtoTestTools.LONG_TESTS_LIST; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalByteBuffer; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer; -import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer2; -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Unit Test for TimestampTest model object. Generate based on protobuf schema. */ public final class TimestampTestTest { - @ParameterizedTest - @MethodSource("createModelTestArguments") - public void testTimestampTestAgainstProtoC(final NoToStringWrapper modelObjWrapper) throws Exception { - final TimestampTest modelObj = modelObjWrapper.getValue(); - // get reusable thread buffers - final BufferedData dataBuffer = getThreadLocalDataBuffer(); - final BufferedData dataBuffer2 = getThreadLocalDataBuffer2(); - final ByteBuffer byteBuffer = getThreadLocalByteBuffer(); - - // model to bytes with PBJ - TimestampTest.PROTOBUF.write(modelObj,dataBuffer); - // clamp limit to bytes written - dataBuffer.limit(dataBuffer.position()); + @ParameterizedTest + @MethodSource("createModelTestArguments") + public void testTimestampTestAgainstProtoC(final NoToStringWrapper modelObjWrapper) + throws Exception { + final TimestampTest modelObj = modelObjWrapper.getValue(); + // get reusable thread buffers + final BufferedData dataBuffer = getThreadLocalDataBuffer(); + final BufferedData dataBuffer2 = getThreadLocalDataBuffer2(); + final ByteBuffer byteBuffer = getThreadLocalByteBuffer(); - // copy bytes to ByteBuffer - dataBuffer.resetPosition(); - dataBuffer.readBytes(byteBuffer); - byteBuffer.flip(); + // model to bytes with PBJ + TimestampTest.PROTOBUF.write(modelObj, dataBuffer); + // clamp limit to bytes written + dataBuffer.limit(dataBuffer.position()); - // read proto bytes with ProtoC to make sure it is readable and no parse exceptions are thrown - final com.hedera.pbj.test.proto.java.TimestampTest protoCModelObj = com.hedera.pbj.test.proto.java.TimestampTest.parseFrom(byteBuffer); + // copy bytes to ByteBuffer + dataBuffer.resetPosition(); + dataBuffer.readBytes(byteBuffer); + byteBuffer.flip(); - // read proto bytes with PBJ parser - dataBuffer.resetPosition(); - final TimestampTest modelObj2 = TimestampTest.PROTOBUF.parse(dataBuffer); + // read proto bytes with ProtoC to make sure it is readable and no parse exceptions are thrown + final com.hedera.pbj.test.proto.java.TimestampTest protoCModelObj = + com.hedera.pbj.test.proto.java.TimestampTest.parseFrom(byteBuffer); - // check the read back object is equal to written original one - //assertEquals(modelObj.toString(), modelObj2.toString()); - assertEquals(modelObj, modelObj2); + // read proto bytes with PBJ parser + dataBuffer.resetPosition(); + final TimestampTest modelObj2 = TimestampTest.PROTOBUF.parse(dataBuffer); - // model to bytes with ProtoC writer - byteBuffer.clear(); - final CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteBuffer); - protoCModelObj.writeTo(codedOutput); - codedOutput.flush(); - byteBuffer.flip(); - // copy to a data buffer - dataBuffer2.writeBytes(byteBuffer); - dataBuffer2.flip(); + // check the read back object is equal to written original one + // assertEquals(modelObj.toString(), modelObj2.toString()); + assertEquals(modelObj, modelObj2); - // compare written bytes - assertEquals(dataBuffer, dataBuffer2); + // model to bytes with ProtoC writer + byteBuffer.clear(); + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteBuffer); + protoCModelObj.writeTo(codedOutput); + codedOutput.flush(); + byteBuffer.flip(); + // copy to a data buffer + dataBuffer2.writeBytes(byteBuffer); + dataBuffer2.flip(); - // parse those bytes again with PBJ - dataBuffer2.resetPosition(); - final TimestampTest modelObj3 = TimestampTest.PROTOBUF.parse(dataBuffer2); - assertEquals(modelObj, modelObj3); - } + // compare written bytes + assertEquals(dataBuffer, dataBuffer2); - /** - * List of all valid arguments for testing, built as a static list, so we can reuse it. - */ - public static final List ARGUMENTS; + // parse those bytes again with PBJ + dataBuffer2.resetPosition(); + final TimestampTest modelObj3 = TimestampTest.PROTOBUF.parse(dataBuffer2); + assertEquals(modelObj, modelObj3); + } - static { - final var secondsList = LONG_TESTS_LIST; - final var nanosList = INTEGER_TESTS_LIST; - // work out the longest of all the lists of args as that is how many test cases we need - final int maxValues = IntStream.of( - secondsList.size(), - nanosList.size() - ).max().getAsInt(); - // create new stream of model objects using lists above as constructor params - ARGUMENTS = IntStream.range(0,maxValues) - .mapToObj(i -> new TimestampTest( - secondsList.get(Math.min(i, secondsList.size()-1)), - nanosList.get(Math.min(i, nanosList.size()-1)) - )).toList(); - } + /** + * List of all valid arguments for testing, built as a static list, so we can reuse it. + */ + public static final List ARGUMENTS; - /** - * Create a stream of all test permutations of the TimestampTest class we are testing. This is reused by other tests - * as well that have model objects with fields of this type. - * - * @return stream of model objects for all test cases - */ - public static Stream> createModelTestArguments() { - return ARGUMENTS.stream().map(NoToStringWrapper::new); - } + static { + final var secondsList = LONG_TESTS_LIST; + final var nanosList = INTEGER_TESTS_LIST; + // work out the longest of all the lists of args as that is how many test cases we need + final int maxValues = + IntStream.of(secondsList.size(), nanosList.size()).max().getAsInt(); + // create new stream of model objects using lists above as constructor params + ARGUMENTS = IntStream.range(0, maxValues) + .mapToObj(i -> new TimestampTest( + secondsList.get(Math.min(i, secondsList.size() - 1)), + nanosList.get(Math.min(i, nanosList.size() - 1)))) + .toList(); + } + /** + * Create a stream of all test permutations of the TimestampTest class we are testing. This is reused by other tests + * as well that have model objects with fields of this type. + * + * @return stream of model objects for all test cases + */ + public static Stream> createModelTestArguments() { + return ARGUMENTS.stream().map(NoToStringWrapper::new); + } } diff --git a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TruncatedDataTests.java b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TruncatedDataTests.java index d8dd1ff2..7a85ab1f 100644 --- a/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TruncatedDataTests.java +++ b/pbj-integration-tests/src/test/java/com/hedera/pbj/integration/test/TruncatedDataTests.java @@ -1,21 +1,20 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.pbj.integration.test; +import static org.junit.jupiter.api.Assertions.*; + import com.google.protobuf.InvalidProtocolBufferException; import com.hedera.pbj.runtime.ProtoParserTools; import com.hedera.pbj.runtime.io.buffer.BufferedData; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.hedera.pbj.test.proto.pbj.Everything; +import java.util.HexFormat; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.util.HexFormat; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - final class TruncatedDataTests { // ================================================================================================================ // Verify common comments. @@ -24,12 +23,13 @@ final class TruncatedDataTests { @DisplayName("Issue 96") void issue96() { final var unhexed = HexFormat.of().parseHex(testData); - assertThrows(InvalidProtocolBufferException.class, () -> - com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); - assertThrows(Exception.class, () -> - com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parseStrict( + assertThrows( + InvalidProtocolBufferException.class, + () -> com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); + assertThrows( + Exception.class, + () -> com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parseStrict( BufferedData.wrap(unhexed))); - } @ParameterizedTest @@ -40,8 +40,7 @@ void testBoxedFloat(final int value) { Bytes bytes = Everything.PROTOBUF.toBytes(ev); assertThrows(Exception.class, () -> { final Bytes b = bytes.slice(0, bytes.length() + value); - Everything.PROTOBUF.parseStrict( - BufferedData.wrap(b.toByteArray())); + Everything.PROTOBUF.parseStrict(BufferedData.wrap(b.toByteArray())); }); } @@ -53,8 +52,7 @@ void testBoxedInt32(final int value) { Bytes bytes = Everything.PROTOBUF.toBytes(ev); assertThrows(Exception.class, () -> { final Bytes b = bytes.slice(0, bytes.length() + value); - Everything.PROTOBUF.parseStrict( - BufferedData.wrap(b.toByteArray())); + Everything.PROTOBUF.parseStrict(BufferedData.wrap(b.toByteArray())); }); } @@ -66,8 +64,7 @@ void testBoxedInt64(final int value) { Bytes bytes = Everything.PROTOBUF.toBytes(ev); assertThrows(Exception.class, () -> { final Bytes b = bytes.slice(0, bytes.length() + value); - Everything.PROTOBUF.parseStrict( - BufferedData.wrap(b.toByteArray())); + Everything.PROTOBUF.parseStrict(BufferedData.wrap(b.toByteArray())); }); } @@ -79,8 +76,7 @@ void testNumberInt64(final int value) { Bytes bytes = Everything.PROTOBUF.toBytes(ev); assertThrows(Exception.class, () -> { final Bytes b = bytes.slice(0, bytes.length() + value); - Everything.PROTOBUF.parseStrict( - BufferedData.wrap(b.toByteArray())); + Everything.PROTOBUF.parseStrict(BufferedData.wrap(b.toByteArray())); }); } @@ -311,29 +307,25 @@ void testFixedInt64(final int value) { @DisplayName("Test readUint32Strict") void testUint32Strict() { final var unhexed = HexFormat.of().parseHex(""); - assertDoesNotThrow(() -> - com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); + assertDoesNotThrow(() -> com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); // empty object is valid assertDoesNotThrow(() -> - com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parseStrict( - BufferedData.wrap(unhexed))); + com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parseStrict(BufferedData.wrap(unhexed))); } @Test @DisplayName("Test readUint32NonStrict") void testUint32NonStrict() { final var unhexed = HexFormat.of().parseHex(""); - assertDoesNotThrow(() -> - com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); - assertDoesNotThrow(() -> - com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parse( - BufferedData.wrap(unhexed))); + assertDoesNotThrow(() -> com.hederahashgraph.api.proto.java.ServicesConfigurationList.parseFrom(unhexed)); + assertDoesNotThrow( + () -> com.hedera.hapi.node.base.ServicesConfigurationList.PROTOBUF.parse(BufferedData.wrap(unhexed))); } static Stream createTruncateTestArguments() { - return Stream.of( - Integer.MIN_VALUE, (int)Byte.MIN_VALUE, -100, -66, -1, -2, -3, -4, -6, -7, -999, -1000); + return Stream.of(Integer.MIN_VALUE, (int) Byte.MIN_VALUE, -100, -66, -1, -2, -3, -4, -6, -7, -999, -1000); } - public static final String testData = "0a190a1266696c65732e6665655363686564756c657312033131310a310a29636f6e7472616374732e707265636f6d70696c652e687473456e61626c65546f6b656e4372656174651204747275650a230a1c746f6b656e732e6d6178546f6b656e4e616d6555746638427974657312033130300a1f0a16746f6b656e732e73746f726552656c734f6e4469736b120566616c73650a260a2072617465732e696e7472616461794368616e67654c696d697450657263656e74120232350a230a1e7374616b696e672e72657761726442616c616e63655468726573686f6c641201300a2a0a24636f6e7472616374732e6d6178526566756e6450657263656e744f664761734c696d6974120232300a2d0a267374616b696e672e726577617264486973746f72792e6e756d53746f726564506572696f647312033336350a1a0a146163636f756e74732e73797374656d41646d696e120235300a280a21666565732e746f6b656e5472616e7366657255736167654d756c7469706c69657212033338300a1c0a146175746f4372656174696f6e2e656e61626c65641204747275650a1e0a18666565732e6d696e436f6e67657374696f6e506572696f64120236300a1a0a1366696c65732e65786368616e6765526174657312033131320a280a1a626f6f7473747261702e72617465732e6e657874457870697279120a343130323434343830300a1a0a146163636f756e74732e667265657a6541646d696e120235380a1e0a166865646572612e666972737455736572456e746974791204313030310a370a1f636f6e7472616374732e73746f72616765536c6f745072696365546965727312143074696c3130304d2c3230303074696c3435304d0a270a2174726163656162696c6974792e6d61784578706f727473506572436f6e73536563120231300a220a1c6163636f756e74732e73797374656d556e64656c65746541646d696e120236300a280a1f636f6e7472616374732e616c6c6f774175746f4173736f63696174696f6e73120566616c73650a320a2b6865646572612e7265636f726453747265616d2e6e756d4f66426c6f636b486173686573496e537461746512033235360a2e0a256865646572612e776f726b666c6f772e766572696669636174696f6e54696d656f75744d53120532303030300a1c0a146163636f756e74732e73746f72654f6e4469736b1204747275650a280a216865646572612e616c6c6f77616e6365732e6d61784163636f756e744c696d697412033130300a2b0a256865646572612e616c6c6f77616e6365732e6d61785472616e73616374696f6e4c696d6974120232300a2b0a25636f6e73656e7375732e6d6573736167652e6d6178466f6c6c6f77696e675265636f726473120235300a2a0a236865646572612e7472616e73616374696f6e2e6d617856616c69644475726174696f6e12033138300a490a0c76657273696f6e2e68617069123953656d616e74696356657273696f6e5b6d616a6f723d302c206d696e6f723d34302c2070617463683d302c207072653d2c206275696c643d5d0a240a1d6163636f756e74732e7374616b696e675265776172644163636f756e7412033830300a310a2c6175746f72656e65772e6d61784e756d6265724f66456e746974696573546f52656e65774f7244656c6574651201320a380a217374616b696e672e6d61784461696c795374616b655265776172645468506572481213393232333337323033363835343737353830370a2b0a1f636f6e7472616374732e7265666572656e6365536c6f744c69666574696d65120833313533363030300a2d0a226c65646765722e6175746f52656e6577506572696f642e6d696e4475726174696f6e1207323539323030300a4d0a1076657273696f6e2e7365727669636573123953656d616e74696356657273696f6e5b6d616a6f723d302c206d696e6f723d34302c2070617463683d302c207072653d2c206275696c643d5d0a3a0a31636f6e7472616374732e707265636f6d70696c652e61746f6d696343727970746f5472616e736665722e656e61626c6564120566616c73650a220a14656e7469746965732e6d61784c69666574696d65120a333135333630303030300a260a1d636f6e7472616374732e65766d2e76657273696f6e2e64796e616d6963120566616c73650a2b0a22636f6e7472616374732e7369646563617256616c69646174696f6e456e61626c6564120566616c73650a210a1a6163636f756e74732e6e6f64655265776172644163636f756e7412033830310a180a11636f6e7472616374732e636861696e496412033239350a270a216c65646765722e6368616e6765486973746f7269616e2e6d656d6f727953656373120232300a290a21636f6e73656e7375732e6d6573736167652e6d61784279746573416c6c6f7765641204313032340a180a1166696c65732e61646472657373426f6f6b12033130310a200a1a6163636f756e74732e73797374656d44656c65746541646d696e120235390a380a30636f6e7472616374732e707265636f6d70696c652e6872634661636164652e6173736f63696174652e656e61626c65641204747275650a220a1b6163636f756e74732e6c6173745468726f74746c654578656d707412033130300a1e0a16746f6b656e732e6e6674732e617265456e61626c65641204747275650a1b0a10746f706963732e6d61784e756d6265721207313030303030300a200a1a6c65646765722e6e66745472616e73666572732e6d61784c656e120231300a2a0a25636f6e73656e7375732e6d6573736167652e6d6178507265636564696e675265636f7264731201330a190a117374616b696e672e6973456e61626c65641204747275650a260a1b746f6b656e732e6e6674732e6d6178416c6c6f7765644d696e74731207353030303030300a2f0a187374616b696e672e6d61785374616b6552657761726465641213353030303030303030303030303030303030300a2b0a1d626f6f7473747261702e72617465732e63757272656e74457870697279120a343130323434343830300a1e0a1766696c65732e7570677261646546696c654e756d62657212033135300a240a19636f6e7472616374732e64656661756c744c69666574696d651207373839303030300a260a217374616b696e672e666565732e6e6f646552657761726450657263656e746167651201300a200a19746f6b656e732e6d617853796d626f6c55746638427974657312033130300a250a1d736967732e657870616e6446726f6d496d6d757461626c6553746174651204747275650a170a127374616b696e672e726577617264526174651201300a2b0a1d626f6f7473747261702e73797374656d2e656e74697479457870697279120a313831323633373638360a1f0a196163636f756e74732e61646472657373426f6f6b41646d696e120235350a2b0a246865646572612e7265636f726453747265616d2e736964656361724d617853697a654d6212033235360a300a257363686564756c696e672e6d617845787069726174696f6e4675747572655365636f6e64731207353335363830300a2a0a21636f6e7472616374732e656e666f7263654372656174696f6e5468726f74746c65120566616c73650a1c0a14746f6b656e732e6d61785065724163636f756e741204313030300a1c0a1566696c65732e686170695065726d697373696f6e7312033132320a2d0a286865646572612e7265636f726453747265616d2e7369676e617475726546696c6556657273696f6e1201360a200a19746f6b656e732e6e6674732e6d6178517565727952616e676512033130300a1d0a176c65646765722e7472616e73666572732e6d61784c656e120231300a230a1a6163636f756e74732e626c6f636b6c6973742e656e61626c6564120566616c73650a200a1b72617465732e6d69646e69676874436865636b496e74657276616c1201310a2f0a2a74726163656162696c6974792e6d696e46726565546f557365644761735468726f74746c65526174696f1201390a340a266865646572612e7265636f726453747265616d2e73747265616d46696c6550726f6475636572120a636f6e63757272656e740a220a1c746f6b656e732e6e6674732e6d6178426174636853697a6557697065120231300a330a2b6865646572612e7265636f726453747265616d2e636f6d707265737346696c65734f6e4372656174696f6e1204747275650a1a0a127374616b696e672e706572696f644d696e731204313434300a240a1b6175746f72656e65772e6772616e744672656552656e6577616c73120566616c73650a2b0a1e636f6e7472616374732e6d61784b7650616972732e61676772656761746512093530303030303030300a220a1c746f6b656e732e6e6674732e6d6178426174636853697a654d696e74120231300a240a1d7374616b696e672e73756d4f66436f6e73656e7375735765696768747312033530300a210a1b746f6b656e732e6d6178437573746f6d46656573416c6c6f776564120231300a1c0a146c617a794372656174696f6e2e656e61626c65641204747275650a1b0a10746f6b656e732e6d61784e756d6265721207313030303030300a1d0a126163636f756e74732e6d61784e756d6265721207353030303030300a240a1c636f6e7472616374732e6974656d697a6553746f72616765466565731204747275650a230a1b6865646572612e616c6c6f77616e6365732e6973456e61626c65641204747275650a380a23626f6f7473747261702e6665655363686564756c65734a736f6e2e7265736f7572636512116665655363686564756c65732e6a736f6e0a2b0a246c65646765722e7265636f7264732e6d6178517565727961626c6542794163636f756e7412033138300a220a16636f6e7472616374732e6d6178476173506572536563120831353030303030300a300a28636f6e7472616374732e707265636f6d70696c652e6578706f72745265636f7264526573756c74731204747275650a1b0a156175746f52656e65772e746172676574547970657312025b5d0a270a22636f6e7472616374732e6d61784e756d5769746848617069536967734163636573731201300a280a20636f6e7472616374732e7468726f74746c652e7468726f74746c6542794761731204747275650a230a17746f6b656e732e6d617841676772656761746552656c73120831303030303030300a260a20626f6f7473747261702e72617465732e63757272656e7443656e744571756976120231320a290a236865646572612e7472616e73616374696f6e2e6d696e56616c69644475726174696f6e120231350a510a12636f6e7472616374732e7369646563617273123b5b434f4e54524143545f53544154455f4348414e47452c20434f4e54524143545f414354494f4e2c20434f4e54524143545f42595445434f44455d0a1b0a156c65646765722e66756e64696e674163636f756e74120239380a230a1a7363686564756c696e672e6c6f6e675465726d456e61626c6564120566616c73650a220a1a6c65646765722e6d61784175746f4173736f63696174696f6e731204353030300a1e0a16636f6e7472616374"; + public static final String testData = + "0a190a1266696c65732e6665655363686564756c657312033131310a310a29636f6e7472616374732e707265636f6d70696c652e687473456e61626c65546f6b656e4372656174651204747275650a230a1c746f6b656e732e6d6178546f6b656e4e616d6555746638427974657312033130300a1f0a16746f6b656e732e73746f726552656c734f6e4469736b120566616c73650a260a2072617465732e696e7472616461794368616e67654c696d697450657263656e74120232350a230a1e7374616b696e672e72657761726442616c616e63655468726573686f6c641201300a2a0a24636f6e7472616374732e6d6178526566756e6450657263656e744f664761734c696d6974120232300a2d0a267374616b696e672e726577617264486973746f72792e6e756d53746f726564506572696f647312033336350a1a0a146163636f756e74732e73797374656d41646d696e120235300a280a21666565732e746f6b656e5472616e7366657255736167654d756c7469706c69657212033338300a1c0a146175746f4372656174696f6e2e656e61626c65641204747275650a1e0a18666565732e6d696e436f6e67657374696f6e506572696f64120236300a1a0a1366696c65732e65786368616e6765526174657312033131320a280a1a626f6f7473747261702e72617465732e6e657874457870697279120a343130323434343830300a1a0a146163636f756e74732e667265657a6541646d696e120235380a1e0a166865646572612e666972737455736572456e746974791204313030310a370a1f636f6e7472616374732e73746f72616765536c6f745072696365546965727312143074696c3130304d2c3230303074696c3435304d0a270a2174726163656162696c6974792e6d61784578706f727473506572436f6e73536563120231300a220a1c6163636f756e74732e73797374656d556e64656c65746541646d696e120236300a280a1f636f6e7472616374732e616c6c6f774175746f4173736f63696174696f6e73120566616c73650a320a2b6865646572612e7265636f726453747265616d2e6e756d4f66426c6f636b486173686573496e537461746512033235360a2e0a256865646572612e776f726b666c6f772e766572696669636174696f6e54696d656f75744d53120532303030300a1c0a146163636f756e74732e73746f72654f6e4469736b1204747275650a280a216865646572612e616c6c6f77616e6365732e6d61784163636f756e744c696d697412033130300a2b0a256865646572612e616c6c6f77616e6365732e6d61785472616e73616374696f6e4c696d6974120232300a2b0a25636f6e73656e7375732e6d6573736167652e6d6178466f6c6c6f77696e675265636f726473120235300a2a0a236865646572612e7472616e73616374696f6e2e6d617856616c69644475726174696f6e12033138300a490a0c76657273696f6e2e68617069123953656d616e74696356657273696f6e5b6d616a6f723d302c206d696e6f723d34302c2070617463683d302c207072653d2c206275696c643d5d0a240a1d6163636f756e74732e7374616b696e675265776172644163636f756e7412033830300a310a2c6175746f72656e65772e6d61784e756d6265724f66456e746974696573546f52656e65774f7244656c6574651201320a380a217374616b696e672e6d61784461696c795374616b655265776172645468506572481213393232333337323033363835343737353830370a2b0a1f636f6e7472616374732e7265666572656e6365536c6f744c69666574696d65120833313533363030300a2d0a226c65646765722e6175746f52656e6577506572696f642e6d696e4475726174696f6e1207323539323030300a4d0a1076657273696f6e2e7365727669636573123953656d616e74696356657273696f6e5b6d616a6f723d302c206d696e6f723d34302c2070617463683d302c207072653d2c206275696c643d5d0a3a0a31636f6e7472616374732e707265636f6d70696c652e61746f6d696343727970746f5472616e736665722e656e61626c6564120566616c73650a220a14656e7469746965732e6d61784c69666574696d65120a333135333630303030300a260a1d636f6e7472616374732e65766d2e76657273696f6e2e64796e616d6963120566616c73650a2b0a22636f6e7472616374732e7369646563617256616c69646174696f6e456e61626c6564120566616c73650a210a1a6163636f756e74732e6e6f64655265776172644163636f756e7412033830310a180a11636f6e7472616374732e636861696e496412033239350a270a216c65646765722e6368616e6765486973746f7269616e2e6d656d6f727953656373120232300a290a21636f6e73656e7375732e6d6573736167652e6d61784279746573416c6c6f7765641204313032340a180a1166696c65732e61646472657373426f6f6b12033130310a200a1a6163636f756e74732e73797374656d44656c65746541646d696e120235390a380a30636f6e7472616374732e707265636f6d70696c652e6872634661636164652e6173736f63696174652e656e61626c65641204747275650a220a1b6163636f756e74732e6c6173745468726f74746c654578656d707412033130300a1e0a16746f6b656e732e6e6674732e617265456e61626c65641204747275650a1b0a10746f706963732e6d61784e756d6265721207313030303030300a200a1a6c65646765722e6e66745472616e73666572732e6d61784c656e120231300a2a0a25636f6e73656e7375732e6d6573736167652e6d6178507265636564696e675265636f7264731201330a190a117374616b696e672e6973456e61626c65641204747275650a260a1b746f6b656e732e6e6674732e6d6178416c6c6f7765644d696e74731207353030303030300a2f0a187374616b696e672e6d61785374616b6552657761726465641213353030303030303030303030303030303030300a2b0a1d626f6f7473747261702e72617465732e63757272656e74457870697279120a343130323434343830300a1e0a1766696c65732e7570677261646546696c654e756d62657212033135300a240a19636f6e7472616374732e64656661756c744c69666574696d651207373839303030300a260a217374616b696e672e666565732e6e6f646552657761726450657263656e746167651201300a200a19746f6b656e732e6d617853796d626f6c55746638427974657312033130300a250a1d736967732e657870616e6446726f6d496d6d757461626c6553746174651204747275650a170a127374616b696e672e726577617264526174651201300a2b0a1d626f6f7473747261702e73797374656d2e656e74697479457870697279120a313831323633373638360a1f0a196163636f756e74732e61646472657373426f6f6b41646d696e120235350a2b0a246865646572612e7265636f726453747265616d2e736964656361724d617853697a654d6212033235360a300a257363686564756c696e672e6d617845787069726174696f6e4675747572655365636f6e64731207353335363830300a2a0a21636f6e7472616374732e656e666f7263654372656174696f6e5468726f74746c65120566616c73650a1c0a14746f6b656e732e6d61785065724163636f756e741204313030300a1c0a1566696c65732e686170695065726d697373696f6e7312033132320a2d0a286865646572612e7265636f726453747265616d2e7369676e617475726546696c6556657273696f6e1201360a200a19746f6b656e732e6e6674732e6d6178517565727952616e676512033130300a1d0a176c65646765722e7472616e73666572732e6d61784c656e120231300a230a1a6163636f756e74732e626c6f636b6c6973742e656e61626c6564120566616c73650a200a1b72617465732e6d69646e69676874436865636b496e74657276616c1201310a2f0a2a74726163656162696c6974792e6d696e46726565546f557365644761735468726f74746c65526174696f1201390a340a266865646572612e7265636f726453747265616d2e73747265616d46696c6550726f6475636572120a636f6e63757272656e740a220a1c746f6b656e732e6e6674732e6d6178426174636853697a6557697065120231300a330a2b6865646572612e7265636f726453747265616d2e636f6d707265737346696c65734f6e4372656174696f6e1204747275650a1a0a127374616b696e672e706572696f644d696e731204313434300a240a1b6175746f72656e65772e6772616e744672656552656e6577616c73120566616c73650a2b0a1e636f6e7472616374732e6d61784b7650616972732e61676772656761746512093530303030303030300a220a1c746f6b656e732e6e6674732e6d6178426174636853697a654d696e74120231300a240a1d7374616b696e672e73756d4f66436f6e73656e7375735765696768747312033530300a210a1b746f6b656e732e6d6178437573746f6d46656573416c6c6f776564120231300a1c0a146c617a794372656174696f6e2e656e61626c65641204747275650a1b0a10746f6b656e732e6d61784e756d6265721207313030303030300a1d0a126163636f756e74732e6d61784e756d6265721207353030303030300a240a1c636f6e7472616374732e6974656d697a6553746f72616765466565731204747275650a230a1b6865646572612e616c6c6f77616e6365732e6973456e61626c65641204747275650a380a23626f6f7473747261702e6665655363686564756c65734a736f6e2e7265736f7572636512116665655363686564756c65732e6a736f6e0a2b0a246c65646765722e7265636f7264732e6d6178517565727961626c6542794163636f756e7412033138300a220a16636f6e7472616374732e6d6178476173506572536563120831353030303030300a300a28636f6e7472616374732e707265636f6d70696c652e6578706f72745265636f7264526573756c74731204747275650a1b0a156175746f52656e65772e746172676574547970657312025b5d0a270a22636f6e7472616374732e6d61784e756d5769746848617069536967734163636573731201300a280a20636f6e7472616374732e7468726f74746c652e7468726f74746c6542794761731204747275650a230a17746f6b656e732e6d617841676772656761746552656c73120831303030303030300a260a20626f6f7473747261702e72617465732e63757272656e7443656e744571756976120231320a290a236865646572612e7472616e73616374696f6e2e6d696e56616c69644475726174696f6e120231350a510a12636f6e7472616374732e7369646563617273123b5b434f4e54524143545f53544154455f4348414e47452c20434f4e54524143545f414354494f4e2c20434f4e54524143545f42595445434f44455d0a1b0a156c65646765722e66756e64696e674163636f756e74120239380a230a1a7363686564756c696e672e6c6f6e675465726d456e61626c6564120566616c73650a220a1a6c65646765722e6d61784175746f4173736f63696174696f6e731204353030300a1e0a16636f6e7472616374"; }