main.go 3.2 KB

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