Przeglądaj źródła

Added conformance test support for Java.

Change-Id: I4c81808e6ace77d2b5737a43417045321b0b10f0
Josh Haberman 10 lat temu
rodzic
commit
420f938bac

+ 120 - 0
conformance/ConformanceJava.java

@@ -0,0 +1,120 @@
+
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+class ConformanceJava {
+  private int testCount = 0;
+
+  private boolean readFromStdin(byte[] buf, int len) throws Exception {
+    int ofs = 0;
+    while (len > 0) {
+      int read = System.in.read(buf, ofs, len);
+      if (read == -1) {
+        return false;  // EOF
+      }
+      ofs += read;
+      len -= read;
+    }
+
+    return true;
+  }
+
+  private void writeToStdout(byte[] buf) throws Exception {
+    System.out.write(buf);
+  }
+
+  // Returns -1 on EOF (the actual values will always be positive).
+  private int readLittleEndianIntFromStdin() throws Exception {
+    byte[] buf = new byte[4];
+    if (!readFromStdin(buf, 4)) {
+      return -1;
+    }
+    return buf[0] | (buf[1] << 1) | (buf[2] << 2) | (buf[3] << 3);
+  }
+
+  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);
+    writeToStdout(buf);
+  }
+
+  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+    Conformance.TestAllTypes testMessage;
+
+    switch (request.getPayloadCase()) {
+      case PROTOBUF_PAYLOAD: {
+        try {
+          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
+        } catch (InvalidProtocolBufferException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
+      case JSON_PAYLOAD: {
+        return Conformance.ConformanceResponse.newBuilder().setRuntimeError("JSON not yet supported.").build();
+      }
+      case PAYLOAD_NOT_SET: {
+        throw new RuntimeException("Request didn't have payload.");
+      }
+
+      default: {
+        throw new RuntimeException("Unexpected payload case.");
+      }
+    }
+
+    switch (request.getRequestedOutput()) {
+      case UNSPECIFIED:
+        throw new RuntimeException("Unspecified output format.");
+
+      case PROTOBUF:
+        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+
+      case JSON:
+        return Conformance.ConformanceResponse.newBuilder().setRuntimeError("JSON not yet supported.").build();
+
+      default: {
+        throw new RuntimeException("Unexpected request output.");
+      }
+    }
+  }
+
+  private boolean doTestIo() throws Exception {
+    int bytes = readLittleEndianIntFromStdin();
+
+    if (bytes == -1) {
+      return false;  // EOF
+    }
+
+    byte[] serializedInput = new byte[bytes];
+
+    if (!readFromStdin(serializedInput, bytes)) {
+      throw new RuntimeException("Unexpected EOF from test program.");
+    }
+
+    Conformance.ConformanceRequest request =
+        Conformance.ConformanceRequest.parseFrom(serializedInput);
+    Conformance.ConformanceResponse response = doTest(request);
+    byte[] serializedOutput = response.toByteArray();
+
+    writeLittleEndianIntToStdout(serializedOutput.length);
+    writeToStdout(serializedOutput);
+
+    return true;
+  }
+
+  public void run() throws Exception {
+    while (doTestIo()) {
+      // Empty.
+    }
+
+    System.err.println("ConformanceJava: received EOF from test runner after " +
+        this.testCount + " tests");
+  }
+
+  public static void main(String[] args) throws Exception {
+    new ConformanceJava().run();
+  }
+}

+ 22 - 9
conformance/Makefile.am

@@ -21,30 +21,43 @@ conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
 
 
 if USE_EXTERNAL_PROTOC
 if USE_EXTERNAL_PROTOC
 
 
-unittest_proto_middleman: $(protoc_inputs)
-	$(PROTOC) -I$(srcdir) --cpp_out=. $^
-	touch unittest_proto_middleman
+protoc_middleman: $(protoc_inputs)
+	$(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. $^
+	touch protoc_middleman
 
 
 else
 else
 
 
 # We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
 # We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
 # relative to srcdir, which may not be the same as the current directory when
 # relative to srcdir, which may not be the same as the current directory when
 # building out-of-tree.
 # building out-of-tree.
-unittest_proto_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) )
-	touch unittest_proto_middleman
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd $(protoc_inputs) )
+	touch protoc_middleman
 
 
 endif
 endif
 
 
-$(protoc_outputs): unittest_proto_middleman
+$(protoc_outputs): protoc_middleman
 
 
 BUILT_SOURCES = $(protoc_outputs)
 BUILT_SOURCES = $(protoc_outputs)
 
 
-CLEANFILES = $(protoc_outputs) unittest_proto_middleman
+CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java
 
 
 MAINTAINERCLEANFILES =   \
 MAINTAINERCLEANFILES =   \
   Makefile.in
   Makefile.in
 
 
+javac_middleman: ConformanceJava.java protoc_middleman
+	javac ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+	@touch javac_middleman
+
+conformance-java: javac_middleman
+	@echo "Writing shortcut script conformance-java..."
+	@echo '#! /bin/sh' > conformance-java
+	@echo 'java -classpath .:$$CLASSPATH ConformanceJava "$$@"' >> conformance-java
+	@chmod +x conformance-java
+
 # Targets for actually running tests.
 # Targets for actually running tests.
-test_cpp: unittest_proto_middleman conformance-test-runner conformance-cpp
+test_cpp: protoc_middleman conformance-test-runner conformance-cpp
 	./conformance-test-runner ./conformance-cpp
 	./conformance-test-runner ./conformance-cpp
+
+test_java: protoc_middleman conformance-test-runner conformance-java
+	./conformance-test-runner ./conformance-java

+ 1 - 0
conformance/conformance.proto

@@ -30,6 +30,7 @@
 
 
 syntax = "proto3";
 syntax = "proto3";
 package conformance;
 package conformance;
+option java_package = "com.google.protobuf.conformance";
 
 
 // This defines the conformance testing protocol.  This protocol exists between
 // This defines the conformance testing protocol.  This protocol exists between
 // the conformance test suite itself and the code being tested.  For each test,
 // the conformance test suite itself and the code being tested.  For each test,

+ 2 - 2
conformance/conformance_test_runner.cc

@@ -48,9 +48,9 @@
 // Every test consists of a ConformanceRequest/ConformanceResponse
 // Every test consists of a ConformanceRequest/ConformanceResponse
 // request/reply pair.  The protocol on the pipe is simply:
 // request/reply pair.  The protocol on the pipe is simply:
 //
 //
-//   1. tester sends 4-byte length N
+//   1. tester sends 4-byte length N (little endian)
 //   2. tester sends N bytes representing a ConformanceRequest proto
 //   2. tester sends N bytes representing a ConformanceRequest proto
-//   3. testee sends 4-byte length M
+//   3. testee sends 4-byte length M (little endian)
 //   4. testee sends M bytes representing a ConformanceResponse proto
 //   4. testee sends M bytes representing a ConformanceResponse proto
 
 
 #include <errno.h>
 #include <errno.h>