Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 1 | // 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 Neil | 1de09cb | 2019-08-20 15:25:49 -0700 | [diff] [blame] | 5 | package conformance_test |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 6 | |
| 7 | import ( |
| 8 | "encoding/binary" |
Joe Tsai | dd271b6 | 2019-08-16 01:09:33 -0700 | [diff] [blame] | 9 | "flag" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 10 | "io" |
| 11 | "log" |
| 12 | "os" |
Joe Tsai | dd271b6 | 2019-08-16 01:09:33 -0700 | [diff] [blame] | 13 | "os/exec" |
| 14 | "path/filepath" |
| 15 | "testing" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 16 | |
Damien Neil | 5c5b531 | 2019-05-14 12:44:37 -0700 | [diff] [blame] | 17 | "google.golang.org/protobuf/encoding/protojson" |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 18 | "google.golang.org/protobuf/encoding/prototext" |
Damien Neil | e89e624 | 2019-05-13 23:55:40 -0700 | [diff] [blame] | 19 | "google.golang.org/protobuf/proto" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 20 | |
Damien Neil | e89e624 | 2019-05-13 23:55:40 -0700 | [diff] [blame] | 21 | pb "google.golang.org/protobuf/internal/testprotos/conformance" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 22 | ) |
| 23 | |
Joe Tsai | dd271b6 | 2019-08-16 01:09:33 -0700 | [diff] [blame] | 24 | func 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 | |
| 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, "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 Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 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 | |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 96 | func handle(req *pb.ConformanceRequest) (res *pb.ConformanceResponse) { |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 97 | var msg proto.Message = &pb.TestAllTypesProto2{} |
| 98 | if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" { |
| 99 | msg = &pb.TestAllTypesProto3{} |
| 100 | } |
| 101 | |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 102 | // Unmarshal the test message. |
| 103 | var err error |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 104 | switch p := req.Payload.(type) { |
| 105 | case *pb.ConformanceRequest_ProtobufPayload: |
| 106 | err = proto.Unmarshal(p.ProtobufPayload, msg) |
| 107 | case *pb.ConformanceRequest_JsonPayload: |
Damien Neil | 5c5b531 | 2019-05-14 12:44:37 -0700 | [diff] [blame] | 108 | err = protojson.UnmarshalOptions{ |
Herbie Ong | 4f0be71 | 2019-04-25 17:57:12 -0700 | [diff] [blame] | 109 | DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST, |
Joe Tsai | cdb7773 | 2019-05-14 16:05:06 -0700 | [diff] [blame] | 110 | }.Unmarshal([]byte(p.JsonPayload), msg) |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 111 | case *pb.ConformanceRequest_TextPayload: |
| 112 | err = prototext.Unmarshal([]byte(p.TextPayload), msg) |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 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 | |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 128 | // Marshal the test message. |
| 129 | var b []byte |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 130 | switch req.RequestedOutputFormat { |
| 131 | case pb.WireFormat_PROTOBUF: |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 132 | b, err = proto.Marshal(msg) |
| 133 | res = &pb.ConformanceResponse{ |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 134 | Result: &pb.ConformanceResponse_ProtobufPayload{ |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 135 | ProtobufPayload: b, |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 136 | }, |
| 137 | } |
| 138 | case pb.WireFormat_JSON: |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 139 | b, err = protojson.Marshal(msg) |
| 140 | res = &pb.ConformanceResponse{ |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 141 | Result: &pb.ConformanceResponse_JsonPayload{ |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 142 | JsonPayload: string(b), |
| 143 | }, |
| 144 | } |
| 145 | case pb.WireFormat_TEXT_FORMAT: |
Joe Tsai | cd4a31e | 2019-09-14 19:14:24 -0700 | [diff] [blame] | 146 | b, err = prototext.MarshalOptions{ |
| 147 | EmitUnknown: req.PrintUnknownFields, |
| 148 | }.Marshal(msg) |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 149 | res = &pb.ConformanceResponse{ |
| 150 | Result: &pb.ConformanceResponse_TextPayload{ |
| 151 | TextPayload: string(b), |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 152 | }, |
| 153 | } |
| 154 | default: |
| 155 | return &pb.ConformanceResponse{ |
| 156 | Result: &pb.ConformanceResponse_RuntimeError{ |
| 157 | RuntimeError: "unknown output format", |
| 158 | }, |
| 159 | } |
| 160 | } |
Joe Tsai | abd06a8 | 2019-08-16 00:39:27 -0700 | [diff] [blame] | 161 | if err != nil { |
| 162 | return &pb.ConformanceResponse{ |
| 163 | Result: &pb.ConformanceResponse_SerializeError{ |
| 164 | SerializeError: err.Error(), |
| 165 | }, |
| 166 | } |
| 167 | } |
| 168 | return res |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 169 | } |