xref: /aosp_15_r20/external/protobuf/conformance/ConformanceJava.java (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
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