blob: 1202050a03353ced49187b4fc1d4c4620d19fda0 [file] [log] [blame]
Herbie Ongd64dceb2019-04-25 01:19:57 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Damien Neil1de09cb2019-08-20 15:25:49 -07005package conformance_test
Herbie Ongd64dceb2019-04-25 01:19:57 -07006
7import (
8 "encoding/binary"
Joe Tsaidd271b62019-08-16 01:09:33 -07009 "flag"
Herbie Ongd64dceb2019-04-25 01:19:57 -070010 "io"
11 "log"
12 "os"
Joe Tsaidd271b62019-08-16 01:09:33 -070013 "os/exec"
14 "path/filepath"
15 "testing"
Herbie Ongd64dceb2019-04-25 01:19:57 -070016
Damien Neil5c5b5312019-05-14 12:44:37 -070017 "google.golang.org/protobuf/encoding/protojson"
Joe Tsaiabd06a82019-08-16 00:39:27 -070018 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070019 "google.golang.org/protobuf/proto"
Herbie Ongd64dceb2019-04-25 01:19:57 -070020
Damien Neile89e6242019-05-13 23:55:40 -070021 pb "google.golang.org/protobuf/internal/testprotos/conformance"
Herbie Ongd64dceb2019-04-25 01:19:57 -070022)
23
Joe Tsaidd271b62019-08-16 01:09:33 -070024func init() {
25 // When the environment variable RUN_AS_CONFORMANCE_PLUGIN is set,
26 // we skip running the tests and instead act as a conformance plugin.
27 // This allows the binary to pass itself to conformance.
28 if os.Getenv("RUN_AS_CONFORMANCE_PLUGIN") == "1" {
29 main()
30 os.Exit(0)
31 }
32}
33
34var (
35 execute = flag.Bool("execute", false, "execute the conformance test")
36 protoRoot = flag.String("protoroot", os.Getenv("PROTOBUF_ROOT"), "The root of the protobuf source tree.")
37)
38
39func Test(t *testing.T) {
40 if !*execute {
41 t.SkipNow()
42 }
43 binPath := filepath.Join(*protoRoot, "conformance", "conformance-test-runner")
44 cmd := exec.Command(binPath,
45 "--failure_list", "failing_tests.txt",
46 "--text_format_failure_list", "failing_tests_text_format.txt",
47 "--enforce_recommended",
48 os.Args[0])
49 cmd.Env = append(os.Environ(), "RUN_AS_CONFORMANCE_PLUGIN=1")
50 out, err := cmd.CombinedOutput()
51 if err != nil {
52 t.Fatalf("execution error: %v\n\n%s", err, out)
53 }
54}
55
Herbie Ongd64dceb2019-04-25 01:19:57 -070056func main() {
57 var sizeBuf [4]byte
58 inbuf := make([]byte, 0, 4096)
59 for {
60 _, err := io.ReadFull(os.Stdin, sizeBuf[:])
61 if err == io.EOF {
62 break
63 }
64 if err != nil {
65 log.Fatalf("conformance: read request: %v", err)
66 }
67 size := binary.LittleEndian.Uint32(sizeBuf[:])
68 if int(size) > cap(inbuf) {
69 inbuf = make([]byte, size)
70 }
71 inbuf = inbuf[:size]
72 if _, err := io.ReadFull(os.Stdin, inbuf); err != nil {
73 log.Fatalf("conformance: read request: %v", err)
74 }
75
76 req := &pb.ConformanceRequest{}
77 if err := proto.Unmarshal(inbuf, req); err != nil {
78 log.Fatalf("conformance: parse request: %v", err)
79 }
80 res := handle(req)
81
82 out, err := proto.Marshal(res)
83 if err != nil {
84 log.Fatalf("conformance: marshal response: %v", err)
85 }
86 binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(out)))
87 if _, err := os.Stdout.Write(sizeBuf[:]); err != nil {
88 log.Fatalf("conformance: write response: %v", err)
89 }
90 if _, err := os.Stdout.Write(out); err != nil {
91 log.Fatalf("conformance: write response: %v", err)
92 }
93 }
94}
95
Joe Tsaiabd06a82019-08-16 00:39:27 -070096func handle(req *pb.ConformanceRequest) (res *pb.ConformanceResponse) {
Herbie Ongd64dceb2019-04-25 01:19:57 -070097 var msg proto.Message = &pb.TestAllTypesProto2{}
98 if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" {
99 msg = &pb.TestAllTypesProto3{}
100 }
101
Joe Tsaiabd06a82019-08-16 00:39:27 -0700102 // Unmarshal the test message.
103 var err error
Herbie Ongd64dceb2019-04-25 01:19:57 -0700104 switch p := req.Payload.(type) {
105 case *pb.ConformanceRequest_ProtobufPayload:
106 err = proto.Unmarshal(p.ProtobufPayload, msg)
107 case *pb.ConformanceRequest_JsonPayload:
Damien Neil5c5b5312019-05-14 12:44:37 -0700108 err = protojson.UnmarshalOptions{
Herbie Ong4f0be712019-04-25 17:57:12 -0700109 DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST,
Joe Tsaicdb77732019-05-14 16:05:06 -0700110 }.Unmarshal([]byte(p.JsonPayload), msg)
Joe Tsaiabd06a82019-08-16 00:39:27 -0700111 case *pb.ConformanceRequest_TextPayload:
112 err = prototext.Unmarshal([]byte(p.TextPayload), msg)
Herbie Ongd64dceb2019-04-25 01:19:57 -0700113 default:
114 return &pb.ConformanceResponse{
115 Result: &pb.ConformanceResponse_RuntimeError{
116 RuntimeError: "unknown request payload type",
117 },
118 }
119 }
120 if err != nil {
121 return &pb.ConformanceResponse{
122 Result: &pb.ConformanceResponse_ParseError{
123 ParseError: err.Error(),
124 },
125 }
126 }
127
Joe Tsaiabd06a82019-08-16 00:39:27 -0700128 // Marshal the test message.
129 var b []byte
Herbie Ongd64dceb2019-04-25 01:19:57 -0700130 switch req.RequestedOutputFormat {
131 case pb.WireFormat_PROTOBUF:
Joe Tsaiabd06a82019-08-16 00:39:27 -0700132 b, err = proto.Marshal(msg)
133 res = &pb.ConformanceResponse{
Herbie Ongd64dceb2019-04-25 01:19:57 -0700134 Result: &pb.ConformanceResponse_ProtobufPayload{
Joe Tsaiabd06a82019-08-16 00:39:27 -0700135 ProtobufPayload: b,
Herbie Ongd64dceb2019-04-25 01:19:57 -0700136 },
137 }
138 case pb.WireFormat_JSON:
Joe Tsaiabd06a82019-08-16 00:39:27 -0700139 b, err = protojson.Marshal(msg)
140 res = &pb.ConformanceResponse{
Herbie Ongd64dceb2019-04-25 01:19:57 -0700141 Result: &pb.ConformanceResponse_JsonPayload{
Joe Tsaiabd06a82019-08-16 00:39:27 -0700142 JsonPayload: string(b),
143 },
144 }
145 case pb.WireFormat_TEXT_FORMAT:
Joe Tsaicd4a31e2019-09-14 19:14:24 -0700146 b, err = prototext.MarshalOptions{
147 EmitUnknown: req.PrintUnknownFields,
148 }.Marshal(msg)
Joe Tsaiabd06a82019-08-16 00:39:27 -0700149 res = &pb.ConformanceResponse{
150 Result: &pb.ConformanceResponse_TextPayload{
151 TextPayload: string(b),
Herbie Ongd64dceb2019-04-25 01:19:57 -0700152 },
153 }
154 default:
155 return &pb.ConformanceResponse{
156 Result: &pb.ConformanceResponse_RuntimeError{
157 RuntimeError: "unknown output format",
158 },
159 }
160 }
Joe Tsaiabd06a82019-08-16 00:39:27 -0700161 if err != nil {
162 return &pb.ConformanceResponse{
163 Result: &pb.ConformanceResponse_SerializeError{
164 SerializeError: err.Error(),
165 },
166 }
167 }
168 return res
Herbie Ongd64dceb2019-04-25 01:19:57 -0700169}