1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31import com.google.protobuf.conformance.Conformance;
32import com.google.protobuf.InvalidProtocolBufferException;
33
34class ConformanceJavaLite {
35  private int testCount = 0;
36
37  private boolean readFromStdin(byte[] buf, int len) throws Exception {
38    int ofs = 0;
39    while (len > 0) {
40      int read = System.in.read(buf, ofs, len);
41      if (read == -1) {
42        return false;  // EOF
43      }
44      ofs += read;
45      len -= read;
46    }
47
48    return true;
49  }
50
51  private void writeToStdout(byte[] buf) throws Exception {
52    System.out.write(buf);
53  }
54
55  // Returns -1 on EOF (the actual values will always be positive).
56  private int readLittleEndianIntFromStdin() throws Exception {
57    byte[] buf = new byte[4];
58    if (!readFromStdin(buf, 4)) {
59      return -1;
60    }
61    return (buf[0] & 0xff)
62        | ((buf[1] & 0xff) << 8)
63        | ((buf[2] & 0xff) << 16)
64        | ((buf[3] & 0xff) << 24);
65  }
66
67  private void writeLittleEndianIntToStdout(int val) throws Exception {
68    byte[] buf = new byte[4];
69    buf[0] = (byte)val;
70    buf[1] = (byte)(val >> 8);
71    buf[2] = (byte)(val >> 16);
72    buf[3] = (byte)(val >> 24);
73    writeToStdout(buf);
74  }
75
76  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
77    Conformance.TestAllTypes testMessage;
78
79    switch (request.getPayloadCase()) {
80      case PROTOBUF_PAYLOAD: {
81        try {
82          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
83        } catch (InvalidProtocolBufferException e) {
84          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
85        }
86        break;
87      }
88      case JSON_PAYLOAD: {
89        return Conformance.ConformanceResponse.newBuilder().setSkipped(
90            "Lite runtime does not support JSON format.").build();
91      }
92      case PAYLOAD_NOT_SET: {
93        throw new RuntimeException("Request didn't have payload.");
94      }
95
96      default: {
97        throw new RuntimeException("Unexpected payload case.");
98      }
99    }
100
101    switch (request.getRequestedOutputFormat()) {
102      case UNSPECIFIED:
103        throw new RuntimeException("Unspecified output format.");
104
105      case PROTOBUF:
106        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
107
108      case JSON:
109        return Conformance.ConformanceResponse.newBuilder().setSkipped(
110            "Lite runtime does not support JSON format.").build();
111
112      default: {
113        throw new RuntimeException("Unexpected request output.");
114      }
115    }
116  }
117
118  private boolean doTestIo() throws Exception {
119    int bytes = readLittleEndianIntFromStdin();
120
121    if (bytes == -1) {
122      return false;  // EOF
123    }
124
125    byte[] serializedInput = new byte[bytes];
126
127    if (!readFromStdin(serializedInput, bytes)) {
128      throw new RuntimeException("Unexpected EOF from test program.");
129    }
130
131    Conformance.ConformanceRequest request =
132        Conformance.ConformanceRequest.parseFrom(serializedInput);
133    Conformance.ConformanceResponse response = doTest(request);
134    byte[] serializedOutput = response.toByteArray();
135
136    writeLittleEndianIntToStdout(serializedOutput.length);
137    writeToStdout(serializedOutput);
138
139    return true;
140  }
141
142  public void run() throws Exception {
143    while (doTestIo()) {
144      this.testCount++;
145    }
146
147    System.err.println("ConformanceJavaLite: received EOF from test runner after " +
148        this.testCount + " tests");
149  }
150
151  public static void main(String[] args) throws Exception {
152    new ConformanceJavaLite().run();
153  }
154}
155