build_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2018 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. package filedesc_test
  5. import (
  6. "bytes"
  7. "compress/gzip"
  8. "io/ioutil"
  9. "testing"
  10. "google.golang.org/protobuf/proto"
  11. "google.golang.org/protobuf/reflect/protodesc"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. testpb "google.golang.org/protobuf/internal/testprotos/test"
  14. _ "google.golang.org/protobuf/internal/testprotos/test/weak1"
  15. "google.golang.org/protobuf/types/descriptorpb"
  16. )
  17. func TestInit(t *testing.T) {
  18. // Compare the FileDescriptorProto for the same test file from two different sources:
  19. //
  20. // 1. The result of passing the filedesc-produced FileDescriptor through protodesc.
  21. // 2. The protoc-generated wire-encoded message.
  22. //
  23. // This serves as a test of both filedesc and protodesc.
  24. got := protodesc.ToFileDescriptorProto(testpb.File_test_test_proto)
  25. want := &descriptorpb.FileDescriptorProto{}
  26. zb, _ := (&testpb.TestAllTypes{}).Descriptor()
  27. r, _ := gzip.NewReader(bytes.NewBuffer(zb))
  28. b, _ := ioutil.ReadAll(r)
  29. if err := proto.Unmarshal(b, want); err != nil {
  30. t.Fatal(err)
  31. }
  32. if !proto.Equal(got, want) {
  33. t.Errorf("protodesc.ToFileDescriptorProto(testpb.Test_protoFile) is not equal to the protoc-generated FileDescriptorProto for internal/testprotos/test/test.proto")
  34. }
  35. // Verify that the test proto file provides exhaustive coverage of all descriptor fields.
  36. seen := make(map[protoreflect.FullName]bool)
  37. visitFields(want.ProtoReflect(), func(field protoreflect.FieldDescriptor) {
  38. seen[field.FullName()] = true
  39. })
  40. ignore := map[protoreflect.FullName]bool{
  41. // The protoreflect descriptors don't include source info.
  42. "google.protobuf.FileDescriptorProto.source_code_info": true,
  43. "google.protobuf.FileDescriptorProto.syntax": true,
  44. // TODO: Test oneof and extension options. Testing these requires extending the
  45. // options messages (because they contain no user-settable fields), but importing
  46. // decriptor.proto from test.proto currently causes an import cycle. Add test
  47. // cases when that import cycle has been fixed.
  48. "google.protobuf.OneofDescriptorProto.options": true,
  49. }
  50. for _, messageName := range []protoreflect.Name{
  51. "FileDescriptorProto",
  52. "DescriptorProto",
  53. "FieldDescriptorProto",
  54. "OneofDescriptorProto",
  55. "EnumDescriptorProto",
  56. "EnumValueDescriptorProto",
  57. "ServiceDescriptorProto",
  58. "MethodDescriptorProto",
  59. } {
  60. message := descriptorpb.File_google_protobuf_descriptor_proto.Messages().ByName(messageName)
  61. for i, fields := 0, message.Fields(); i < fields.Len(); i++ {
  62. if name := fields.Get(i).FullName(); !seen[name] && !ignore[name] {
  63. t.Errorf("No test for descriptor field: %v", name)
  64. }
  65. }
  66. }
  67. // Verify that message descriptors for map entries have no Go type info.
  68. mapEntryName := protoreflect.FullName("goproto.proto.test.TestAllTypes.MapInt32Int32Entry")
  69. d := testpb.File_test_test_proto.Messages().ByName("TestAllTypes").Fields().ByName("map_int32_int32").Message()
  70. if gotName, wantName := d.FullName(), mapEntryName; gotName != wantName {
  71. t.Fatalf("looked up wrong descriptor: got %v, want %v", gotName, wantName)
  72. }
  73. if _, ok := d.(protoreflect.MessageType); ok {
  74. t.Errorf("message descriptor for %v must not implement protoreflect.MessageType", mapEntryName)
  75. }
  76. }
  77. // visitFields calls f for every field set in m and its children.
  78. func visitFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor)) {
  79. m.Range(func(fd protoreflect.FieldDescriptor, value protoreflect.Value) bool {
  80. f(fd)
  81. switch fd.Kind() {
  82. case protoreflect.MessageKind, protoreflect.GroupKind:
  83. if fd.IsList() {
  84. for i, list := 0, value.List(); i < list.Len(); i++ {
  85. visitFields(list.Get(i).Message(), f)
  86. }
  87. } else {
  88. visitFields(value.Message(), f)
  89. }
  90. }
  91. return true
  92. })
  93. }
  94. func TestWeakInit(t *testing.T) {
  95. file := testpb.File_test_test_proto
  96. // We do not expect to get a placeholder since weak1 is imported.
  97. fd1 := file.Messages().ByName("TestWeak").Fields().ByName("weak_message1")
  98. if got, want := fd1.IsWeak(), true; got != want {
  99. t.Errorf("field %v: IsWeak() = %v, want %v", fd1.FullName(), got, want)
  100. }
  101. if got, want := fd1.Message().IsPlaceholder(), false; got != want {
  102. t.Errorf("field %v: Message.IsPlaceholder() = %v, want %v", fd1.FullName(), got, want)
  103. }
  104. if got, want := fd1.Message().Fields().Len(), 1; got != want {
  105. t.Errorf("field %v: Message().Fields().Len() == %d, want %d", fd1.FullName(), got, want)
  106. }
  107. // We do expect to get a placeholder since weak2 is not imported.
  108. fd2 := file.Messages().ByName("TestWeak").Fields().ByName("weak_message2")
  109. if got, want := fd2.IsWeak(), true; got != want {
  110. t.Errorf("field %v: IsWeak() = %v, want %v", fd2.FullName(), got, want)
  111. }
  112. if got, want := fd2.Message().IsPlaceholder(), true; got != want {
  113. t.Errorf("field %v: Message.IsPlaceholder() = %v, want %v", fd2.FullName(), got, want)
  114. }
  115. if got, want := fd2.Message().Fields().Len(), 0; got != want {
  116. t.Errorf("field %v: Message().Fields().Len() == %d, want %d", fd2.FullName(), got, want)
  117. }
  118. }