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 | |
| 5 | // This binary implements the conformance test subprocess protocol as documented |
| 6 | // in conformance.proto. |
| 7 | package main |
| 8 | |
| 9 | import ( |
| 10 | "encoding/binary" |
| 11 | "io" |
| 12 | "log" |
| 13 | "os" |
| 14 | |
Damien Neil | 5c5b531 | 2019-05-14 12:44:37 -0700 | [diff] [blame^] | 15 | "google.golang.org/protobuf/encoding/protojson" |
Damien Neil | e89e624 | 2019-05-13 23:55:40 -0700 | [diff] [blame] | 16 | "google.golang.org/protobuf/proto" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 17 | |
Damien Neil | e89e624 | 2019-05-13 23:55:40 -0700 | [diff] [blame] | 18 | pb "google.golang.org/protobuf/internal/testprotos/conformance" |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 19 | ) |
| 20 | |
| 21 | func main() { |
| 22 | var sizeBuf [4]byte |
| 23 | inbuf := make([]byte, 0, 4096) |
| 24 | for { |
| 25 | _, err := io.ReadFull(os.Stdin, sizeBuf[:]) |
| 26 | if err == io.EOF { |
| 27 | break |
| 28 | } |
| 29 | if err != nil { |
| 30 | log.Fatalf("conformance: read request: %v", err) |
| 31 | } |
| 32 | size := binary.LittleEndian.Uint32(sizeBuf[:]) |
| 33 | if int(size) > cap(inbuf) { |
| 34 | inbuf = make([]byte, size) |
| 35 | } |
| 36 | inbuf = inbuf[:size] |
| 37 | if _, err := io.ReadFull(os.Stdin, inbuf); err != nil { |
| 38 | log.Fatalf("conformance: read request: %v", err) |
| 39 | } |
| 40 | |
| 41 | req := &pb.ConformanceRequest{} |
| 42 | if err := proto.Unmarshal(inbuf, req); err != nil { |
| 43 | log.Fatalf("conformance: parse request: %v", err) |
| 44 | } |
| 45 | res := handle(req) |
| 46 | |
| 47 | out, err := proto.Marshal(res) |
| 48 | if err != nil { |
| 49 | log.Fatalf("conformance: marshal response: %v", err) |
| 50 | } |
| 51 | binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(out))) |
| 52 | if _, err := os.Stdout.Write(sizeBuf[:]); err != nil { |
| 53 | log.Fatalf("conformance: write response: %v", err) |
| 54 | } |
| 55 | if _, err := os.Stdout.Write(out); err != nil { |
| 56 | log.Fatalf("conformance: write response: %v", err) |
| 57 | } |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | func handle(req *pb.ConformanceRequest) *pb.ConformanceResponse { |
| 62 | var err error |
| 63 | var msg proto.Message = &pb.TestAllTypesProto2{} |
| 64 | if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" { |
| 65 | msg = &pb.TestAllTypesProto3{} |
| 66 | } |
| 67 | |
| 68 | switch p := req.Payload.(type) { |
| 69 | case *pb.ConformanceRequest_ProtobufPayload: |
| 70 | err = proto.Unmarshal(p.ProtobufPayload, msg) |
| 71 | case *pb.ConformanceRequest_JsonPayload: |
Damien Neil | 5c5b531 | 2019-05-14 12:44:37 -0700 | [diff] [blame^] | 72 | err = protojson.UnmarshalOptions{ |
Herbie Ong | 4f0be71 | 2019-04-25 17:57:12 -0700 | [diff] [blame] | 73 | DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST, |
| 74 | }.Unmarshal(msg, []byte(p.JsonPayload)) |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 75 | default: |
| 76 | return &pb.ConformanceResponse{ |
| 77 | Result: &pb.ConformanceResponse_RuntimeError{ |
| 78 | RuntimeError: "unknown request payload type", |
| 79 | }, |
| 80 | } |
| 81 | } |
| 82 | if err != nil { |
| 83 | return &pb.ConformanceResponse{ |
| 84 | Result: &pb.ConformanceResponse_ParseError{ |
| 85 | ParseError: err.Error(), |
| 86 | }, |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | switch req.RequestedOutputFormat { |
| 91 | case pb.WireFormat_PROTOBUF: |
| 92 | p, err := proto.Marshal(msg) |
| 93 | if err != nil { |
| 94 | return &pb.ConformanceResponse{ |
| 95 | Result: &pb.ConformanceResponse_SerializeError{ |
| 96 | SerializeError: err.Error(), |
| 97 | }, |
| 98 | } |
| 99 | } |
| 100 | return &pb.ConformanceResponse{ |
| 101 | Result: &pb.ConformanceResponse_ProtobufPayload{ |
| 102 | ProtobufPayload: p, |
| 103 | }, |
| 104 | } |
| 105 | case pb.WireFormat_JSON: |
Damien Neil | 5c5b531 | 2019-05-14 12:44:37 -0700 | [diff] [blame^] | 106 | p, err := protojson.Marshal(msg) |
Herbie Ong | d64dceb | 2019-04-25 01:19:57 -0700 | [diff] [blame] | 107 | if err != nil { |
| 108 | return &pb.ConformanceResponse{ |
| 109 | Result: &pb.ConformanceResponse_SerializeError{ |
| 110 | SerializeError: err.Error(), |
| 111 | }, |
| 112 | } |
| 113 | } |
| 114 | return &pb.ConformanceResponse{ |
| 115 | Result: &pb.ConformanceResponse_JsonPayload{ |
| 116 | JsonPayload: string(p), |
| 117 | }, |
| 118 | } |
| 119 | default: |
| 120 | return &pb.ConformanceResponse{ |
| 121 | Result: &pb.ConformanceResponse_RuntimeError{ |
| 122 | RuntimeError: "unknown output format", |
| 123 | }, |
| 124 | } |
| 125 | } |
| 126 | } |