diff options
author | Adam Cozzette <acozzette@google.com> | 2016-11-17 16:48:38 -0800 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2016-11-17 16:59:59 -0800 |
commit | 5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74 (patch) | |
tree | 0276f81f8848a05d84cd7e287b43d665e30f04e3 /conformance/ConformanceJava.java | |
parent | e28286fa05d8327fd6c5aa70cfb3be558f0932b8 (diff) | |
download | protobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.tar.gz protobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.tar.bz2 protobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.zip |
Integrated internal changes from Google
Diffstat (limited to 'conformance/ConformanceJava.java')
-rw-r--r-- | conformance/ConformanceJava.java | 180 |
1 files changed, 176 insertions, 4 deletions
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java index 43787ffc..24d206cb 100644 --- a/conformance/ConformanceJava.java +++ b/conformance/ConformanceJava.java @@ -1,8 +1,11 @@ - +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.conformance.Conformance; -import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat.TypeRegistry; -import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import java.io.IOException; +import java.nio.ByteBuffer; class ConformanceJava { private int testCount = 0; @@ -47,13 +50,182 @@ class ConformanceJava { writeToStdout(buf); } + private enum BinaryDecoder { + BYTE_STRING_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + return Conformance.TestAllTypes.parseFrom(bytes); + } + }, + BYTE_ARRAY_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + return Conformance.TestAllTypes.parseFrom(bytes.toByteArray()); + } + }, + ARRAY_BYTE_BUFFER_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return Conformance.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer)); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "ByteString based ByteBuffer should not throw IOException.", e); + } + } + }, + READONLY_ARRAY_BYTE_BUFFER_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + try { + return Conformance.TestAllTypes.parseFrom( + CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer())); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "ByteString based ByteBuffer should not throw IOException.", e); + } + } + }, + DIRECT_BYTE_BUFFER_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return Conformance.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer)); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "ByteString based ByteBuffer should not throw IOException.", e); + } + } + }, + READONLY_DIRECT_BYTE_BUFFER_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return Conformance.TestAllTypes.parseFrom( + CodedInputStream.newInstance(buffer.asReadOnlyBuffer())); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "ByteString based ByteBuffer should not throw IOException.", e); + } + } + }, + INPUT_STREAM_DECODER() { + @Override + public Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + try { + return Conformance.TestAllTypes.parseFrom(bytes.newInput()); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "ByteString based InputStream should not throw IOException.", e); + } + } + }; + + public abstract Conformance.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException; + } + + private Conformance.TestAllTypes parseBinary(ByteString bytes) + throws InvalidProtocolBufferException { + Conformance.TestAllTypes[] messages = + new Conformance.TestAllTypes[BinaryDecoder.values().length]; + InvalidProtocolBufferException[] exceptions = + new InvalidProtocolBufferException[BinaryDecoder.values().length]; + + boolean hasMessage = false; + boolean hasException = false; + for (int i = 0; i < BinaryDecoder.values().length; ++i) { + try { + messages[i] = BinaryDecoder.values()[i].parse(bytes); + hasMessage = true; + } catch (InvalidProtocolBufferException e) { + exceptions[i] = e; + hasException = true; + } + } + + if (hasMessage && hasException) { + StringBuilder sb = + new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n"); + for (int i = 0; i < BinaryDecoder.values().length; ++i) { + sb.append(BinaryDecoder.values()[i].name()); + if (messages[i] != null) { + sb.append(" accepted the payload.\n"); + } else { + sb.append(" rejected the payload.\n"); + } + } + throw new RuntimeException(sb.toString()); + } + + if (hasException) { + // We do not check if exceptions are equal. Different implementations may return different + // exception messages. Throw an arbitrary one out instead. + throw exceptions[0]; + } + + // Fast path comparing all the messages with the first message, assuming equality being + // symmetric and transitive. + boolean allEqual = true; + for (int i = 1; i < messages.length; ++i) { + if (!messages[0].equals(messages[i])) { + allEqual = false; + break; + } + } + + // Slow path: compare and find out all unequal pairs. + if (!allEqual) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < messages.length - 1; ++i) { + for (int j = i + 1; j < messages.length; ++j) { + if (!messages[i].equals(messages[j])) { + sb.append(BinaryDecoder.values()[i].name()) + .append(" and ") + .append(BinaryDecoder.values()[j].name()) + .append(" parsed the payload differently.\n"); + } + } + } + throw new RuntimeException(sb.toString()); + } + + return messages[0]; + } + private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { Conformance.TestAllTypes testMessage; switch (request.getPayloadCase()) { case PROTOBUF_PAYLOAD: { try { - testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload()); + testMessage = parseBinary(request.getProtobufPayload()); } catch (InvalidProtocolBufferException e) { return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); } |