mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-01 11:58:21 +00:00
6c3ebca21f
This change required some changes to the editions default handling code
because the descriptor.proto changed upstream [2]. The defaults are no
longer one feature set but are split into overridable and
not-overridable features which have to be merged.
I had to do bootstraping in 4 phases but the results should be correct:
1. generate everything depending on descriptor.proto
2. generate new defaults binary proto
3. adjust all code that works with defaults (*/edition.go files)
4. generate everything else
The was required because 1. is a prerequisite for 3. while 2. and 3. are
a prerequisite for 4. (2. and 3. can probably be done in parallel).
The new release also introduced new conformance tests. The go
implementation is not yet conformant and the tests will be fixed in a
follow up change because they require changes to the protojson and
protoext encoders.
[1] e5502c746e
Change-Id: Iddf248f6582a0402ab31256f6e64755d870ed82c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/582635
Auto-Submit: Lasse Folger <lassefolger@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicolas Hillegeer <aktau@google.com>
185 lines
5.1 KiB
Go
185 lines
5.1 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"
|
|
"fmt"
|
|
"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"
|
|
epb "google.golang.org/protobuf/internal/testprotos/conformance/editions"
|
|
empb "google.golang.org/protobuf/internal/testprotos/conformance/editionsmigration"
|
|
)
|
|
|
|
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",
|
|
"--maximum_edition", "2023",
|
|
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{}
|
|
switch req.GetMessageType() {
|
|
case "protobuf_test_messages.proto3.TestAllTypesProto3":
|
|
msg = &pb.TestAllTypesProto3{}
|
|
case "protobuf_test_messages.proto2.TestAllTypesProto2":
|
|
msg = &pb.TestAllTypesProto2{}
|
|
case "protobuf_test_messages.editions.TestAllTypesEdition2023":
|
|
msg = &epb.TestAllTypesEdition2023{}
|
|
case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
|
|
msg = &empb.TestAllTypesProto3{}
|
|
case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
|
|
msg = &empb.TestAllTypesProto2{}
|
|
default:
|
|
panic(fmt.Sprintf("unknown message type: %s", req.GetMessageType()))
|
|
}
|
|
|
|
// 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
|
|
}
|