protobuf-go/internal/fileinit/fileinit_test.go
Joe Tsai a95b29fbf6 types: consistently name generated protos
Rename each generated protobuf package such that the base of the
Go package path is always equal to the Go package name to follow
proper Go package naming conventions.

The Go package name is derived from the .proto source file name by
replacing ".proto" with "pb" and stripping all underscores.

Change-Id: Iea05d1b5d94b1b2821ae10276ab771bb2df93c0e
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/177380
Reviewed-by: Damien Neil <dneil@google.com>
2019-05-16 21:55:40 +00:00

117 lines
4.2 KiB
Go

package fileinit_test
import (
"bytes"
"compress/gzip"
"io/ioutil"
"testing"
proto "github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
testpb "google.golang.org/protobuf/internal/testprotos/test"
"google.golang.org/protobuf/types/descriptorpb"
)
func TestInit(t *testing.T) {
// Compare the FileDescriptorProto for the same test file from two different sources:
//
// 1. The result of passing the fileinit-produced FileDescriptor through protodesc.
// 2. The protoc-generated wire-encoded message.
//
// This serves as a test of both fileinit and protodesc.
got := protodesc.ToFileDescriptorProto(testpb.File_test_test_proto)
want := &descriptorpb.FileDescriptorProto{}
zb, _ := (&testpb.TestAllTypes{}).Descriptor()
r, _ := gzip.NewReader(bytes.NewBuffer(zb))
b, _ := ioutil.ReadAll(r)
if err := proto.Unmarshal(b, want); err != nil {
t.Fatal(err)
}
if !proto.Equal(got, want) {
t.Errorf("protodesc.ToFileDescriptorProto(testpb.Test_protoFile) is not equal to the protoc-generated FileDescriptorProto for internal/testprotos/test/test.proto")
}
// Verify that the test proto file provides exhaustive coverage of all descriptor fields.
seen := make(map[protoreflect.FullName]bool)
visitFields(want.ProtoReflect(), func(field protoreflect.FieldDescriptor) {
seen[field.FullName()] = true
})
ignore := map[protoreflect.FullName]bool{
// The protoreflect descriptors don't include source info.
"google.protobuf.FileDescriptorProto.source_code_info": true,
"google.protobuf.FileDescriptorProto.syntax": true,
// TODO: Test oneof and extension options. Testing these requires extending the
// options messages (because they contain no user-settable fields), but importing
// decriptor.proto from test.proto currently causes an import cycle. Add test
// cases when that import cycle has been fixed.
"google.protobuf.OneofDescriptorProto.options": true,
}
for _, messageName := range []protoreflect.Name{
"FileDescriptorProto",
"DescriptorProto",
"FieldDescriptorProto",
"OneofDescriptorProto",
"EnumDescriptorProto",
"EnumValueDescriptorProto",
"ServiceDescriptorProto",
"MethodDescriptorProto",
} {
message := descriptorpb.File_google_protobuf_descriptor_proto.Messages().ByName(messageName)
for i, fields := 0, message.Fields(); i < fields.Len(); i++ {
if name := fields.Get(i).FullName(); !seen[name] && !ignore[name] {
t.Errorf("No test for descriptor field: %v", name)
}
}
}
// Verify that message descriptors for map entries have no Go type info.
mapEntryName := protoreflect.FullName("goproto.proto.test.TestAllTypes.MapInt32Int32Entry")
d := testpb.File_test_test_proto.Messages().ByName("TestAllTypes").Fields().ByName("map_int32_int32").Message()
if gotName, wantName := d.FullName(), mapEntryName; gotName != wantName {
t.Fatalf("looked up wrong descriptor: got %v, want %v", gotName, wantName)
}
if _, ok := d.(protoreflect.MessageType); ok {
t.Errorf("message descriptor for %v must not implement protoreflect.MessageType", mapEntryName)
}
}
// visitFields calls f for every field set in m and its children.
func visitFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor)) {
fieldDescs := m.Descriptor().Fields()
k := m.KnownFields()
k.Range(func(num protoreflect.FieldNumber, value protoreflect.Value) bool {
field := fieldDescs.ByNumber(num)
f(field)
switch field.Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
if field.IsList() {
for i, list := 0, value.List(); i < list.Len(); i++ {
visitFields(list.Get(i).Message(), f)
}
} else {
visitFields(value.Message(), f)
}
}
return true
})
}
func TestWeakInit(t *testing.T) {
file := testpb.File_test_test_proto
fd := file.Messages().ByName("TestWeak").Fields().ByName("weak_message")
if want, got := fd.IsWeak(), true; got != want {
t.Errorf("field %v: IsWeak() = %v, want %v", fd.FullName(), want, got)
}
if want, got := fd.Message().IsPlaceholder(), false; got != want {
t.Errorf("field %v: Message.IsPlaceholder() = %v, want %v", fd.FullName(), want, got)
}
if fd.Message().Fields().Len() == 0 {
t.Errorf("field %v: Message().Fields().Len() == 0, want >0", fd.FullName())
}
}