integration_test: add conformance tests
Change-Id: I3c21e5069c34a6417c9177ae5f1bdcb801418c8a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/173665
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/cmd/conformance/conformance.sh b/internal/cmd/conformance/conformance.sh
new file mode 100755
index 0000000..c82ad6a
--- /dev/null
+++ b/internal/cmd/conformance/conformance.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Copyright 2019 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+cd $(dirname $0)
+exec go run main.go $@
diff --git a/internal/cmd/conformance/failure_list_go.txt b/internal/cmd/conformance/failure_list_go.txt
new file mode 100644
index 0000000..f30c4c6
--- /dev/null
+++ b/internal/cmd/conformance/failure_list_go.txt
@@ -0,0 +1,7 @@
+Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
diff --git a/internal/cmd/conformance/main.go b/internal/cmd/conformance/main.go
new file mode 100644
index 0000000..a779929
--- /dev/null
+++ b/internal/cmd/conformance/main.go
@@ -0,0 +1,124 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This binary implements the conformance test subprocess protocol as documented
+// in conformance.proto.
+package main
+
+import (
+ "encoding/binary"
+ "io"
+ "log"
+ "os"
+
+ "github.com/golang/protobuf/v2/encoding/jsonpb"
+ "github.com/golang/protobuf/v2/proto"
+
+ pb "github.com/golang/protobuf/v2/internal/testprotos/conformance"
+)
+
+func main() {
+ var sizeBuf [4]byte
+ inbuf := make([]byte, 0, 4096)
+ for {
+ _, err := io.ReadFull(os.Stdin, sizeBuf[:])
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ log.Fatalf("conformance: read request: %v", err)
+ }
+ size := binary.LittleEndian.Uint32(sizeBuf[:])
+ if int(size) > cap(inbuf) {
+ inbuf = make([]byte, size)
+ }
+ inbuf = inbuf[:size]
+ if _, err := io.ReadFull(os.Stdin, inbuf); err != nil {
+ log.Fatalf("conformance: read request: %v", err)
+ }
+
+ req := &pb.ConformanceRequest{}
+ if err := proto.Unmarshal(inbuf, req); err != nil {
+ log.Fatalf("conformance: parse request: %v", err)
+ }
+ res := handle(req)
+
+ out, err := proto.Marshal(res)
+ if err != nil {
+ log.Fatalf("conformance: marshal response: %v", err)
+ }
+ binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(out)))
+ if _, err := os.Stdout.Write(sizeBuf[:]); err != nil {
+ log.Fatalf("conformance: write response: %v", err)
+ }
+ if _, err := os.Stdout.Write(out); err != nil {
+ log.Fatalf("conformance: write response: %v", err)
+ }
+ }
+}
+
+func handle(req *pb.ConformanceRequest) *pb.ConformanceResponse {
+ var err error
+ var msg proto.Message = &pb.TestAllTypesProto2{}
+ if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" {
+ msg = &pb.TestAllTypesProto3{}
+ }
+
+ switch p := req.Payload.(type) {
+ case *pb.ConformanceRequest_ProtobufPayload:
+ err = proto.Unmarshal(p.ProtobufPayload, msg)
+ case *pb.ConformanceRequest_JsonPayload:
+ err = jsonpb.Unmarshal(msg, []byte(p.JsonPayload))
+ default:
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_RuntimeError{
+ RuntimeError: "unknown request payload type",
+ },
+ }
+ }
+ if err != nil {
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_ParseError{
+ ParseError: err.Error(),
+ },
+ }
+ }
+
+ switch req.RequestedOutputFormat {
+ case pb.WireFormat_PROTOBUF:
+ p, err := proto.Marshal(msg)
+ if err != nil {
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_SerializeError{
+ SerializeError: err.Error(),
+ },
+ }
+ }
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_ProtobufPayload{
+ ProtobufPayload: p,
+ },
+ }
+ case pb.WireFormat_JSON:
+ p, err := jsonpb.Marshal(msg)
+ if err != nil {
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_SerializeError{
+ SerializeError: err.Error(),
+ },
+ }
+ }
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_JsonPayload{
+ JsonPayload: string(p),
+ },
+ }
+ default:
+ return &pb.ConformanceResponse{
+ Result: &pb.ConformanceResponse_RuntimeError{
+ RuntimeError: "unknown output format",
+ },
+ }
+ }
+}
diff --git a/internal/cmd/generate-protos/main.go b/internal/cmd/generate-protos/main.go
index 78e3c19..2d03750 100644
--- a/internal/cmd/generate-protos/main.go
+++ b/internal/cmd/generate-protos/main.go
@@ -185,6 +185,8 @@
{"src", "google/protobuf/field_mask.proto"},
{"src", "google/protobuf/source_context.proto"},
{"src", "google/protobuf/struct.proto"},
+ {"src", "google/protobuf/test_messages_proto2.proto"},
+ {"src", "google/protobuf/test_messages_proto3.proto"},
{"src", "google/protobuf/timestamp.proto"},
{"src", "google/protobuf/type.proto"},
{"src", "google/protobuf/wrappers.proto"},