diff options
Diffstat (limited to 'third_party/protobuf/3.2.0/conformance/ConformanceJava.java')
-rw-r--r-- | third_party/protobuf/3.2.0/conformance/ConformanceJava.java | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/third_party/protobuf/3.2.0/conformance/ConformanceJava.java b/third_party/protobuf/3.2.0/conformance/ConformanceJava.java new file mode 100644 index 0000000000..7badf2a5f5 --- /dev/null +++ b/third_party/protobuf/3.2.0/conformance/ConformanceJava.java @@ -0,0 +1,315 @@ +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.conformance.Conformance; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf_test_messages.proto3.TestMessagesProto3; +import com.google.protobuf.util.JsonFormat; +import com.google.protobuf.util.JsonFormat.TypeRegistry; +import java.io.IOException; +import java.nio.ByteBuffer; + +class ConformanceJava { + private int testCount = 0; + private TypeRegistry typeRegistry; + + private boolean readFromStdin(byte[] buf, int len) throws Exception { + int ofs = 0; + while (len > 0) { + int read = System.in.read(buf, ofs, len); + if (read == -1) { + return false; // EOF + } + ofs += read; + len -= read; + } + + return true; + } + + private void writeToStdout(byte[] buf) throws Exception { + System.out.write(buf); + } + + // Returns -1 on EOF (the actual values will always be positive). + private int readLittleEndianIntFromStdin() throws Exception { + byte[] buf = new byte[4]; + if (!readFromStdin(buf, 4)) { + return -1; + } + return (buf[0] & 0xff) + | ((buf[1] & 0xff) << 8) + | ((buf[2] & 0xff) << 16) + | ((buf[3] & 0xff) << 24); + } + + private void writeLittleEndianIntToStdout(int val) throws Exception { + byte[] buf = new byte[4]; + buf[0] = (byte)val; + buf[1] = (byte)(val >> 8); + buf[2] = (byte)(val >> 16); + buf[3] = (byte)(val >> 24); + writeToStdout(buf); + } + + private enum BinaryDecoder { + BYTE_STRING_DECODER() { + @Override + public TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + return TestMessagesProto3.TestAllTypes.parseFrom(bytes); + } + }, + BYTE_ARRAY_DECODER() { + @Override + public TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + return TestMessagesProto3.TestAllTypes.parseFrom(bytes.toByteArray()); + } + }, + ARRAY_BYTE_BUFFER_DECODER() { + @Override + public TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return TestMessagesProto3.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 TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + try { + return TestMessagesProto3.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 TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return TestMessagesProto3.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 TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + try { + return TestMessagesProto3.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 TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException { + try { + return TestMessagesProto3.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 TestMessagesProto3.TestAllTypes parse(ByteString bytes) + throws InvalidProtocolBufferException; + } + + private TestMessagesProto3.TestAllTypes parseBinary(ByteString bytes) + throws InvalidProtocolBufferException { + TestMessagesProto3.TestAllTypes[] messages = + new TestMessagesProto3.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) { + TestMessagesProto3.TestAllTypes testMessage; + + switch (request.getPayloadCase()) { + case PROTOBUF_PAYLOAD: { + try { + testMessage = parseBinary(request.getProtobufPayload()); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); + } + break; + } + case JSON_PAYLOAD: { + try { + TestMessagesProto3.TestAllTypes.Builder builder = TestMessagesProto3.TestAllTypes.newBuilder(); + JsonFormat.parser().usingTypeRegistry(typeRegistry) + .merge(request.getJsonPayload(), builder); + testMessage = builder.build(); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); + } + break; + } + case PAYLOAD_NOT_SET: { + throw new RuntimeException("Request didn't have payload."); + } + + default: { + throw new RuntimeException("Unexpected payload case."); + } + } + + switch (request.getRequestedOutputFormat()) { + case UNSPECIFIED: + throw new RuntimeException("Unspecified output format."); + + case PROTOBUF: + return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build(); + + case JSON: + try { + return Conformance.ConformanceResponse.newBuilder().setJsonPayload( + JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build(); + } catch (InvalidProtocolBufferException | IllegalArgumentException e) { + return Conformance.ConformanceResponse.newBuilder().setSerializeError( + e.getMessage()).build(); + } + + default: { + throw new RuntimeException("Unexpected request output."); + } + } + } + + private boolean doTestIo() throws Exception { + int bytes = readLittleEndianIntFromStdin(); + + if (bytes == -1) { + return false; // EOF + } + + byte[] serializedInput = new byte[bytes]; + + if (!readFromStdin(serializedInput, bytes)) { + throw new RuntimeException("Unexpected EOF from test program."); + } + + Conformance.ConformanceRequest request = + Conformance.ConformanceRequest.parseFrom(serializedInput); + Conformance.ConformanceResponse response = doTest(request); + byte[] serializedOutput = response.toByteArray(); + + writeLittleEndianIntToStdout(serializedOutput.length); + writeToStdout(serializedOutput); + + return true; + } + + public void run() throws Exception { + typeRegistry = TypeRegistry.newBuilder().add( + TestMessagesProto3.TestAllTypes.getDescriptor()).build(); + while (doTestIo()) { + this.testCount++; + } + + System.err.println("ConformanceJava: received EOF from test runner after " + + this.testCount + " tests"); + } + + public static void main(String[] args) throws Exception { + new ConformanceJava().run(); + } +} |