1
2
3
4
5 package conformance_test
6
7 import (
8 "encoding/binary"
9 "flag"
10 "fmt"
11 "io"
12 "log"
13 "os"
14 "os/exec"
15 "path/filepath"
16 "testing"
17
18 "google.golang.org/protobuf/encoding/protojson"
19 "google.golang.org/protobuf/encoding/prototext"
20 "google.golang.org/protobuf/proto"
21
22 pb "google.golang.org/protobuf/internal/testprotos/conformance"
23 epb "google.golang.org/protobuf/internal/testprotos/conformance/editions"
24 empb "google.golang.org/protobuf/internal/testprotos/conformance/editionsmigration"
25 )
26
27 func init() {
28
29
30
31 if os.Getenv("RUN_AS_CONFORMANCE_PLUGIN") == "1" {
32 main()
33 os.Exit(0)
34 }
35 }
36
37 var (
38 execute = flag.Bool("execute", false, "execute the conformance test")
39 protoRoot = flag.String("protoroot", os.Getenv("PROTOBUF_ROOT"), "The root of the protobuf source tree.")
40 )
41
42 func Test(t *testing.T) {
43 if !*execute {
44 t.SkipNow()
45 }
46 binPath := filepath.Join(*protoRoot, "bazel-bin", "conformance", "conformance_test_runner")
47 cmd := exec.Command(binPath,
48 "--failure_list", "failing_tests.txt",
49 "--text_format_failure_list", "failing_tests_text_format.txt",
50 "--enforce_recommended",
51 "--maximum_edition", "2023",
52 os.Args[0])
53 cmd.Env = append(os.Environ(), "RUN_AS_CONFORMANCE_PLUGIN=1")
54 out, err := cmd.CombinedOutput()
55 if err != nil {
56 t.Fatalf("execution error: %v\n\n%s", err, out)
57 }
58 }
59
60 func main() {
61 var sizeBuf [4]byte
62 inbuf := make([]byte, 0, 4096)
63 for {
64 _, err := io.ReadFull(os.Stdin, sizeBuf[:])
65 if err == io.EOF {
66 break
67 }
68 if err != nil {
69 log.Fatalf("conformance: read request: %v", err)
70 }
71 size := binary.LittleEndian.Uint32(sizeBuf[:])
72 if int(size) > cap(inbuf) {
73 inbuf = make([]byte, size)
74 }
75 inbuf = inbuf[:size]
76 if _, err := io.ReadFull(os.Stdin, inbuf); err != nil {
77 log.Fatalf("conformance: read request: %v", err)
78 }
79
80 req := &pb.ConformanceRequest{}
81 if err := proto.Unmarshal(inbuf, req); err != nil {
82 log.Fatalf("conformance: parse request: %v", err)
83 }
84 res := handle(req)
85
86 out, err := proto.Marshal(res)
87 if err != nil {
88 log.Fatalf("conformance: marshal response: %v", err)
89 }
90 binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(out)))
91 if _, err := os.Stdout.Write(sizeBuf[:]); err != nil {
92 log.Fatalf("conformance: write response: %v", err)
93 }
94 if _, err := os.Stdout.Write(out); err != nil {
95 log.Fatalf("conformance: write response: %v", err)
96 }
97 }
98 }
99
100 func handle(req *pb.ConformanceRequest) (res *pb.ConformanceResponse) {
101 var msg proto.Message = &pb.TestAllTypesProto2{}
102 switch req.GetMessageType() {
103 case "protobuf_test_messages.proto3.TestAllTypesProto3":
104 msg = &pb.TestAllTypesProto3{}
105 case "protobuf_test_messages.proto2.TestAllTypesProto2":
106 msg = &pb.TestAllTypesProto2{}
107 case "protobuf_test_messages.editions.TestAllTypesEdition2023":
108 msg = &epb.TestAllTypesEdition2023{}
109 case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
110 msg = &empb.TestAllTypesProto3{}
111 case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
112 msg = &empb.TestAllTypesProto2{}
113 default:
114 panic(fmt.Sprintf("unknown message type: %s", req.GetMessageType()))
115 }
116
117
118 var err error
119 switch p := req.Payload.(type) {
120 case *pb.ConformanceRequest_ProtobufPayload:
121 err = proto.Unmarshal(p.ProtobufPayload, msg)
122 case *pb.ConformanceRequest_JsonPayload:
123 err = protojson.UnmarshalOptions{
124 DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST,
125 }.Unmarshal([]byte(p.JsonPayload), msg)
126 case *pb.ConformanceRequest_TextPayload:
127 err = prototext.Unmarshal([]byte(p.TextPayload), msg)
128 default:
129 return &pb.ConformanceResponse{
130 Result: &pb.ConformanceResponse_RuntimeError{
131 RuntimeError: "unknown request payload type",
132 },
133 }
134 }
135 if err != nil {
136 return &pb.ConformanceResponse{
137 Result: &pb.ConformanceResponse_ParseError{
138 ParseError: err.Error(),
139 },
140 }
141 }
142
143
144 var b []byte
145 switch req.RequestedOutputFormat {
146 case pb.WireFormat_PROTOBUF:
147 b, err = proto.Marshal(msg)
148 res = &pb.ConformanceResponse{
149 Result: &pb.ConformanceResponse_ProtobufPayload{
150 ProtobufPayload: b,
151 },
152 }
153 case pb.WireFormat_JSON:
154 b, err = protojson.Marshal(msg)
155 res = &pb.ConformanceResponse{
156 Result: &pb.ConformanceResponse_JsonPayload{
157 JsonPayload: string(b),
158 },
159 }
160 case pb.WireFormat_TEXT_FORMAT:
161 b, err = prototext.MarshalOptions{
162 EmitUnknown: req.PrintUnknownFields,
163 }.Marshal(msg)
164 res = &pb.ConformanceResponse{
165 Result: &pb.ConformanceResponse_TextPayload{
166 TextPayload: string(b),
167 },
168 }
169 default:
170 return &pb.ConformanceResponse{
171 Result: &pb.ConformanceResponse_RuntimeError{
172 RuntimeError: "unknown output format",
173 },
174 }
175 }
176 if err != nil {
177 return &pb.ConformanceResponse{
178 Result: &pb.ConformanceResponse_SerializeError{
179 SerializeError: err.Error(),
180 },
181 }
182 }
183 return res
184 }
185
View as plain text