protobuf-go/internal/conformance/conformance_test.go
Josh Humphries bc1253ad37 types/descriptorpb: regenerate using latest protobuf v22.0 release
This updates all generated code to match the contents of the latest
v22.0 release of Protobuf.

This involved a couple of changes to the script that does the sync'ing:
  1. The new Protobuf version no longer includes autoconf configuration
     and instead requires using bazel to build things.
  2. The new Protobuf release does not have an artifact named
     "protobuf-all-${VERSION}.tar.gz", but the one named
     "protobuf-${VERSION}.tar.gz" has all of the sources and was
     sufficient for the regenerate.bash script to complete.

This change does NOT regenerate the protos related to benchmarks.
The Protobuf repo no longer includes benchmarks. The CL removing them
says they are superceded by google/fleetbench:
    83c499de86
But that project's proto benchmark files are very different:
    https://github.com/google/fleetbench/tree/main/fleetbench/proto
So I commented out those steps in the generation code since the benchmarks
will need some work to reconcile with fleetbench.

This code adds known failing tests for conformance. New test cases were
added in https://github.com/protocolbuffers/protobuf/pull/9534, but the
Go protojson package does not behave according to the new tests. There
is an existing issue in GitHub about this:
    https://github.com/golang/protobuf/issues/1208

Change-Id: Iad796ec7889bc2a74b58db5224facf850cd1a1cd
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/469255
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
2023-02-22 09:33:03 +00:00

170 lines
4.4 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package conformance_test
import (
"encoding/binary"
"flag"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"testing"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
pb "google.golang.org/protobuf/internal/testprotos/conformance"
)
func init() {
// When the environment variable RUN_AS_CONFORMANCE_PLUGIN is set,
// we skip running the tests and instead act as a conformance plugin.
// This allows the binary to pass itself to conformance.
if os.Getenv("RUN_AS_CONFORMANCE_PLUGIN") == "1" {
main()
os.Exit(0)
}
}
var (
execute = flag.Bool("execute", false, "execute the conformance test")
protoRoot = flag.String("protoroot", os.Getenv("PROTOBUF_ROOT"), "The root of the protobuf source tree.")
)
func Test(t *testing.T) {
if !*execute {
t.SkipNow()
}
binPath := filepath.Join(*protoRoot, "bazel-bin", "conformance", "conformance_test_runner")
cmd := exec.Command(binPath,
"--failure_list", "failing_tests.txt",
"--text_format_failure_list", "failing_tests_text_format.txt",
"--enforce_recommended",
os.Args[0])
cmd.Env = append(os.Environ(), "RUN_AS_CONFORMANCE_PLUGIN=1")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("execution error: %v\n\n%s", err, out)
}
}
func main() {
var sizeBuf [4]byte
inbuf := make([]byte, 0, 4096)
for {
_, err := io.ReadFull(os.Stdin, sizeBuf[:])
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("conformance: read request: %v", err)
}
size := binary.LittleEndian.Uint32(sizeBuf[:])
if int(size) > cap(inbuf) {
inbuf = make([]byte, size)
}
inbuf = inbuf[:size]
if _, err := io.ReadFull(os.Stdin, inbuf); err != nil {
log.Fatalf("conformance: read request: %v", err)
}
req := &pb.ConformanceRequest{}
if err := proto.Unmarshal(inbuf, req); err != nil {
log.Fatalf("conformance: parse request: %v", err)
}
res := handle(req)
out, err := proto.Marshal(res)
if err != nil {
log.Fatalf("conformance: marshal response: %v", err)
}
binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(out)))
if _, err := os.Stdout.Write(sizeBuf[:]); err != nil {
log.Fatalf("conformance: write response: %v", err)
}
if _, err := os.Stdout.Write(out); err != nil {
log.Fatalf("conformance: write response: %v", err)
}
}
}
func handle(req *pb.ConformanceRequest) (res *pb.ConformanceResponse) {
var msg proto.Message = &pb.TestAllTypesProto2{}
if req.GetMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3" {
msg = &pb.TestAllTypesProto3{}
}
// Unmarshal the test message.
var err error
switch p := req.Payload.(type) {
case *pb.ConformanceRequest_ProtobufPayload:
err = proto.Unmarshal(p.ProtobufPayload, msg)
case *pb.ConformanceRequest_JsonPayload:
err = protojson.UnmarshalOptions{
DiscardUnknown: req.TestCategory == pb.TestCategory_JSON_IGNORE_UNKNOWN_PARSING_TEST,
}.Unmarshal([]byte(p.JsonPayload), msg)
case *pb.ConformanceRequest_TextPayload:
err = prototext.Unmarshal([]byte(p.TextPayload), msg)
default:
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_RuntimeError{
RuntimeError: "unknown request payload type",
},
}
}
if err != nil {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_ParseError{
ParseError: err.Error(),
},
}
}
// Marshal the test message.
var b []byte
switch req.RequestedOutputFormat {
case pb.WireFormat_PROTOBUF:
b, err = proto.Marshal(msg)
res = &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_ProtobufPayload{
ProtobufPayload: b,
},
}
case pb.WireFormat_JSON:
b, err = protojson.Marshal(msg)
res = &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_JsonPayload{
JsonPayload: string(b),
},
}
case pb.WireFormat_TEXT_FORMAT:
b, err = prototext.MarshalOptions{
EmitUnknown: req.PrintUnknownFields,
}.Marshal(msg)
res = &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_TextPayload{
TextPayload: string(b),
},
}
default:
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_RuntimeError{
RuntimeError: "unknown output format",
},
}
}
if err != nil {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_SerializeError{
SerializeError: err.Error(),
},
}
}
return res
}