Sync from Piper @368734211 PROTOBUF_SYNC_PIPER
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java index 5319982..100bec4 100644 --- a/conformance/ConformanceJava.java +++ b/conformance/ConformanceJava.java
@@ -54,7 +54,7 @@ while (len > 0) { int read = System.in.read(buf, ofs, len); if (read == -1) { - return false; // EOF + return false; // EOF } ofs += read; len -= read; @@ -81,10 +81,10 @@ 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); + buf[0] = (byte) val; + buf[1] = (byte) (val >> 8); + buf[2] = (byte) (val >> 16); + buf[3] = (byte) (val >> 24); writeToStdout(buf); } @@ -98,85 +98,71 @@ INPUT_STREAM_DECODER; } - private static class BinaryDecoder <MessageType extends AbstractMessage> { - public MessageType decode (ByteString bytes, BinaryDecoderType type, - Parser <MessageType> parser, ExtensionRegistry extensions) - throws InvalidProtocolBufferException { + private static class BinaryDecoder<T extends AbstractMessage> { + public T decode( + ByteString bytes, BinaryDecoderType type, Parser<T> parser, ExtensionRegistry extensions) + throws InvalidProtocolBufferException { switch (type) { case BTYE_STRING_DECODER: - return parser.parseFrom(bytes, extensions); case BYTE_ARRAY_DECODER: - return parser.parseFrom(bytes.toByteArray(), extensions); - case ARRAY_BYTE_BUFFER_DECODER: { - ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); - bytes.copyTo(buffer); - buffer.flip(); - try { + return parser.parseFrom(bytes, extensions); + case ARRAY_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); - } catch (InvalidProtocolBufferException e) { - throw e; } - } - case READONLY_ARRAY_BYTE_BUFFER_DECODER: { - try { + case READONLY_ARRAY_BYTE_BUFFER_DECODER: + { return parser.parseFrom( CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions); - } catch (InvalidProtocolBufferException e) { - throw e; } - } - case DIRECT_BYTE_BUFFER_DECODER: { - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); - bytes.copyTo(buffer); - buffer.flip(); - try { + case DIRECT_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); - } catch (InvalidProtocolBufferException e) { - throw e; } - } - case READONLY_DIRECT_BYTE_BUFFER_DECODER: { - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); - bytes.copyTo(buffer); - buffer.flip(); - try { + case READONLY_DIRECT_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); return parser.parseFrom( CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions); - } catch (InvalidProtocolBufferException e) { - throw e; } - } - case INPUT_STREAM_DECODER: { - try { + case INPUT_STREAM_DECODER: + { return parser.parseFrom(bytes.newInput(), extensions); - } catch (InvalidProtocolBufferException e) { - throw e; } - } - default : - return null; } + return null; } } - private <MessageType extends AbstractMessage> MessageType parseBinary( - ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions) + private <T extends AbstractMessage> T parseBinary( + ByteString bytes, Parser<T> parser, ExtensionRegistry extensions) throws InvalidProtocolBufferException { - ArrayList <MessageType> messages = new ArrayList <MessageType> (); - ArrayList <InvalidProtocolBufferException> exceptions = - new ArrayList <InvalidProtocolBufferException>(); + ArrayList<T> messages = new ArrayList<>(); + ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>(); for (int i = 0; i < BinaryDecoderType.values().length; i++) { messages.add(null); exceptions.add(null); } - BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> (); + if (messages.isEmpty()) { + throw new RuntimeException("binary decoder types missing"); + } + + BinaryDecoder<T> decoder = new BinaryDecoder<>(); boolean hasMessage = false; boolean hasException = false; for (int i = 0; i < BinaryDecoderType.values().length; ++i) { try { - //= BinaryDecoderType.values()[i].parseProto3(bytes); + // = BinaryDecoderType.values()[i].parseProto3(bytes); messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions)); hasMessage = true; } catch (InvalidProtocolBufferException e) { @@ -202,7 +188,15 @@ 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.get(0); + InvalidProtocolBufferException exception = null; + for (InvalidProtocolBufferException e : exceptions) { + if (exception != null) { + exception.addSuppressed(e); + } else { + exception = e; + } + } + throw exception; } // Fast path comparing all the messages with the first message, assuming equality being @@ -242,115 +236,138 @@ request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2"); switch (request.getPayloadCase()) { - case PROTOBUF_PAYLOAD: { - if (isProto3) { - try { - ExtensionRegistry extensions = ExtensionRegistry.newInstance(); - TestMessagesProto3.registerAllExtensions(extensions); - testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions); - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); - } - } else if (isProto2) { - try { - ExtensionRegistry extensions = ExtensionRegistry.newInstance(); - TestMessagesProto2.registerAllExtensions(extensions); - testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions); - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); - } - } else { - throw new RuntimeException("Protobuf request doesn't have specific payload type."); - } - break; - } - case JSON_PAYLOAD: { - try { - JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry); - if (request.getTestCategory() - == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) { - parser = parser.ignoringUnknownFields(); - } + case PROTOBUF_PAYLOAD: + { if (isProto3) { - TestMessagesProto3.TestAllTypesProto3.Builder builder = - TestMessagesProto3.TestAllTypesProto3.newBuilder(); - parser.merge(request.getJsonPayload(), builder); - testMessage = builder.build(); + try { + ExtensionRegistry extensions = ExtensionRegistry.newInstance(); + TestMessagesProto3.registerAllExtensions(extensions); + testMessage = + parseBinary( + request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } } else if (isProto2) { - TestMessagesProto2.TestAllTypesProto2.Builder builder = - TestMessagesProto2.TestAllTypesProto2.newBuilder(); - parser.merge(request.getJsonPayload(), builder); - testMessage = builder.build(); + try { + ExtensionRegistry extensions = ExtensionRegistry.newInstance(); + TestMessagesProto2.registerAllExtensions(extensions); + testMessage = + parseBinary( + request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } } else { throw new RuntimeException("Protobuf request doesn't have specific payload type."); } - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); + break; } - break; - } - case TEXT_PAYLOAD: { - if (isProto3) { + case JSON_PAYLOAD: + { try { - TestMessagesProto3.TestAllTypesProto3.Builder builder = - TestMessagesProto3.TestAllTypesProto3.newBuilder(); - TextFormat.merge(request.getTextPayload(), builder); - testMessage = builder.build(); - } catch (TextFormat.ParseException e) { + JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry); + if (request.getTestCategory() + == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) { + parser = parser.ignoringUnknownFields(); + } + if (isProto3) { + TestMessagesProto3.TestAllTypesProto3.Builder builder = + TestMessagesProto3.TestAllTypesProto3.newBuilder(); + parser.merge(request.getJsonPayload(), builder); + testMessage = builder.build(); + } else if (isProto2) { + TestMessagesProto2.TestAllTypesProto2.Builder builder = + TestMessagesProto2.TestAllTypesProto2.newBuilder(); + parser.merge(request.getJsonPayload(), builder); + testMessage = builder.build(); + } else { + throw new RuntimeException("Protobuf request doesn't have specific payload type."); + } + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } + break; + } + case TEXT_PAYLOAD: + { + if (isProto3) { + try { + TestMessagesProto3.TestAllTypesProto3.Builder builder = + TestMessagesProto3.TestAllTypesProto3.newBuilder(); + TextFormat.merge(request.getTextPayload(), builder); + testMessage = builder.build(); + } catch (TextFormat.ParseException e) { return Conformance.ConformanceResponse.newBuilder() .setParseError(e.getMessage()) .build(); - } - } else if (isProto2) { - try { - TestMessagesProto2.TestAllTypesProto2.Builder builder = - TestMessagesProto2.TestAllTypesProto2.newBuilder(); - TextFormat.merge(request.getTextPayload(), builder); - testMessage = builder.build(); - } catch (TextFormat.ParseException e) { + } + } else if (isProto2) { + try { + TestMessagesProto2.TestAllTypesProto2.Builder builder = + TestMessagesProto2.TestAllTypesProto2.newBuilder(); + TextFormat.merge(request.getTextPayload(), builder); + testMessage = builder.build(); + } catch (TextFormat.ParseException e) { return Conformance.ConformanceResponse.newBuilder() .setParseError(e.getMessage()) .build(); + } + } else { + throw new RuntimeException("Protobuf request doesn't have specific payload type."); } - } else { - throw new RuntimeException("Protobuf request doesn't have specific payload type."); + break; } - break; - } - case PAYLOAD_NOT_SET: { - throw new RuntimeException("Request didn't have payload."); - } + case PAYLOAD_NOT_SET: + { + throw new RuntimeException("Request didn't have payload."); + } - default: { - throw new RuntimeException("Unexpected payload case."); - } + default: + { + throw new RuntimeException("Unexpected payload case."); + } } switch (request.getRequestedOutputFormat()) { case UNSPECIFIED: throw new RuntimeException("Unspecified output format."); - case PROTOBUF: { - ByteString MessageString = testMessage.toByteString(); - return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build(); - } + case PROTOBUF: + { + ByteString messageString = testMessage.toByteString(); + return Conformance.ConformanceResponse.newBuilder() + .setProtobufPayload(messageString) + .build(); + } case JSON: try { - return Conformance.ConformanceResponse.newBuilder().setJsonPayload( - JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build(); + return Conformance.ConformanceResponse.newBuilder() + .setJsonPayload( + JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)) + .build(); } catch (InvalidProtocolBufferException | IllegalArgumentException e) { - return Conformance.ConformanceResponse.newBuilder().setSerializeError( - e.getMessage()).build(); + return Conformance.ConformanceResponse.newBuilder() + .setSerializeError(e.getMessage()) + .build(); } case TEXT_FORMAT: - return Conformance.ConformanceResponse.newBuilder().setTextPayload( - TextFormat.printToString(testMessage)).build(); + return Conformance.ConformanceResponse.newBuilder() + .setTextPayload(TextFormat.printToString(testMessage)) + .build(); - default: { - throw new RuntimeException("Unexpected request output."); - } + default: + { + throw new RuntimeException("Unexpected request output."); + } } } @@ -358,7 +375,7 @@ int bytes = readLittleEndianIntFromStdin(); if (bytes == -1) { - return false; // EOF + return false; // EOF } byte[] serializedInput = new byte[bytes]; @@ -379,14 +396,16 @@ } public void run() throws Exception { - typeRegistry = TypeRegistry.newBuilder().add( - TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build(); + typeRegistry = + TypeRegistry.newBuilder() + .add(TestMessagesProto3.TestAllTypesProto3.getDescriptor()) + .build(); while (doTestIo()) { this.testCount++; } - System.err.println("ConformanceJava: received EOF from test runner after " + - this.testCount + " tests"); + System.err.println( + "ConformanceJava: received EOF from test runner after " + this.testCount + " tests"); } public static void main(String[] args) throws Exception {
diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java index 147738d..eb3d06a 100644 --- a/conformance/ConformanceJavaLite.java +++ b/conformance/ConformanceJavaLite.java
@@ -28,8 +28,19 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import com.google.protobuf.conformance.Conformance; +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.ExtensionRegistryLite; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.MessageLite; +import com.google.protobuf.Parser; +import com.google.protobuf.conformance.Conformance; +import com.google.protobuf_test_messages.proto2.TestMessagesProto2; +import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2; +import com.google.protobuf_test_messages.proto3.TestMessagesProto3; +import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3; +import java.nio.ByteBuffer; +import java.util.ArrayList; class ConformanceJavaLite { private int testCount = 0; @@ -39,7 +50,7 @@ while (len > 0) { int read = System.in.read(buf, ofs, len); if (read == -1) { - return false; // EOF + return false; // EOF } ofs += read; len -= read; @@ -66,36 +77,214 @@ 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); + buf[0] = (byte) val; + buf[1] = (byte) (val >> 8); + buf[2] = (byte) (val >> 16); + buf[3] = (byte) (val >> 24); writeToStdout(buf); } - private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { - Conformance.TestAllTypes testMessage; + private enum BinaryDecoderType { + BTYE_STRING_DECODER, + BYTE_ARRAY_DECODER, + ARRAY_BYTE_BUFFER_DECODER, + READONLY_ARRAY_BYTE_BUFFER_DECODER, + DIRECT_BYTE_BUFFER_DECODER, + READONLY_DIRECT_BYTE_BUFFER_DECODER, + INPUT_STREAM_DECODER; + } - switch (request.getPayloadCase()) { - case PROTOBUF_PAYLOAD: { - try { - testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload()); - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); + private static class BinaryDecoder<T extends MessageLite> { + public T decode( + ByteString bytes, + BinaryDecoderType type, + Parser<T> parser, + ExtensionRegistryLite extensions) + throws InvalidProtocolBufferException { + switch (type) { + case BTYE_STRING_DECODER: + case BYTE_ARRAY_DECODER: + return parser.parseFrom(bytes, extensions); + case ARRAY_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocate(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); + } + case READONLY_ARRAY_BYTE_BUFFER_DECODER: + { + return parser.parseFrom( + CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions); + } + case DIRECT_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions); + } + case READONLY_DIRECT_BYTE_BUFFER_DECODER: + { + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); + bytes.copyTo(buffer); + buffer.flip(); + return parser.parseFrom( + CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions); + } + case INPUT_STREAM_DECODER: + { + return parser.parseFrom(bytes.newInput(), extensions); + } + } + return null; + } + } + + private <T extends MessageLite> T parseBinary( + ByteString bytes, Parser<T> parser, ExtensionRegistryLite extensions) + throws InvalidProtocolBufferException { + ArrayList<T> messages = new ArrayList<>(); + ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>(); + + for (int i = 0; i < BinaryDecoderType.values().length; i++) { + messages.add(null); + exceptions.add(null); + } + if (messages.isEmpty()) { + throw new RuntimeException("binary decoder types missing"); + } + + BinaryDecoder<T> decoder = new BinaryDecoder<>(); + + boolean hasMessage = false; + boolean hasException = false; + for (int i = 0; i < BinaryDecoderType.values().length; ++i) { + try { + messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions)); + hasMessage = true; + } catch (InvalidProtocolBufferException e) { + exceptions.set(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 < BinaryDecoderType.values().length; ++i) { + sb.append(BinaryDecoderType.values()[i].name()); + if (messages.get(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. + InvalidProtocolBufferException exception = null; + for (InvalidProtocolBufferException e : exceptions) { + if (exception != null) { + exception.addSuppressed(e); + } else { + exception = e; + } + } + throw exception; + } + + // 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.size(); ++i) { + if (!messages.get(0).equals(messages.get(i))) { + allEqual = false; break; } - case JSON_PAYLOAD: { - return Conformance.ConformanceResponse.newBuilder().setSkipped( - "Lite runtime does not support JSON format.").build(); - } - case PAYLOAD_NOT_SET: { - throw new RuntimeException("Request didn't have payload."); - } + } - default: { - throw new RuntimeException("Unexpected payload case."); + // Slow path: compare and find out all unequal pairs. + if (!allEqual) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < messages.size() - 1; ++i) { + for (int j = i + 1; j < messages.size(); ++j) { + if (!messages.get(i).equals(messages.get(j))) { + sb.append(BinaryDecoderType.values()[i].name()) + .append(" and ") + .append(BinaryDecoderType.values()[j].name()) + .append(" parsed the payload differently.\n"); + } + } } + throw new RuntimeException(sb.toString()); + } + + return messages.get(0); + } + + private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { + com.google.protobuf.MessageLite testMessage; + boolean isProto3 = + request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3"); + boolean isProto2 = + request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2"); + + switch (request.getPayloadCase()) { + case PROTOBUF_PAYLOAD: + { + if (isProto3) { + try { + ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance(); + TestMessagesProto3.registerAllExtensions(extensions); + testMessage = + parseBinary( + request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } + } else if (isProto2) { + try { + ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance(); + TestMessagesProto2.registerAllExtensions(extensions); + testMessage = + parseBinary( + request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } + } else { + throw new RuntimeException("Protobuf request doesn't have specific payload type."); + } + break; + } + case JSON_PAYLOAD: + { + return Conformance.ConformanceResponse.newBuilder() + .setSkipped("Lite runtime does not support JSON format.") + .build(); + } + case TEXT_PAYLOAD: + { + return Conformance.ConformanceResponse.newBuilder() + .setSkipped("Lite runtime does not support Text format.") + .build(); + } + case PAYLOAD_NOT_SET: + { + throw new RuntimeException("Request didn't have payload."); + } + default: + { + throw new RuntimeException("Unexpected payload case."); + } } switch (request.getRequestedOutputFormat()) { @@ -103,15 +292,23 @@ throw new RuntimeException("Unspecified output format."); case PROTOBUF: - return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build(); + return Conformance.ConformanceResponse.newBuilder() + .setProtobufPayload(testMessage.toByteString()) + .build(); case JSON: - return Conformance.ConformanceResponse.newBuilder().setSkipped( - "Lite runtime does not support JSON format.").build(); + return Conformance.ConformanceResponse.newBuilder() + .setSkipped("Lite runtime does not support JSON format.") + .build(); - default: { - throw new RuntimeException("Unexpected request output."); - } + case TEXT_FORMAT: + return Conformance.ConformanceResponse.newBuilder() + .setSkipped("Lite runtime does not support Text format.") + .build(); + default: + { + throw new RuntimeException("Unexpected request output."); + } } } @@ -119,7 +316,7 @@ int bytes = readLittleEndianIntFromStdin(); if (bytes == -1) { - return false; // EOF + return false; // EOF } byte[] serializedInput = new byte[bytes]; @@ -144,8 +341,8 @@ this.testCount++; } - System.err.println("ConformanceJavaLite: received EOF from test runner after " + - this.testCount + " tests"); + System.err.println( + "ConformanceJavaLite: received EOF from test runner after " + this.testCount + " tests"); } public static void main(String[] args) throws Exception {