1
2
3
4
5 package conformance_test
6
7 import (
8 "encoding/binary"
9 "flag"
10 "io"
11 "log"
12 "os"
13 "os/exec"
14 "path/filepath"
15 "testing"
16
17 "google.golang.org/protobuf/encoding/protojson"
18 "google.golang.org/protobuf/encoding/prototext"
19 "google.golang.org/protobuf/proto"
20
21 pb "google.golang.org/protobuf/internal/testprotos/conformance"
22 )
23
24 func init() {
25
26
27
28 if os.Getenv("RUN_AS_CONFORMANCE_PLUGIN") == "1" {
29 main()
30 os.Exit(0)
31 }
32 }
33
34 var (
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
39 func Test(t *testing.T) {
40 if !*execute {
41 t.SkipNow()
42 }
43 binPath := filepath.Join(*protoRoot, "bazel-bin", "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
56 func 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
96 func handle(req *pb.ConformanceRequest) (res *pb.ConformanceResponse) {
97 var msg proto.Message = &pb.TestAllTypesProto2{}
98 if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" {
99 msg = &pb.TestAllTypesProto3{}
100 }
101
102
103 var err error
104 switch p := req.Payload.(type) {
105 case *pb.ConformanceRequest_ProtobufPayload:
106 err = proto.Unmarshal(p.ProtobufPayload, msg)
107 case *pb.ConformanceRequest_JsonPayload:
108 err = protojson.UnmarshalOptions{
109 DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST,
110 }.Unmarshal([]byte(p.JsonPayload), msg)
111 case *pb.ConformanceRequest_TextPayload:
112 err = prototext.Unmarshal([]byte(p.TextPayload), msg)
113 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
128
129 var b []byte
130 switch req.RequestedOutputFormat {
131 case pb.WireFormat_PROTOBUF:
132 b, err = proto.Marshal(msg)
133 res = &pb.ConformanceResponse{
134 Result: &pb.ConformanceResponse_ProtobufPayload{
135 ProtobufPayload: b,
136 },
137 }
138 case pb.WireFormat_JSON:
139 b, err = protojson.Marshal(msg)
140 res = &pb.ConformanceResponse{
141 Result: &pb.ConformanceResponse_JsonPayload{
142 JsonPayload: string(b),
143 },
144 }
145 case pb.WireFormat_TEXT_FORMAT:
146 b, err = prototext.MarshalOptions{
147 EmitUnknown: req.PrintUnknownFields,
148 }.Marshal(msg)
149 res = &pb.ConformanceResponse{
150 Result: &pb.ConformanceResponse_TextPayload{
151 TextPayload: string(b),
152 },
153 }
154 default:
155 return &pb.ConformanceResponse{
156 Result: &pb.ConformanceResponse_RuntimeError{
157 RuntimeError: "unknown output format",
158 },
159 }
160 }
161 if err != nil {
162 return &pb.ConformanceResponse{
163 Result: &pb.ConformanceResponse_SerializeError{
164 SerializeError: err.Error(),
165 },
166 }
167 }
168 return res
169 }
170
View as plain text