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