1*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format 2*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc. All rights reserved. 3*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/ 4*1b3f573fSAndroid Build Coastguard Worker // 5*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without 6*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are 7*1b3f573fSAndroid Build Coastguard Worker // met: 8*1b3f573fSAndroid Build Coastguard Worker // 9*1b3f573fSAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright 10*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer. 11*1b3f573fSAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above 12*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer 13*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the 14*1b3f573fSAndroid Build Coastguard Worker // distribution. 15*1b3f573fSAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its 16*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from 17*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission. 18*1b3f573fSAndroid Build Coastguard Worker // 19*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*1b3f573fSAndroid Build Coastguard Worker 31*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.AbstractMessage; 32*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.ByteString; 33*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.CodedInputStream; 34*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.ExtensionRegistry; 35*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.InvalidProtocolBufferException; 36*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.Parser; 37*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.TextFormat; 38*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.conformance.Conformance; 39*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.util.JsonFormat; 40*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf.util.JsonFormat.TypeRegistry; 41*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf_test_messages.proto2.TestMessagesProto2; 42*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2; 43*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf_test_messages.proto3.TestMessagesProto3; 44*1b3f573fSAndroid Build Coastguard Worker import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3; 45*1b3f573fSAndroid Build Coastguard Worker import java.nio.ByteBuffer; 46*1b3f573fSAndroid Build Coastguard Worker import java.util.ArrayList; 47*1b3f573fSAndroid Build Coastguard Worker 48*1b3f573fSAndroid Build Coastguard Worker class ConformanceJava { 49*1b3f573fSAndroid Build Coastguard Worker private int testCount = 0; 50*1b3f573fSAndroid Build Coastguard Worker private TypeRegistry typeRegistry; 51*1b3f573fSAndroid Build Coastguard Worker readFromStdin(byte[] buf, int len)52*1b3f573fSAndroid Build Coastguard Worker private boolean readFromStdin(byte[] buf, int len) throws Exception { 53*1b3f573fSAndroid Build Coastguard Worker int ofs = 0; 54*1b3f573fSAndroid Build Coastguard Worker while (len > 0) { 55*1b3f573fSAndroid Build Coastguard Worker int read = System.in.read(buf, ofs, len); 56*1b3f573fSAndroid Build Coastguard Worker if (read == -1) { 57*1b3f573fSAndroid Build Coastguard Worker return false; // EOF 58*1b3f573fSAndroid Build Coastguard Worker } 59*1b3f573fSAndroid Build Coastguard Worker ofs += read; 60*1b3f573fSAndroid Build Coastguard Worker len -= read; 61*1b3f573fSAndroid Build Coastguard Worker } 62*1b3f573fSAndroid Build Coastguard Worker 63*1b3f573fSAndroid Build Coastguard Worker return true; 64*1b3f573fSAndroid Build Coastguard Worker } 65*1b3f573fSAndroid Build Coastguard Worker writeToStdout(byte[] buf)66*1b3f573fSAndroid Build Coastguard Worker private void writeToStdout(byte[] buf) throws Exception { 67*1b3f573fSAndroid Build Coastguard Worker System.out.write(buf); 68*1b3f573fSAndroid Build Coastguard Worker } 69*1b3f573fSAndroid Build Coastguard Worker 70*1b3f573fSAndroid Build Coastguard Worker // Returns -1 on EOF (the actual values will always be positive). readLittleEndianIntFromStdin()71*1b3f573fSAndroid Build Coastguard Worker private int readLittleEndianIntFromStdin() throws Exception { 72*1b3f573fSAndroid Build Coastguard Worker byte[] buf = new byte[4]; 73*1b3f573fSAndroid Build Coastguard Worker if (!readFromStdin(buf, 4)) { 74*1b3f573fSAndroid Build Coastguard Worker return -1; 75*1b3f573fSAndroid Build Coastguard Worker } 76*1b3f573fSAndroid Build Coastguard Worker return (buf[0] & 0xff) 77*1b3f573fSAndroid Build Coastguard Worker | ((buf[1] & 0xff) << 8) 78*1b3f573fSAndroid Build Coastguard Worker | ((buf[2] & 0xff) << 16) 79*1b3f573fSAndroid Build Coastguard Worker | ((buf[3] & 0xff) << 24); 80*1b3f573fSAndroid Build Coastguard Worker } 81*1b3f573fSAndroid Build Coastguard Worker writeLittleEndianIntToStdout(int val)82*1b3f573fSAndroid Build Coastguard Worker private void writeLittleEndianIntToStdout(int val) throws Exception { 83*1b3f573fSAndroid Build Coastguard Worker byte[] buf = new byte[4]; 84*1b3f573fSAndroid Build Coastguard Worker buf[0] = (byte) val; 85*1b3f573fSAndroid Build Coastguard Worker buf[1] = (byte) (val >> 8); 86*1b3f573fSAndroid Build Coastguard Worker buf[2] = (byte) (val >> 16); 87*1b3f573fSAndroid Build Coastguard Worker buf[3] = (byte) (val >> 24); 88*1b3f573fSAndroid Build Coastguard Worker writeToStdout(buf); 89*1b3f573fSAndroid Build Coastguard Worker } 90*1b3f573fSAndroid Build Coastguard Worker 91*1b3f573fSAndroid Build Coastguard Worker private enum BinaryDecoderType { 92*1b3f573fSAndroid Build Coastguard Worker BTYE_STRING_DECODER, 93*1b3f573fSAndroid Build Coastguard Worker BYTE_ARRAY_DECODER, 94*1b3f573fSAndroid Build Coastguard Worker ARRAY_BYTE_BUFFER_DECODER, 95*1b3f573fSAndroid Build Coastguard Worker READONLY_ARRAY_BYTE_BUFFER_DECODER, 96*1b3f573fSAndroid Build Coastguard Worker DIRECT_BYTE_BUFFER_DECODER, 97*1b3f573fSAndroid Build Coastguard Worker READONLY_DIRECT_BYTE_BUFFER_DECODER, 98*1b3f573fSAndroid Build Coastguard Worker INPUT_STREAM_DECODER; 99*1b3f573fSAndroid Build Coastguard Worker } 100*1b3f573fSAndroid Build Coastguard Worker 101*1b3f573fSAndroid Build Coastguard Worker private static class BinaryDecoder<T extends AbstractMessage> { decode( ByteString bytes, BinaryDecoderType type, Parser<T> parser, ExtensionRegistry extensions)102*1b3f573fSAndroid Build Coastguard Worker public T decode( 103*1b3f573fSAndroid Build Coastguard Worker ByteString bytes, BinaryDecoderType type, Parser<T> parser, ExtensionRegistry extensions) 104*1b3f573fSAndroid Build Coastguard Worker throws InvalidProtocolBufferException { 105*1b3f573fSAndroid Build Coastguard Worker switch (type) { 106*1b3f573fSAndroid Build Coastguard Worker case BTYE_STRING_DECODER: 107*1b3f573fSAndroid Build Coastguard Worker case BYTE_ARRAY_DECODER: 108*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom(bytes, extensions); 109*1b3f573fSAndroid Build Coastguard Worker case ARRAY_BYTE_BUFFER_DECODER: 110*1b3f573fSAndroid Build Coastguard Worker { 111*1b3f573fSAndroid Build Coastguard Worker ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); 112*1b3f573fSAndroid Build Coastguard Worker bytes.copyTo(buffer); 113*1b3f573fSAndroid Build Coastguard Worker buffer.flip(); 114*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); 115*1b3f573fSAndroid Build Coastguard Worker } 116*1b3f573fSAndroid Build Coastguard Worker case READONLY_ARRAY_BYTE_BUFFER_DECODER: 117*1b3f573fSAndroid Build Coastguard Worker { 118*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom( 119*1b3f573fSAndroid Build Coastguard Worker CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions); 120*1b3f573fSAndroid Build Coastguard Worker } 121*1b3f573fSAndroid Build Coastguard Worker case DIRECT_BYTE_BUFFER_DECODER: 122*1b3f573fSAndroid Build Coastguard Worker { 123*1b3f573fSAndroid Build Coastguard Worker ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); 124*1b3f573fSAndroid Build Coastguard Worker bytes.copyTo(buffer); 125*1b3f573fSAndroid Build Coastguard Worker buffer.flip(); 126*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); 127*1b3f573fSAndroid Build Coastguard Worker } 128*1b3f573fSAndroid Build Coastguard Worker case READONLY_DIRECT_BYTE_BUFFER_DECODER: 129*1b3f573fSAndroid Build Coastguard Worker { 130*1b3f573fSAndroid Build Coastguard Worker ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); 131*1b3f573fSAndroid Build Coastguard Worker bytes.copyTo(buffer); 132*1b3f573fSAndroid Build Coastguard Worker buffer.flip(); 133*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom( 134*1b3f573fSAndroid Build Coastguard Worker CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions); 135*1b3f573fSAndroid Build Coastguard Worker } 136*1b3f573fSAndroid Build Coastguard Worker case INPUT_STREAM_DECODER: 137*1b3f573fSAndroid Build Coastguard Worker { 138*1b3f573fSAndroid Build Coastguard Worker return parser.parseFrom(bytes.newInput(), extensions); 139*1b3f573fSAndroid Build Coastguard Worker } 140*1b3f573fSAndroid Build Coastguard Worker } 141*1b3f573fSAndroid Build Coastguard Worker return null; 142*1b3f573fSAndroid Build Coastguard Worker } 143*1b3f573fSAndroid Build Coastguard Worker } 144*1b3f573fSAndroid Build Coastguard Worker parseBinary( ByteString bytes, Parser<T> parser, ExtensionRegistry extensions)145*1b3f573fSAndroid Build Coastguard Worker private <T extends AbstractMessage> T parseBinary( 146*1b3f573fSAndroid Build Coastguard Worker ByteString bytes, Parser<T> parser, ExtensionRegistry extensions) 147*1b3f573fSAndroid Build Coastguard Worker throws InvalidProtocolBufferException { 148*1b3f573fSAndroid Build Coastguard Worker ArrayList<T> messages = new ArrayList<>(); 149*1b3f573fSAndroid Build Coastguard Worker ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>(); 150*1b3f573fSAndroid Build Coastguard Worker 151*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < BinaryDecoderType.values().length; i++) { 152*1b3f573fSAndroid Build Coastguard Worker messages.add(null); 153*1b3f573fSAndroid Build Coastguard Worker exceptions.add(null); 154*1b3f573fSAndroid Build Coastguard Worker } 155*1b3f573fSAndroid Build Coastguard Worker if (messages.isEmpty()) { 156*1b3f573fSAndroid Build Coastguard Worker throw new RuntimeException("binary decoder types missing"); 157*1b3f573fSAndroid Build Coastguard Worker } 158*1b3f573fSAndroid Build Coastguard Worker 159*1b3f573fSAndroid Build Coastguard Worker BinaryDecoder<T> decoder = new BinaryDecoder<>(); 160*1b3f573fSAndroid Build Coastguard Worker 161*1b3f573fSAndroid Build Coastguard Worker boolean hasMessage = false; 162*1b3f573fSAndroid Build Coastguard Worker boolean hasException = false; 163*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < BinaryDecoderType.values().length; ++i) { 164*1b3f573fSAndroid Build Coastguard Worker try { 165*1b3f573fSAndroid Build Coastguard Worker // = BinaryDecoderType.values()[i].parseProto3(bytes); 166*1b3f573fSAndroid Build Coastguard Worker messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions)); 167*1b3f573fSAndroid Build Coastguard Worker hasMessage = true; 168*1b3f573fSAndroid Build Coastguard Worker } catch (InvalidProtocolBufferException e) { 169*1b3f573fSAndroid Build Coastguard Worker exceptions.set(i, e); 170*1b3f573fSAndroid Build Coastguard Worker hasException = true; 171*1b3f573fSAndroid Build Coastguard Worker } 172*1b3f573fSAndroid Build Coastguard Worker } 173*1b3f573fSAndroid Build Coastguard Worker 174*1b3f573fSAndroid Build Coastguard Worker if (hasMessage && hasException) { 175*1b3f573fSAndroid Build Coastguard Worker StringBuilder sb = 176*1b3f573fSAndroid Build Coastguard Worker new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n"); 177*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < BinaryDecoderType.values().length; ++i) { 178*1b3f573fSAndroid Build Coastguard Worker sb.append(BinaryDecoderType.values()[i].name()); 179*1b3f573fSAndroid Build Coastguard Worker if (messages.get(i) != null) { 180*1b3f573fSAndroid Build Coastguard Worker sb.append(" accepted the payload.\n"); 181*1b3f573fSAndroid Build Coastguard Worker } else { 182*1b3f573fSAndroid Build Coastguard Worker sb.append(" rejected the payload.\n"); 183*1b3f573fSAndroid Build Coastguard Worker } 184*1b3f573fSAndroid Build Coastguard Worker } 185*1b3f573fSAndroid Build Coastguard Worker throw new RuntimeException(sb.toString()); 186*1b3f573fSAndroid Build Coastguard Worker } 187*1b3f573fSAndroid Build Coastguard Worker 188*1b3f573fSAndroid Build Coastguard Worker if (hasException) { 189*1b3f573fSAndroid Build Coastguard Worker // We do not check if exceptions are equal. Different implementations may return different 190*1b3f573fSAndroid Build Coastguard Worker // exception messages. Throw an arbitrary one out instead. 191*1b3f573fSAndroid Build Coastguard Worker InvalidProtocolBufferException exception = null; 192*1b3f573fSAndroid Build Coastguard Worker for (InvalidProtocolBufferException e : exceptions) { 193*1b3f573fSAndroid Build Coastguard Worker if (exception != null) { 194*1b3f573fSAndroid Build Coastguard Worker exception.addSuppressed(e); 195*1b3f573fSAndroid Build Coastguard Worker } else { 196*1b3f573fSAndroid Build Coastguard Worker exception = e; 197*1b3f573fSAndroid Build Coastguard Worker } 198*1b3f573fSAndroid Build Coastguard Worker } 199*1b3f573fSAndroid Build Coastguard Worker throw exception; 200*1b3f573fSAndroid Build Coastguard Worker } 201*1b3f573fSAndroid Build Coastguard Worker 202*1b3f573fSAndroid Build Coastguard Worker // Fast path comparing all the messages with the first message, assuming equality being 203*1b3f573fSAndroid Build Coastguard Worker // symmetric and transitive. 204*1b3f573fSAndroid Build Coastguard Worker boolean allEqual = true; 205*1b3f573fSAndroid Build Coastguard Worker for (int i = 1; i < messages.size(); ++i) { 206*1b3f573fSAndroid Build Coastguard Worker if (!messages.get(0).equals(messages.get(i))) { 207*1b3f573fSAndroid Build Coastguard Worker allEqual = false; 208*1b3f573fSAndroid Build Coastguard Worker break; 209*1b3f573fSAndroid Build Coastguard Worker } 210*1b3f573fSAndroid Build Coastguard Worker } 211*1b3f573fSAndroid Build Coastguard Worker 212*1b3f573fSAndroid Build Coastguard Worker // Slow path: compare and find out all unequal pairs. 213*1b3f573fSAndroid Build Coastguard Worker if (!allEqual) { 214*1b3f573fSAndroid Build Coastguard Worker StringBuilder sb = new StringBuilder(); 215*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < messages.size() - 1; ++i) { 216*1b3f573fSAndroid Build Coastguard Worker for (int j = i + 1; j < messages.size(); ++j) { 217*1b3f573fSAndroid Build Coastguard Worker if (!messages.get(i).equals(messages.get(j))) { 218*1b3f573fSAndroid Build Coastguard Worker sb.append(BinaryDecoderType.values()[i].name()) 219*1b3f573fSAndroid Build Coastguard Worker .append(" and ") 220*1b3f573fSAndroid Build Coastguard Worker .append(BinaryDecoderType.values()[j].name()) 221*1b3f573fSAndroid Build Coastguard Worker .append(" parsed the payload differently.\n"); 222*1b3f573fSAndroid Build Coastguard Worker } 223*1b3f573fSAndroid Build Coastguard Worker } 224*1b3f573fSAndroid Build Coastguard Worker } 225*1b3f573fSAndroid Build Coastguard Worker throw new RuntimeException(sb.toString()); 226*1b3f573fSAndroid Build Coastguard Worker } 227*1b3f573fSAndroid Build Coastguard Worker 228*1b3f573fSAndroid Build Coastguard Worker return messages.get(0); 229*1b3f573fSAndroid Build Coastguard Worker } 230*1b3f573fSAndroid Build Coastguard Worker doTest(Conformance.ConformanceRequest request)231*1b3f573fSAndroid Build Coastguard Worker private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { 232*1b3f573fSAndroid Build Coastguard Worker AbstractMessage testMessage; 233*1b3f573fSAndroid Build Coastguard Worker String messageType = request.getMessageType(); 234*1b3f573fSAndroid Build Coastguard Worker boolean isProto3 = 235*1b3f573fSAndroid Build Coastguard Worker messageType.equals("protobuf_test_messages.proto3.TestAllTypesProto3"); 236*1b3f573fSAndroid Build Coastguard Worker boolean isProto2 = 237*1b3f573fSAndroid Build Coastguard Worker messageType.equals("protobuf_test_messages.proto2.TestAllTypesProto2"); 238*1b3f573fSAndroid Build Coastguard Worker 239*1b3f573fSAndroid Build Coastguard Worker switch (request.getPayloadCase()) { 240*1b3f573fSAndroid Build Coastguard Worker case PROTOBUF_PAYLOAD: 241*1b3f573fSAndroid Build Coastguard Worker { 242*1b3f573fSAndroid Build Coastguard Worker if (isProto3) { 243*1b3f573fSAndroid Build Coastguard Worker try { 244*1b3f573fSAndroid Build Coastguard Worker ExtensionRegistry extensions = ExtensionRegistry.newInstance(); 245*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto3.registerAllExtensions(extensions); 246*1b3f573fSAndroid Build Coastguard Worker testMessage = 247*1b3f573fSAndroid Build Coastguard Worker parseBinary( 248*1b3f573fSAndroid Build Coastguard Worker request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions); 249*1b3f573fSAndroid Build Coastguard Worker } catch (InvalidProtocolBufferException e) { 250*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 251*1b3f573fSAndroid Build Coastguard Worker .setParseError(e.getMessage()) 252*1b3f573fSAndroid Build Coastguard Worker .build(); 253*1b3f573fSAndroid Build Coastguard Worker } 254*1b3f573fSAndroid Build Coastguard Worker } else if (isProto2) { 255*1b3f573fSAndroid Build Coastguard Worker try { 256*1b3f573fSAndroid Build Coastguard Worker ExtensionRegistry extensions = ExtensionRegistry.newInstance(); 257*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto2.registerAllExtensions(extensions); 258*1b3f573fSAndroid Build Coastguard Worker testMessage = 259*1b3f573fSAndroid Build Coastguard Worker parseBinary( 260*1b3f573fSAndroid Build Coastguard Worker request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions); 261*1b3f573fSAndroid Build Coastguard Worker } catch (InvalidProtocolBufferException e) { 262*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 263*1b3f573fSAndroid Build Coastguard Worker .setParseError(e.getMessage()) 264*1b3f573fSAndroid Build Coastguard Worker .build(); 265*1b3f573fSAndroid Build Coastguard Worker } 266*1b3f573fSAndroid Build Coastguard Worker } else { 267*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException( 268*1b3f573fSAndroid Build Coastguard Worker "Protobuf request has unexpected payload type: " + messageType); 269*1b3f573fSAndroid Build Coastguard Worker } 270*1b3f573fSAndroid Build Coastguard Worker break; 271*1b3f573fSAndroid Build Coastguard Worker } 272*1b3f573fSAndroid Build Coastguard Worker case JSON_PAYLOAD: 273*1b3f573fSAndroid Build Coastguard Worker { 274*1b3f573fSAndroid Build Coastguard Worker try { 275*1b3f573fSAndroid Build Coastguard Worker JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry); 276*1b3f573fSAndroid Build Coastguard Worker if (request.getTestCategory() 277*1b3f573fSAndroid Build Coastguard Worker == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) { 278*1b3f573fSAndroid Build Coastguard Worker parser = parser.ignoringUnknownFields(); 279*1b3f573fSAndroid Build Coastguard Worker } 280*1b3f573fSAndroid Build Coastguard Worker if (isProto3) { 281*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto3.TestAllTypesProto3.Builder builder = 282*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto3.TestAllTypesProto3.newBuilder(); 283*1b3f573fSAndroid Build Coastguard Worker parser.merge(request.getJsonPayload(), builder); 284*1b3f573fSAndroid Build Coastguard Worker testMessage = builder.build(); 285*1b3f573fSAndroid Build Coastguard Worker } else if (isProto2) { 286*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto2.TestAllTypesProto2.Builder builder = 287*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto2.TestAllTypesProto2.newBuilder(); 288*1b3f573fSAndroid Build Coastguard Worker parser.merge(request.getJsonPayload(), builder); 289*1b3f573fSAndroid Build Coastguard Worker testMessage = builder.build(); 290*1b3f573fSAndroid Build Coastguard Worker } else { 291*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException( 292*1b3f573fSAndroid Build Coastguard Worker "Protobuf request has unexpected payload type: " + messageType); 293*1b3f573fSAndroid Build Coastguard Worker } 294*1b3f573fSAndroid Build Coastguard Worker } catch (InvalidProtocolBufferException e) { 295*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 296*1b3f573fSAndroid Build Coastguard Worker .setParseError(e.getMessage()) 297*1b3f573fSAndroid Build Coastguard Worker .build(); 298*1b3f573fSAndroid Build Coastguard Worker } 299*1b3f573fSAndroid Build Coastguard Worker break; 300*1b3f573fSAndroid Build Coastguard Worker } 301*1b3f573fSAndroid Build Coastguard Worker case TEXT_PAYLOAD: 302*1b3f573fSAndroid Build Coastguard Worker { 303*1b3f573fSAndroid Build Coastguard Worker if (isProto3) { 304*1b3f573fSAndroid Build Coastguard Worker try { 305*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto3.TestAllTypesProto3.Builder builder = 306*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto3.TestAllTypesProto3.newBuilder(); 307*1b3f573fSAndroid Build Coastguard Worker TextFormat.merge(request.getTextPayload(), builder); 308*1b3f573fSAndroid Build Coastguard Worker testMessage = builder.build(); 309*1b3f573fSAndroid Build Coastguard Worker } catch (TextFormat.ParseException e) { 310*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 311*1b3f573fSAndroid Build Coastguard Worker .setParseError(e.getMessage()) 312*1b3f573fSAndroid Build Coastguard Worker .build(); 313*1b3f573fSAndroid Build Coastguard Worker } 314*1b3f573fSAndroid Build Coastguard Worker } else if (isProto2) { 315*1b3f573fSAndroid Build Coastguard Worker try { 316*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto2.TestAllTypesProto2.Builder builder = 317*1b3f573fSAndroid Build Coastguard Worker TestMessagesProto2.TestAllTypesProto2.newBuilder(); 318*1b3f573fSAndroid Build Coastguard Worker TextFormat.merge(request.getTextPayload(), builder); 319*1b3f573fSAndroid Build Coastguard Worker testMessage = builder.build(); 320*1b3f573fSAndroid Build Coastguard Worker } catch (TextFormat.ParseException e) { 321*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 322*1b3f573fSAndroid Build Coastguard Worker .setParseError(e.getMessage()) 323*1b3f573fSAndroid Build Coastguard Worker .build(); 324*1b3f573fSAndroid Build Coastguard Worker } 325*1b3f573fSAndroid Build Coastguard Worker } else { 326*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException( 327*1b3f573fSAndroid Build Coastguard Worker "Protobuf request has unexpected payload type: " + messageType); 328*1b3f573fSAndroid Build Coastguard Worker } 329*1b3f573fSAndroid Build Coastguard Worker break; 330*1b3f573fSAndroid Build Coastguard Worker } 331*1b3f573fSAndroid Build Coastguard Worker case PAYLOAD_NOT_SET: 332*1b3f573fSAndroid Build Coastguard Worker { 333*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException("Request didn't have payload."); 334*1b3f573fSAndroid Build Coastguard Worker } 335*1b3f573fSAndroid Build Coastguard Worker 336*1b3f573fSAndroid Build Coastguard Worker default: 337*1b3f573fSAndroid Build Coastguard Worker { 338*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException("Unexpected payload case."); 339*1b3f573fSAndroid Build Coastguard Worker } 340*1b3f573fSAndroid Build Coastguard Worker } 341*1b3f573fSAndroid Build Coastguard Worker 342*1b3f573fSAndroid Build Coastguard Worker switch (request.getRequestedOutputFormat()) { 343*1b3f573fSAndroid Build Coastguard Worker case UNSPECIFIED: 344*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException("Unspecified output format."); 345*1b3f573fSAndroid Build Coastguard Worker 346*1b3f573fSAndroid Build Coastguard Worker case PROTOBUF: 347*1b3f573fSAndroid Build Coastguard Worker { 348*1b3f573fSAndroid Build Coastguard Worker ByteString messageString = testMessage.toByteString(); 349*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 350*1b3f573fSAndroid Build Coastguard Worker .setProtobufPayload(messageString) 351*1b3f573fSAndroid Build Coastguard Worker .build(); 352*1b3f573fSAndroid Build Coastguard Worker } 353*1b3f573fSAndroid Build Coastguard Worker 354*1b3f573fSAndroid Build Coastguard Worker case JSON: 355*1b3f573fSAndroid Build Coastguard Worker try { 356*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 357*1b3f573fSAndroid Build Coastguard Worker .setJsonPayload( 358*1b3f573fSAndroid Build Coastguard Worker JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)) 359*1b3f573fSAndroid Build Coastguard Worker .build(); 360*1b3f573fSAndroid Build Coastguard Worker } catch (InvalidProtocolBufferException | IllegalArgumentException e) { 361*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 362*1b3f573fSAndroid Build Coastguard Worker .setSerializeError(e.getMessage()) 363*1b3f573fSAndroid Build Coastguard Worker .build(); 364*1b3f573fSAndroid Build Coastguard Worker } 365*1b3f573fSAndroid Build Coastguard Worker 366*1b3f573fSAndroid Build Coastguard Worker case TEXT_FORMAT: 367*1b3f573fSAndroid Build Coastguard Worker return Conformance.ConformanceResponse.newBuilder() 368*1b3f573fSAndroid Build Coastguard Worker .setTextPayload(TextFormat.printer().printToString(testMessage)) 369*1b3f573fSAndroid Build Coastguard Worker .build(); 370*1b3f573fSAndroid Build Coastguard Worker 371*1b3f573fSAndroid Build Coastguard Worker default: 372*1b3f573fSAndroid Build Coastguard Worker { 373*1b3f573fSAndroid Build Coastguard Worker throw new IllegalArgumentException("Unexpected request output."); 374*1b3f573fSAndroid Build Coastguard Worker } 375*1b3f573fSAndroid Build Coastguard Worker } 376*1b3f573fSAndroid Build Coastguard Worker } 377*1b3f573fSAndroid Build Coastguard Worker doTestIo()378*1b3f573fSAndroid Build Coastguard Worker private boolean doTestIo() throws Exception { 379*1b3f573fSAndroid Build Coastguard Worker int bytes = readLittleEndianIntFromStdin(); 380*1b3f573fSAndroid Build Coastguard Worker 381*1b3f573fSAndroid Build Coastguard Worker if (bytes == -1) { 382*1b3f573fSAndroid Build Coastguard Worker return false; // EOF 383*1b3f573fSAndroid Build Coastguard Worker } 384*1b3f573fSAndroid Build Coastguard Worker 385*1b3f573fSAndroid Build Coastguard Worker byte[] serializedInput = new byte[bytes]; 386*1b3f573fSAndroid Build Coastguard Worker 387*1b3f573fSAndroid Build Coastguard Worker if (!readFromStdin(serializedInput, bytes)) { 388*1b3f573fSAndroid Build Coastguard Worker throw new RuntimeException("Unexpected EOF from test program."); 389*1b3f573fSAndroid Build Coastguard Worker } 390*1b3f573fSAndroid Build Coastguard Worker 391*1b3f573fSAndroid Build Coastguard Worker Conformance.ConformanceRequest request = 392*1b3f573fSAndroid Build Coastguard Worker Conformance.ConformanceRequest.parseFrom(serializedInput); 393*1b3f573fSAndroid Build Coastguard Worker Conformance.ConformanceResponse response = doTest(request); 394*1b3f573fSAndroid Build Coastguard Worker byte[] serializedOutput = response.toByteArray(); 395*1b3f573fSAndroid Build Coastguard Worker 396*1b3f573fSAndroid Build Coastguard Worker writeLittleEndianIntToStdout(serializedOutput.length); 397*1b3f573fSAndroid Build Coastguard Worker writeToStdout(serializedOutput); 398*1b3f573fSAndroid Build Coastguard Worker 399*1b3f573fSAndroid Build Coastguard Worker return true; 400*1b3f573fSAndroid Build Coastguard Worker } 401*1b3f573fSAndroid Build Coastguard Worker run()402*1b3f573fSAndroid Build Coastguard Worker public void run() throws Exception { 403*1b3f573fSAndroid Build Coastguard Worker typeRegistry = 404*1b3f573fSAndroid Build Coastguard Worker TypeRegistry.newBuilder() 405*1b3f573fSAndroid Build Coastguard Worker .add(TestMessagesProto3.TestAllTypesProto3.getDescriptor()) 406*1b3f573fSAndroid Build Coastguard Worker .build(); 407*1b3f573fSAndroid Build Coastguard Worker while (doTestIo()) { 408*1b3f573fSAndroid Build Coastguard Worker this.testCount++; 409*1b3f573fSAndroid Build Coastguard Worker } 410*1b3f573fSAndroid Build Coastguard Worker 411*1b3f573fSAndroid Build Coastguard Worker System.err.println( 412*1b3f573fSAndroid Build Coastguard Worker "ConformanceJava: received EOF from test runner after " + this.testCount + " tests"); 413*1b3f573fSAndroid Build Coastguard Worker } 414*1b3f573fSAndroid Build Coastguard Worker main(String[] args)415*1b3f573fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 416*1b3f573fSAndroid Build Coastguard Worker new ConformanceJava().run(); 417*1b3f573fSAndroid Build Coastguard Worker } 418*1b3f573fSAndroid Build Coastguard Worker } 419