...

Source file src/google.golang.org/protobuf/internal/conformance/conformance_test.go

Documentation: google.golang.org/protobuf/internal/conformance

     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  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  	// 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, "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  	// Unmarshal the test message.
   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  	// Marshal the test message.
   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