1 2 import com.google.protobuf.conformance.Conformance; 3 import com.google.protobuf.util.JsonFormat; 4 import com.google.protobuf.util.JsonFormat.TypeRegistry; 5 import com.google.protobuf.InvalidProtocolBufferException; 6 7 class ConformanceJava { 8 private int testCount = 0; 9 private TypeRegistry typeRegistry; 10 readFromStdin(byte[] buf, int len)11 private boolean readFromStdin(byte[] buf, int len) throws Exception { 12 int ofs = 0; 13 while (len > 0) { 14 int read = System.in.read(buf, ofs, len); 15 if (read == -1) { 16 return false; // EOF 17 } 18 ofs += read; 19 len -= read; 20 } 21 22 return true; 23 } 24 writeToStdout(byte[] buf)25 private void writeToStdout(byte[] buf) throws Exception { 26 System.out.write(buf); 27 } 28 29 // Returns -1 on EOF (the actual values will always be positive). readLittleEndianIntFromStdin()30 private int readLittleEndianIntFromStdin() throws Exception { 31 byte[] buf = new byte[4]; 32 if (!readFromStdin(buf, 4)) { 33 return -1; 34 } 35 return (buf[0] & 0xff) 36 | ((buf[1] & 0xff) << 8) 37 | ((buf[2] & 0xff) << 16) 38 | ((buf[3] & 0xff) << 24); 39 } 40 writeLittleEndianIntToStdout(int val)41 private void writeLittleEndianIntToStdout(int val) throws Exception { 42 byte[] buf = new byte[4]; 43 buf[0] = (byte)val; 44 buf[1] = (byte)(val >> 8); 45 buf[2] = (byte)(val >> 16); 46 buf[3] = (byte)(val >> 24); 47 writeToStdout(buf); 48 } 49 doTest(Conformance.ConformanceRequest request)50 private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { 51 Conformance.TestAllTypes testMessage; 52 53 switch (request.getPayloadCase()) { 54 case PROTOBUF_PAYLOAD: { 55 try { 56 testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload()); 57 } catch (InvalidProtocolBufferException e) { 58 return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); 59 } 60 break; 61 } 62 case JSON_PAYLOAD: { 63 try { 64 Conformance.TestAllTypes.Builder builder = Conformance.TestAllTypes.newBuilder(); 65 JsonFormat.parser().usingTypeRegistry(typeRegistry) 66 .merge(request.getJsonPayload(), builder); 67 testMessage = builder.build(); 68 } catch (InvalidProtocolBufferException e) { 69 return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); 70 } 71 break; 72 } 73 case PAYLOAD_NOT_SET: { 74 throw new RuntimeException("Request didn't have payload."); 75 } 76 77 default: { 78 throw new RuntimeException("Unexpected payload case."); 79 } 80 } 81 82 switch (request.getRequestedOutputFormat()) { 83 case UNSPECIFIED: 84 throw new RuntimeException("Unspecified output format."); 85 86 case PROTOBUF: 87 return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build(); 88 89 case JSON: 90 try { 91 return Conformance.ConformanceResponse.newBuilder().setJsonPayload( 92 JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build(); 93 } catch (InvalidProtocolBufferException | IllegalArgumentException e) { 94 return Conformance.ConformanceResponse.newBuilder().setSerializeError( 95 e.getMessage()).build(); 96 } 97 98 default: { 99 throw new RuntimeException("Unexpected request output."); 100 } 101 } 102 } 103 doTestIo()104 private boolean doTestIo() throws Exception { 105 int bytes = readLittleEndianIntFromStdin(); 106 107 if (bytes == -1) { 108 return false; // EOF 109 } 110 111 byte[] serializedInput = new byte[bytes]; 112 113 if (!readFromStdin(serializedInput, bytes)) { 114 throw new RuntimeException("Unexpected EOF from test program."); 115 } 116 117 Conformance.ConformanceRequest request = 118 Conformance.ConformanceRequest.parseFrom(serializedInput); 119 Conformance.ConformanceResponse response = doTest(request); 120 byte[] serializedOutput = response.toByteArray(); 121 122 writeLittleEndianIntToStdout(serializedOutput.length); 123 writeToStdout(serializedOutput); 124 125 return true; 126 } 127 run()128 public void run() throws Exception { 129 typeRegistry = TypeRegistry.newBuilder().add( 130 Conformance.TestAllTypes.getDescriptor()).build(); 131 while (doTestIo()) { 132 this.testCount++; 133 } 134 135 System.err.println("ConformanceJava: received EOF from test runner after " + 136 this.testCount + " tests"); 137 } 138 main(String[] args)139 public static void main(String[] args) throws Exception { 140 new ConformanceJava().run(); 141 } 142 } 143