Home | History | Annotate | Download | only in conformance
      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 
     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 
     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).
     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 
     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 
     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 
    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 
    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 
    139   public static void main(String[] args) throws Exception {
    140     new ConformanceJava().run();
    141   }
    142 }
    143