xref: /aosp_15_r20/external/golang-protobuf/reflect/protoregistry/registry_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 protoregistry_test
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"fmt"
9*1c12ee1eSDan Willemsen	"strings"
10*1c12ee1eSDan Willemsen	"testing"
11*1c12ee1eSDan Willemsen
12*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp"
13*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp/cmpopts"
14*1c12ee1eSDan Willemsen
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/prototext"
16*1c12ee1eSDan Willemsen	pimpl "google.golang.org/protobuf/internal/impl"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protodesc"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
20*1c12ee1eSDan Willemsen
21*1c12ee1eSDan Willemsen	testpb "google.golang.org/protobuf/internal/testprotos/registry"
22*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/descriptorpb"
23*1c12ee1eSDan Willemsen)
24*1c12ee1eSDan Willemsen
25*1c12ee1eSDan Willemsenfunc mustMakeFile(s string) protoreflect.FileDescriptor {
26*1c12ee1eSDan Willemsen	pb := new(descriptorpb.FileDescriptorProto)
27*1c12ee1eSDan Willemsen	if err := prototext.Unmarshal([]byte(s), pb); err != nil {
28*1c12ee1eSDan Willemsen		panic(err)
29*1c12ee1eSDan Willemsen	}
30*1c12ee1eSDan Willemsen	fd, err := protodesc.NewFile(pb, nil)
31*1c12ee1eSDan Willemsen	if err != nil {
32*1c12ee1eSDan Willemsen		panic(err)
33*1c12ee1eSDan Willemsen	}
34*1c12ee1eSDan Willemsen	return fd
35*1c12ee1eSDan Willemsen}
36*1c12ee1eSDan Willemsen
37*1c12ee1eSDan Willemsenfunc TestFiles(t *testing.T) {
38*1c12ee1eSDan Willemsen	type (
39*1c12ee1eSDan Willemsen		file struct {
40*1c12ee1eSDan Willemsen			Path string
41*1c12ee1eSDan Willemsen			Pkg  protoreflect.FullName
42*1c12ee1eSDan Willemsen		}
43*1c12ee1eSDan Willemsen		testFile struct {
44*1c12ee1eSDan Willemsen			inFile  protoreflect.FileDescriptor
45*1c12ee1eSDan Willemsen			wantErr string
46*1c12ee1eSDan Willemsen		}
47*1c12ee1eSDan Willemsen		testFindDesc struct {
48*1c12ee1eSDan Willemsen			inName    protoreflect.FullName
49*1c12ee1eSDan Willemsen			wantFound bool
50*1c12ee1eSDan Willemsen		}
51*1c12ee1eSDan Willemsen		testRangePkg struct {
52*1c12ee1eSDan Willemsen			inPkg     protoreflect.FullName
53*1c12ee1eSDan Willemsen			wantFiles []file
54*1c12ee1eSDan Willemsen		}
55*1c12ee1eSDan Willemsen		testFindPath struct {
56*1c12ee1eSDan Willemsen			inPath    string
57*1c12ee1eSDan Willemsen			wantFiles []file
58*1c12ee1eSDan Willemsen			wantErr   string
59*1c12ee1eSDan Willemsen		}
60*1c12ee1eSDan Willemsen	)
61*1c12ee1eSDan Willemsen
62*1c12ee1eSDan Willemsen	tests := []struct {
63*1c12ee1eSDan Willemsen		files     []testFile
64*1c12ee1eSDan Willemsen		findDescs []testFindDesc
65*1c12ee1eSDan Willemsen		rangePkgs []testRangePkg
66*1c12ee1eSDan Willemsen		findPaths []testFindPath
67*1c12ee1eSDan Willemsen	}{{
68*1c12ee1eSDan Willemsen		// Test that overlapping packages and files are permitted.
69*1c12ee1eSDan Willemsen		files: []testFile{
70*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"test1.proto" package:"foo.bar"`)},
71*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"foo/bar/test.proto" package:"my.test"`)},
72*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"foo/bar/test.proto" package:"foo.bar.baz"`), wantErr: "already registered"},
73*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"test2.proto" package:"my.test.package"`)},
74*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"weird" package:"foo.bar"`)},
75*1c12ee1eSDan Willemsen			{inFile: mustMakeFile(`syntax:"proto2" name:"foo/bar/baz/../test.proto" package:"my.test"`)},
76*1c12ee1eSDan Willemsen		},
77*1c12ee1eSDan Willemsen
78*1c12ee1eSDan Willemsen		rangePkgs: []testRangePkg{{
79*1c12ee1eSDan Willemsen			inPkg: "nothing",
80*1c12ee1eSDan Willemsen		}, {
81*1c12ee1eSDan Willemsen			inPkg: "",
82*1c12ee1eSDan Willemsen		}, {
83*1c12ee1eSDan Willemsen			inPkg: ".",
84*1c12ee1eSDan Willemsen		}, {
85*1c12ee1eSDan Willemsen			inPkg: "foo",
86*1c12ee1eSDan Willemsen		}, {
87*1c12ee1eSDan Willemsen			inPkg: "foo.",
88*1c12ee1eSDan Willemsen		}, {
89*1c12ee1eSDan Willemsen			inPkg: "foo..",
90*1c12ee1eSDan Willemsen		}, {
91*1c12ee1eSDan Willemsen			inPkg: "foo.bar",
92*1c12ee1eSDan Willemsen			wantFiles: []file{
93*1c12ee1eSDan Willemsen				{"test1.proto", "foo.bar"},
94*1c12ee1eSDan Willemsen				{"weird", "foo.bar"},
95*1c12ee1eSDan Willemsen			},
96*1c12ee1eSDan Willemsen		}, {
97*1c12ee1eSDan Willemsen			inPkg: "my.test",
98*1c12ee1eSDan Willemsen			wantFiles: []file{
99*1c12ee1eSDan Willemsen				{"foo/bar/baz/../test.proto", "my.test"},
100*1c12ee1eSDan Willemsen				{"foo/bar/test.proto", "my.test"},
101*1c12ee1eSDan Willemsen			},
102*1c12ee1eSDan Willemsen		}, {
103*1c12ee1eSDan Willemsen			inPkg: "fo",
104*1c12ee1eSDan Willemsen		}},
105*1c12ee1eSDan Willemsen
106*1c12ee1eSDan Willemsen		findPaths: []testFindPath{{
107*1c12ee1eSDan Willemsen			inPath:  "nothing",
108*1c12ee1eSDan Willemsen			wantErr: "not found",
109*1c12ee1eSDan Willemsen		}, {
110*1c12ee1eSDan Willemsen			inPath: "weird",
111*1c12ee1eSDan Willemsen			wantFiles: []file{
112*1c12ee1eSDan Willemsen				{"weird", "foo.bar"},
113*1c12ee1eSDan Willemsen			},
114*1c12ee1eSDan Willemsen		}, {
115*1c12ee1eSDan Willemsen			inPath: "foo/bar/test.proto",
116*1c12ee1eSDan Willemsen			wantFiles: []file{
117*1c12ee1eSDan Willemsen				{"foo/bar/test.proto", "my.test"},
118*1c12ee1eSDan Willemsen			},
119*1c12ee1eSDan Willemsen		}},
120*1c12ee1eSDan Willemsen	}, {
121*1c12ee1eSDan Willemsen		// Test when new enum conflicts with existing package.
122*1c12ee1eSDan Willemsen		files: []testFile{{
123*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`syntax:"proto2" name:"test1a.proto" package:"foo.bar.baz"`),
124*1c12ee1eSDan Willemsen		}, {
125*1c12ee1eSDan Willemsen			inFile:  mustMakeFile(`syntax:"proto2" name:"test1b.proto" enum_type:[{name:"foo" value:[{name:"VALUE" number:0}]}]`),
126*1c12ee1eSDan Willemsen			wantErr: `file "test1b.proto" has a name conflict over foo`,
127*1c12ee1eSDan Willemsen		}},
128*1c12ee1eSDan Willemsen	}, {
129*1c12ee1eSDan Willemsen		// Test when new package conflicts with existing enum.
130*1c12ee1eSDan Willemsen		files: []testFile{{
131*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`syntax:"proto2" name:"test2a.proto" enum_type:[{name:"foo" value:[{name:"VALUE" number:0}]}]`),
132*1c12ee1eSDan Willemsen		}, {
133*1c12ee1eSDan Willemsen			inFile:  mustMakeFile(`syntax:"proto2" name:"test2b.proto" package:"foo.bar.baz"`),
134*1c12ee1eSDan Willemsen			wantErr: `file "test2b.proto" has a package name conflict over foo`,
135*1c12ee1eSDan Willemsen		}},
136*1c12ee1eSDan Willemsen	}, {
137*1c12ee1eSDan Willemsen		// Test when new enum conflicts with existing enum in same package.
138*1c12ee1eSDan Willemsen		files: []testFile{{
139*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`syntax:"proto2" name:"test3a.proto" package:"foo" enum_type:[{name:"BAR" value:[{name:"VALUE" number:0}]}]`),
140*1c12ee1eSDan Willemsen		}, {
141*1c12ee1eSDan Willemsen			inFile:  mustMakeFile(`syntax:"proto2" name:"test3b.proto" package:"foo" enum_type:[{name:"BAR" value:[{name:"VALUE2" number:0}]}]`),
142*1c12ee1eSDan Willemsen			wantErr: `file "test3b.proto" has a name conflict over foo.BAR`,
143*1c12ee1eSDan Willemsen		}},
144*1c12ee1eSDan Willemsen	}, {
145*1c12ee1eSDan Willemsen		files: []testFile{{
146*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`
147*1c12ee1eSDan Willemsen				syntax:  "proto2"
148*1c12ee1eSDan Willemsen				name:    "test1.proto"
149*1c12ee1eSDan Willemsen				package: "fizz.buzz"
150*1c12ee1eSDan Willemsen				message_type: [{
151*1c12ee1eSDan Willemsen					name: "Message"
152*1c12ee1eSDan Willemsen					field: [
153*1c12ee1eSDan Willemsen						{name:"Field" number:1 label:LABEL_OPTIONAL type:TYPE_STRING oneof_index:0}
154*1c12ee1eSDan Willemsen					]
155*1c12ee1eSDan Willemsen					oneof_decl:      [{name:"Oneof"}]
156*1c12ee1eSDan Willemsen					extension_range: [{start:1000 end:2000}]
157*1c12ee1eSDan Willemsen
158*1c12ee1eSDan Willemsen					enum_type: [
159*1c12ee1eSDan Willemsen						{name:"Enum" value:[{name:"EnumValue" number:0}]}
160*1c12ee1eSDan Willemsen					]
161*1c12ee1eSDan Willemsen					nested_type: [
162*1c12ee1eSDan Willemsen						{name:"Message" field:[{name:"Field" number:1 label:LABEL_OPTIONAL type:TYPE_STRING}]}
163*1c12ee1eSDan Willemsen					]
164*1c12ee1eSDan Willemsen					extension: [
165*1c12ee1eSDan Willemsen						{name:"Extension" number:1001 label:LABEL_OPTIONAL type:TYPE_STRING extendee:".fizz.buzz.Message"}
166*1c12ee1eSDan Willemsen					]
167*1c12ee1eSDan Willemsen				}]
168*1c12ee1eSDan Willemsen				enum_type: [{
169*1c12ee1eSDan Willemsen					name:  "Enum"
170*1c12ee1eSDan Willemsen					value: [{name:"EnumValue" number:0}]
171*1c12ee1eSDan Willemsen				}]
172*1c12ee1eSDan Willemsen				extension: [
173*1c12ee1eSDan Willemsen					{name:"Extension" number:1000 label:LABEL_OPTIONAL type:TYPE_STRING extendee:".fizz.buzz.Message"}
174*1c12ee1eSDan Willemsen				]
175*1c12ee1eSDan Willemsen				service: [{
176*1c12ee1eSDan Willemsen					name: "Service"
177*1c12ee1eSDan Willemsen					method: [{
178*1c12ee1eSDan Willemsen						name:             "Method"
179*1c12ee1eSDan Willemsen						input_type:       ".fizz.buzz.Message"
180*1c12ee1eSDan Willemsen						output_type:      ".fizz.buzz.Message"
181*1c12ee1eSDan Willemsen						client_streaming: true
182*1c12ee1eSDan Willemsen						server_streaming: true
183*1c12ee1eSDan Willemsen					}]
184*1c12ee1eSDan Willemsen				}]
185*1c12ee1eSDan Willemsen			`),
186*1c12ee1eSDan Willemsen		}, {
187*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`
188*1c12ee1eSDan Willemsen				syntax:  "proto2"
189*1c12ee1eSDan Willemsen				name:    "test2.proto"
190*1c12ee1eSDan Willemsen				package: "fizz.buzz.gazz"
191*1c12ee1eSDan Willemsen				enum_type: [{
192*1c12ee1eSDan Willemsen					name:  "Enum"
193*1c12ee1eSDan Willemsen					value: [{name:"EnumValue" number:0}]
194*1c12ee1eSDan Willemsen				}]
195*1c12ee1eSDan Willemsen			`),
196*1c12ee1eSDan Willemsen		}, {
197*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`
198*1c12ee1eSDan Willemsen				syntax:  "proto2"
199*1c12ee1eSDan Willemsen				name:    "test3.proto"
200*1c12ee1eSDan Willemsen				package: "fizz.buzz"
201*1c12ee1eSDan Willemsen				enum_type: [{
202*1c12ee1eSDan Willemsen					name:  "Enum1"
203*1c12ee1eSDan Willemsen					value: [{name:"EnumValue1" number:0}]
204*1c12ee1eSDan Willemsen				}, {
205*1c12ee1eSDan Willemsen					name:  "Enum2"
206*1c12ee1eSDan Willemsen					value: [{name:"EnumValue2" number:0}]
207*1c12ee1eSDan Willemsen				}]
208*1c12ee1eSDan Willemsen			`),
209*1c12ee1eSDan Willemsen		}, {
210*1c12ee1eSDan Willemsen			// Make sure we can register without package name.
211*1c12ee1eSDan Willemsen			inFile: mustMakeFile(`
212*1c12ee1eSDan Willemsen				name:   "weird"
213*1c12ee1eSDan Willemsen				syntax: "proto2"
214*1c12ee1eSDan Willemsen				message_type: [{
215*1c12ee1eSDan Willemsen					name: "Message"
216*1c12ee1eSDan Willemsen					nested_type: [{
217*1c12ee1eSDan Willemsen						name: "Message"
218*1c12ee1eSDan Willemsen						nested_type: [{
219*1c12ee1eSDan Willemsen							name: "Message"
220*1c12ee1eSDan Willemsen						}]
221*1c12ee1eSDan Willemsen					}]
222*1c12ee1eSDan Willemsen				}]
223*1c12ee1eSDan Willemsen			`),
224*1c12ee1eSDan Willemsen		}},
225*1c12ee1eSDan Willemsen		findDescs: []testFindDesc{
226*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.message", wantFound: false},
227*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message", wantFound: true},
228*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.X", wantFound: false},
229*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Field", wantFound: false},
230*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Oneof", wantFound: false},
231*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Field", wantFound: true},
232*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Field.X", wantFound: false},
233*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Oneof", wantFound: true},
234*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Oneof.X", wantFound: false},
235*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Message", wantFound: true},
236*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Message.X", wantFound: false},
237*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Enum", wantFound: true},
238*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Enum.X", wantFound: false},
239*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.EnumValue", wantFound: true},
240*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.EnumValue.X", wantFound: false},
241*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Extension", wantFound: true},
242*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Message.Extension.X", wantFound: false},
243*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.enum", wantFound: false},
244*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum", wantFound: true},
245*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum.X", wantFound: false},
246*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.EnumValue", wantFound: true},
247*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.EnumValue.X", wantFound: false},
248*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum.EnumValue", wantFound: false},
249*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Extension", wantFound: true},
250*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Extension.X", wantFound: false},
251*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.service", wantFound: false},
252*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Service", wantFound: true},
253*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Service.X", wantFound: false},
254*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Method", wantFound: false},
255*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Service.Method", wantFound: true},
256*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Service.Method.X", wantFound: false},
257*1c12ee1eSDan Willemsen
258*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.gazz", wantFound: false},
259*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.gazz.Enum", wantFound: true},
260*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.gazz.EnumValue", wantFound: true},
261*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.gazz.Enum.EnumValue", wantFound: false},
262*1c12ee1eSDan Willemsen
263*1c12ee1eSDan Willemsen			{inName: "fizz.buzz", wantFound: false},
264*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum1", wantFound: true},
265*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.EnumValue1", wantFound: true},
266*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum1.EnumValue1", wantFound: false},
267*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum2", wantFound: true},
268*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.EnumValue2", wantFound: true},
269*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum2.EnumValue2", wantFound: false},
270*1c12ee1eSDan Willemsen			{inName: "fizz.buzz.Enum3", wantFound: false},
271*1c12ee1eSDan Willemsen
272*1c12ee1eSDan Willemsen			{inName: "", wantFound: false},
273*1c12ee1eSDan Willemsen			{inName: "Message", wantFound: true},
274*1c12ee1eSDan Willemsen			{inName: "Message.Message", wantFound: true},
275*1c12ee1eSDan Willemsen			{inName: "Message.Message.Message", wantFound: true},
276*1c12ee1eSDan Willemsen			{inName: "Message.Message.Message.Message", wantFound: false},
277*1c12ee1eSDan Willemsen		},
278*1c12ee1eSDan Willemsen	}}
279*1c12ee1eSDan Willemsen
280*1c12ee1eSDan Willemsen	sortFiles := cmpopts.SortSlices(func(x, y file) bool {
281*1c12ee1eSDan Willemsen		return x.Path < y.Path || (x.Path == y.Path && x.Pkg < y.Pkg)
282*1c12ee1eSDan Willemsen	})
283*1c12ee1eSDan Willemsen	for _, tt := range tests {
284*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
285*1c12ee1eSDan Willemsen			var files protoregistry.Files
286*1c12ee1eSDan Willemsen			for i, tc := range tt.files {
287*1c12ee1eSDan Willemsen				gotErr := files.RegisterFile(tc.inFile)
288*1c12ee1eSDan Willemsen				if ((gotErr == nil) != (tc.wantErr == "")) || !strings.Contains(fmt.Sprint(gotErr), tc.wantErr) {
289*1c12ee1eSDan Willemsen					t.Errorf("file %d, Register() = %v, want %v", i, gotErr, tc.wantErr)
290*1c12ee1eSDan Willemsen				}
291*1c12ee1eSDan Willemsen			}
292*1c12ee1eSDan Willemsen
293*1c12ee1eSDan Willemsen			for _, tc := range tt.findDescs {
294*1c12ee1eSDan Willemsen				d, _ := files.FindDescriptorByName(tc.inName)
295*1c12ee1eSDan Willemsen				gotFound := d != nil
296*1c12ee1eSDan Willemsen				if gotFound != tc.wantFound {
297*1c12ee1eSDan Willemsen					t.Errorf("FindDescriptorByName(%v) find mismatch: got %v, want %v", tc.inName, gotFound, tc.wantFound)
298*1c12ee1eSDan Willemsen				}
299*1c12ee1eSDan Willemsen			}
300*1c12ee1eSDan Willemsen
301*1c12ee1eSDan Willemsen			for _, tc := range tt.rangePkgs {
302*1c12ee1eSDan Willemsen				var gotFiles []file
303*1c12ee1eSDan Willemsen				var gotCnt int
304*1c12ee1eSDan Willemsen				wantCnt := files.NumFilesByPackage(tc.inPkg)
305*1c12ee1eSDan Willemsen				files.RangeFilesByPackage(tc.inPkg, func(fd protoreflect.FileDescriptor) bool {
306*1c12ee1eSDan Willemsen					gotFiles = append(gotFiles, file{fd.Path(), fd.Package()})
307*1c12ee1eSDan Willemsen					gotCnt++
308*1c12ee1eSDan Willemsen					return true
309*1c12ee1eSDan Willemsen				})
310*1c12ee1eSDan Willemsen				if gotCnt != wantCnt {
311*1c12ee1eSDan Willemsen					t.Errorf("NumFilesByPackage(%v) = %v, want %v", tc.inPkg, gotCnt, wantCnt)
312*1c12ee1eSDan Willemsen				}
313*1c12ee1eSDan Willemsen				if diff := cmp.Diff(tc.wantFiles, gotFiles, sortFiles); diff != "" {
314*1c12ee1eSDan Willemsen					t.Errorf("RangeFilesByPackage(%v) mismatch (-want +got):\n%v", tc.inPkg, diff)
315*1c12ee1eSDan Willemsen				}
316*1c12ee1eSDan Willemsen			}
317*1c12ee1eSDan Willemsen
318*1c12ee1eSDan Willemsen			for _, tc := range tt.findPaths {
319*1c12ee1eSDan Willemsen				var gotFiles []file
320*1c12ee1eSDan Willemsen				fd, gotErr := files.FindFileByPath(tc.inPath)
321*1c12ee1eSDan Willemsen				if gotErr == nil {
322*1c12ee1eSDan Willemsen					gotFiles = append(gotFiles, file{fd.Path(), fd.Package()})
323*1c12ee1eSDan Willemsen				}
324*1c12ee1eSDan Willemsen				if ((gotErr == nil) != (tc.wantErr == "")) || !strings.Contains(fmt.Sprint(gotErr), tc.wantErr) {
325*1c12ee1eSDan Willemsen					t.Errorf("FindFileByPath(%v) = %v, want %v", tc.inPath, gotErr, tc.wantErr)
326*1c12ee1eSDan Willemsen				}
327*1c12ee1eSDan Willemsen				if diff := cmp.Diff(tc.wantFiles, gotFiles, sortFiles); diff != "" {
328*1c12ee1eSDan Willemsen					t.Errorf("FindFileByPath(%v) mismatch (-want +got):\n%v", tc.inPath, diff)
329*1c12ee1eSDan Willemsen				}
330*1c12ee1eSDan Willemsen			}
331*1c12ee1eSDan Willemsen		})
332*1c12ee1eSDan Willemsen	}
333*1c12ee1eSDan Willemsen}
334*1c12ee1eSDan Willemsen
335*1c12ee1eSDan Willemsenfunc TestTypes(t *testing.T) {
336*1c12ee1eSDan Willemsen	mt1 := pimpl.Export{}.MessageTypeOf(&testpb.Message1{})
337*1c12ee1eSDan Willemsen	et1 := pimpl.Export{}.EnumTypeOf(testpb.Enum1_ONE)
338*1c12ee1eSDan Willemsen	xt1 := testpb.E_StringField
339*1c12ee1eSDan Willemsen	xt2 := testpb.E_Message4_MessageField
340*1c12ee1eSDan Willemsen	registry := new(protoregistry.Types)
341*1c12ee1eSDan Willemsen	if err := registry.RegisterMessage(mt1); err != nil {
342*1c12ee1eSDan Willemsen		t.Fatalf("registry.RegisterMessage(%v) returns unexpected error: %v", mt1.Descriptor().FullName(), err)
343*1c12ee1eSDan Willemsen	}
344*1c12ee1eSDan Willemsen	if err := registry.RegisterEnum(et1); err != nil {
345*1c12ee1eSDan Willemsen		t.Fatalf("registry.RegisterEnum(%v) returns unexpected error: %v", et1.Descriptor().FullName(), err)
346*1c12ee1eSDan Willemsen	}
347*1c12ee1eSDan Willemsen	if err := registry.RegisterExtension(xt1); err != nil {
348*1c12ee1eSDan Willemsen		t.Fatalf("registry.RegisterExtension(%v) returns unexpected error: %v", xt1.TypeDescriptor().FullName(), err)
349*1c12ee1eSDan Willemsen	}
350*1c12ee1eSDan Willemsen	if err := registry.RegisterExtension(xt2); err != nil {
351*1c12ee1eSDan Willemsen		t.Fatalf("registry.RegisterExtension(%v) returns unexpected error: %v", xt2.TypeDescriptor().FullName(), err)
352*1c12ee1eSDan Willemsen	}
353*1c12ee1eSDan Willemsen
354*1c12ee1eSDan Willemsen	t.Run("FindMessageByName", func(t *testing.T) {
355*1c12ee1eSDan Willemsen		tests := []struct {
356*1c12ee1eSDan Willemsen			name         string
357*1c12ee1eSDan Willemsen			messageType  protoreflect.MessageType
358*1c12ee1eSDan Willemsen			wantErr      bool
359*1c12ee1eSDan Willemsen			wantNotFound bool
360*1c12ee1eSDan Willemsen		}{{
361*1c12ee1eSDan Willemsen			name:        "testprotos.Message1",
362*1c12ee1eSDan Willemsen			messageType: mt1,
363*1c12ee1eSDan Willemsen		}, {
364*1c12ee1eSDan Willemsen			name:         "testprotos.NoSuchMessage",
365*1c12ee1eSDan Willemsen			wantErr:      true,
366*1c12ee1eSDan Willemsen			wantNotFound: true,
367*1c12ee1eSDan Willemsen		}, {
368*1c12ee1eSDan Willemsen			name:    "testprotos.Enum1",
369*1c12ee1eSDan Willemsen			wantErr: true,
370*1c12ee1eSDan Willemsen		}, {
371*1c12ee1eSDan Willemsen			name:    "testprotos.Enum2",
372*1c12ee1eSDan Willemsen			wantErr: true,
373*1c12ee1eSDan Willemsen		}, {
374*1c12ee1eSDan Willemsen			name:    "testprotos.Enum3",
375*1c12ee1eSDan Willemsen			wantErr: true,
376*1c12ee1eSDan Willemsen		}}
377*1c12ee1eSDan Willemsen		for _, tc := range tests {
378*1c12ee1eSDan Willemsen			got, err := registry.FindMessageByName(protoreflect.FullName(tc.name))
379*1c12ee1eSDan Willemsen			gotErr := err != nil
380*1c12ee1eSDan Willemsen			if gotErr != tc.wantErr {
381*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
382*1c12ee1eSDan Willemsen				continue
383*1c12ee1eSDan Willemsen			}
384*1c12ee1eSDan Willemsen			if tc.wantNotFound && err != protoregistry.NotFound {
385*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByName(%v) got error: %v, want NotFound error", tc.name, err)
386*1c12ee1eSDan Willemsen				continue
387*1c12ee1eSDan Willemsen			}
388*1c12ee1eSDan Willemsen			if got != tc.messageType {
389*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByName(%v) got wrong value: %v", tc.name, got)
390*1c12ee1eSDan Willemsen			}
391*1c12ee1eSDan Willemsen		}
392*1c12ee1eSDan Willemsen	})
393*1c12ee1eSDan Willemsen
394*1c12ee1eSDan Willemsen	t.Run("FindMessageByURL", func(t *testing.T) {
395*1c12ee1eSDan Willemsen		tests := []struct {
396*1c12ee1eSDan Willemsen			name         string
397*1c12ee1eSDan Willemsen			messageType  protoreflect.MessageType
398*1c12ee1eSDan Willemsen			wantErr      bool
399*1c12ee1eSDan Willemsen			wantNotFound bool
400*1c12ee1eSDan Willemsen		}{{
401*1c12ee1eSDan Willemsen			name:        "testprotos.Message1",
402*1c12ee1eSDan Willemsen			messageType: mt1,
403*1c12ee1eSDan Willemsen		}, {
404*1c12ee1eSDan Willemsen			name:         "type.googleapis.com/testprotos.Nada",
405*1c12ee1eSDan Willemsen			wantErr:      true,
406*1c12ee1eSDan Willemsen			wantNotFound: true,
407*1c12ee1eSDan Willemsen		}, {
408*1c12ee1eSDan Willemsen			name:    "testprotos.Enum1",
409*1c12ee1eSDan Willemsen			wantErr: true,
410*1c12ee1eSDan Willemsen		}}
411*1c12ee1eSDan Willemsen		for _, tc := range tests {
412*1c12ee1eSDan Willemsen			got, err := registry.FindMessageByURL(tc.name)
413*1c12ee1eSDan Willemsen			gotErr := err != nil
414*1c12ee1eSDan Willemsen			if gotErr != tc.wantErr {
415*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByURL(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
416*1c12ee1eSDan Willemsen				continue
417*1c12ee1eSDan Willemsen			}
418*1c12ee1eSDan Willemsen			if tc.wantNotFound && err != protoregistry.NotFound {
419*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByURL(%v) got error: %v, want NotFound error", tc.name, err)
420*1c12ee1eSDan Willemsen				continue
421*1c12ee1eSDan Willemsen			}
422*1c12ee1eSDan Willemsen			if got != tc.messageType {
423*1c12ee1eSDan Willemsen				t.Errorf("FindMessageByURL(%v) got wrong value: %v", tc.name, got)
424*1c12ee1eSDan Willemsen			}
425*1c12ee1eSDan Willemsen		}
426*1c12ee1eSDan Willemsen	})
427*1c12ee1eSDan Willemsen
428*1c12ee1eSDan Willemsen	t.Run("FindEnumByName", func(t *testing.T) {
429*1c12ee1eSDan Willemsen		tests := []struct {
430*1c12ee1eSDan Willemsen			name         string
431*1c12ee1eSDan Willemsen			enumType     protoreflect.EnumType
432*1c12ee1eSDan Willemsen			wantErr      bool
433*1c12ee1eSDan Willemsen			wantNotFound bool
434*1c12ee1eSDan Willemsen		}{{
435*1c12ee1eSDan Willemsen			name:     "testprotos.Enum1",
436*1c12ee1eSDan Willemsen			enumType: et1,
437*1c12ee1eSDan Willemsen		}, {
438*1c12ee1eSDan Willemsen			name:         "testprotos.None",
439*1c12ee1eSDan Willemsen			wantErr:      true,
440*1c12ee1eSDan Willemsen			wantNotFound: true,
441*1c12ee1eSDan Willemsen		}, {
442*1c12ee1eSDan Willemsen			name:    "testprotos.Message1",
443*1c12ee1eSDan Willemsen			wantErr: true,
444*1c12ee1eSDan Willemsen		}}
445*1c12ee1eSDan Willemsen		for _, tc := range tests {
446*1c12ee1eSDan Willemsen			got, err := registry.FindEnumByName(protoreflect.FullName(tc.name))
447*1c12ee1eSDan Willemsen			gotErr := err != nil
448*1c12ee1eSDan Willemsen			if gotErr != tc.wantErr {
449*1c12ee1eSDan Willemsen				t.Errorf("FindEnumByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
450*1c12ee1eSDan Willemsen				continue
451*1c12ee1eSDan Willemsen			}
452*1c12ee1eSDan Willemsen			if tc.wantNotFound && err != protoregistry.NotFound {
453*1c12ee1eSDan Willemsen				t.Errorf("FindEnumByName(%v) got error: %v, want NotFound error", tc.name, err)
454*1c12ee1eSDan Willemsen				continue
455*1c12ee1eSDan Willemsen			}
456*1c12ee1eSDan Willemsen			if got != tc.enumType {
457*1c12ee1eSDan Willemsen				t.Errorf("FindEnumByName(%v) got wrong value: %v", tc.name, got)
458*1c12ee1eSDan Willemsen			}
459*1c12ee1eSDan Willemsen		}
460*1c12ee1eSDan Willemsen	})
461*1c12ee1eSDan Willemsen
462*1c12ee1eSDan Willemsen	t.Run("FindExtensionByName", func(t *testing.T) {
463*1c12ee1eSDan Willemsen		tests := []struct {
464*1c12ee1eSDan Willemsen			name          string
465*1c12ee1eSDan Willemsen			extensionType protoreflect.ExtensionType
466*1c12ee1eSDan Willemsen			wantErr       bool
467*1c12ee1eSDan Willemsen			wantNotFound  bool
468*1c12ee1eSDan Willemsen		}{{
469*1c12ee1eSDan Willemsen			name:          "testprotos.string_field",
470*1c12ee1eSDan Willemsen			extensionType: xt1,
471*1c12ee1eSDan Willemsen		}, {
472*1c12ee1eSDan Willemsen			name:          "testprotos.Message4.message_field",
473*1c12ee1eSDan Willemsen			extensionType: xt2,
474*1c12ee1eSDan Willemsen		}, {
475*1c12ee1eSDan Willemsen			name:         "testprotos.None",
476*1c12ee1eSDan Willemsen			wantErr:      true,
477*1c12ee1eSDan Willemsen			wantNotFound: true,
478*1c12ee1eSDan Willemsen		}, {
479*1c12ee1eSDan Willemsen			name:    "testprotos.Message1",
480*1c12ee1eSDan Willemsen			wantErr: true,
481*1c12ee1eSDan Willemsen		}}
482*1c12ee1eSDan Willemsen		for _, tc := range tests {
483*1c12ee1eSDan Willemsen			got, err := registry.FindExtensionByName(protoreflect.FullName(tc.name))
484*1c12ee1eSDan Willemsen			gotErr := err != nil
485*1c12ee1eSDan Willemsen			if gotErr != tc.wantErr {
486*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByName(%v) = (_, %v), want error? %t", tc.name, err, tc.wantErr)
487*1c12ee1eSDan Willemsen				continue
488*1c12ee1eSDan Willemsen			}
489*1c12ee1eSDan Willemsen			if tc.wantNotFound && err != protoregistry.NotFound {
490*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByName(%v) got error: %v, want NotFound error", tc.name, err)
491*1c12ee1eSDan Willemsen				continue
492*1c12ee1eSDan Willemsen			}
493*1c12ee1eSDan Willemsen			if got != tc.extensionType {
494*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByName(%v) got wrong value: %v", tc.name, got)
495*1c12ee1eSDan Willemsen			}
496*1c12ee1eSDan Willemsen		}
497*1c12ee1eSDan Willemsen	})
498*1c12ee1eSDan Willemsen
499*1c12ee1eSDan Willemsen	t.Run("FindExtensionByNumber", func(t *testing.T) {
500*1c12ee1eSDan Willemsen		tests := []struct {
501*1c12ee1eSDan Willemsen			parent        string
502*1c12ee1eSDan Willemsen			number        int32
503*1c12ee1eSDan Willemsen			extensionType protoreflect.ExtensionType
504*1c12ee1eSDan Willemsen			wantErr       bool
505*1c12ee1eSDan Willemsen			wantNotFound  bool
506*1c12ee1eSDan Willemsen		}{{
507*1c12ee1eSDan Willemsen			parent:        "testprotos.Message1",
508*1c12ee1eSDan Willemsen			number:        11,
509*1c12ee1eSDan Willemsen			extensionType: xt1,
510*1c12ee1eSDan Willemsen		}, {
511*1c12ee1eSDan Willemsen			parent:       "testprotos.Message1",
512*1c12ee1eSDan Willemsen			number:       13,
513*1c12ee1eSDan Willemsen			wantErr:      true,
514*1c12ee1eSDan Willemsen			wantNotFound: true,
515*1c12ee1eSDan Willemsen		}, {
516*1c12ee1eSDan Willemsen			parent:        "testprotos.Message1",
517*1c12ee1eSDan Willemsen			number:        21,
518*1c12ee1eSDan Willemsen			extensionType: xt2,
519*1c12ee1eSDan Willemsen		}, {
520*1c12ee1eSDan Willemsen			parent:       "testprotos.Message1",
521*1c12ee1eSDan Willemsen			number:       23,
522*1c12ee1eSDan Willemsen			wantErr:      true,
523*1c12ee1eSDan Willemsen			wantNotFound: true,
524*1c12ee1eSDan Willemsen		}, {
525*1c12ee1eSDan Willemsen			parent:       "testprotos.NoSuchMessage",
526*1c12ee1eSDan Willemsen			number:       11,
527*1c12ee1eSDan Willemsen			wantErr:      true,
528*1c12ee1eSDan Willemsen			wantNotFound: true,
529*1c12ee1eSDan Willemsen		}, {
530*1c12ee1eSDan Willemsen			parent:       "testprotos.Message1",
531*1c12ee1eSDan Willemsen			number:       30,
532*1c12ee1eSDan Willemsen			wantErr:      true,
533*1c12ee1eSDan Willemsen			wantNotFound: true,
534*1c12ee1eSDan Willemsen		}, {
535*1c12ee1eSDan Willemsen			parent:       "testprotos.Message1",
536*1c12ee1eSDan Willemsen			number:       99,
537*1c12ee1eSDan Willemsen			wantErr:      true,
538*1c12ee1eSDan Willemsen			wantNotFound: true,
539*1c12ee1eSDan Willemsen		}}
540*1c12ee1eSDan Willemsen		for _, tc := range tests {
541*1c12ee1eSDan Willemsen			got, err := registry.FindExtensionByNumber(protoreflect.FullName(tc.parent), protoreflect.FieldNumber(tc.number))
542*1c12ee1eSDan Willemsen			gotErr := err != nil
543*1c12ee1eSDan Willemsen			if gotErr != tc.wantErr {
544*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByNumber(%v, %d) = (_, %v), want error? %t", tc.parent, tc.number, err, tc.wantErr)
545*1c12ee1eSDan Willemsen				continue
546*1c12ee1eSDan Willemsen			}
547*1c12ee1eSDan Willemsen			if tc.wantNotFound && err != protoregistry.NotFound {
548*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByNumber(%v, %d) got error %v, want NotFound error", tc.parent, tc.number, err)
549*1c12ee1eSDan Willemsen				continue
550*1c12ee1eSDan Willemsen			}
551*1c12ee1eSDan Willemsen			if got != tc.extensionType {
552*1c12ee1eSDan Willemsen				t.Errorf("FindExtensionByNumber(%v, %d) got wrong value: %v", tc.parent, tc.number, got)
553*1c12ee1eSDan Willemsen			}
554*1c12ee1eSDan Willemsen		}
555*1c12ee1eSDan Willemsen	})
556*1c12ee1eSDan Willemsen
557*1c12ee1eSDan Willemsen	sortTypes := cmp.Options{
558*1c12ee1eSDan Willemsen		cmpopts.SortSlices(func(x, y protoreflect.EnumType) bool {
559*1c12ee1eSDan Willemsen			return x.Descriptor().FullName() < y.Descriptor().FullName()
560*1c12ee1eSDan Willemsen		}),
561*1c12ee1eSDan Willemsen		cmpopts.SortSlices(func(x, y protoreflect.MessageType) bool {
562*1c12ee1eSDan Willemsen			return x.Descriptor().FullName() < y.Descriptor().FullName()
563*1c12ee1eSDan Willemsen		}),
564*1c12ee1eSDan Willemsen		cmpopts.SortSlices(func(x, y protoreflect.ExtensionType) bool {
565*1c12ee1eSDan Willemsen			return x.TypeDescriptor().FullName() < y.TypeDescriptor().FullName()
566*1c12ee1eSDan Willemsen		}),
567*1c12ee1eSDan Willemsen	}
568*1c12ee1eSDan Willemsen	compare := cmp.Options{
569*1c12ee1eSDan Willemsen		cmp.Comparer(func(x, y protoreflect.EnumType) bool {
570*1c12ee1eSDan Willemsen			return x == y
571*1c12ee1eSDan Willemsen		}),
572*1c12ee1eSDan Willemsen		cmp.Comparer(func(x, y protoreflect.ExtensionType) bool {
573*1c12ee1eSDan Willemsen			return x == y
574*1c12ee1eSDan Willemsen		}),
575*1c12ee1eSDan Willemsen		cmp.Comparer(func(x, y protoreflect.MessageType) bool {
576*1c12ee1eSDan Willemsen			return x == y
577*1c12ee1eSDan Willemsen		}),
578*1c12ee1eSDan Willemsen	}
579*1c12ee1eSDan Willemsen
580*1c12ee1eSDan Willemsen	t.Run("RangeEnums", func(t *testing.T) {
581*1c12ee1eSDan Willemsen		want := []protoreflect.EnumType{et1}
582*1c12ee1eSDan Willemsen		var got []protoreflect.EnumType
583*1c12ee1eSDan Willemsen		var gotCnt int
584*1c12ee1eSDan Willemsen		wantCnt := registry.NumEnums()
585*1c12ee1eSDan Willemsen		registry.RangeEnums(func(et protoreflect.EnumType) bool {
586*1c12ee1eSDan Willemsen			got = append(got, et)
587*1c12ee1eSDan Willemsen			gotCnt++
588*1c12ee1eSDan Willemsen			return true
589*1c12ee1eSDan Willemsen		})
590*1c12ee1eSDan Willemsen
591*1c12ee1eSDan Willemsen		if gotCnt != wantCnt {
592*1c12ee1eSDan Willemsen			t.Errorf("NumEnums() = %v, want %v", gotCnt, wantCnt)
593*1c12ee1eSDan Willemsen		}
594*1c12ee1eSDan Willemsen		if diff := cmp.Diff(want, got, sortTypes, compare); diff != "" {
595*1c12ee1eSDan Willemsen			t.Errorf("RangeEnums() mismatch (-want +got):\n%v", diff)
596*1c12ee1eSDan Willemsen		}
597*1c12ee1eSDan Willemsen	})
598*1c12ee1eSDan Willemsen
599*1c12ee1eSDan Willemsen	t.Run("RangeMessages", func(t *testing.T) {
600*1c12ee1eSDan Willemsen		want := []protoreflect.MessageType{mt1}
601*1c12ee1eSDan Willemsen		var got []protoreflect.MessageType
602*1c12ee1eSDan Willemsen		var gotCnt int
603*1c12ee1eSDan Willemsen		wantCnt := registry.NumMessages()
604*1c12ee1eSDan Willemsen		registry.RangeMessages(func(mt protoreflect.MessageType) bool {
605*1c12ee1eSDan Willemsen			got = append(got, mt)
606*1c12ee1eSDan Willemsen			gotCnt++
607*1c12ee1eSDan Willemsen			return true
608*1c12ee1eSDan Willemsen		})
609*1c12ee1eSDan Willemsen
610*1c12ee1eSDan Willemsen		if gotCnt != wantCnt {
611*1c12ee1eSDan Willemsen			t.Errorf("NumMessages() = %v, want %v", gotCnt, wantCnt)
612*1c12ee1eSDan Willemsen		}
613*1c12ee1eSDan Willemsen		if diff := cmp.Diff(want, got, sortTypes, compare); diff != "" {
614*1c12ee1eSDan Willemsen			t.Errorf("RangeMessages() mismatch (-want +got):\n%v", diff)
615*1c12ee1eSDan Willemsen		}
616*1c12ee1eSDan Willemsen	})
617*1c12ee1eSDan Willemsen
618*1c12ee1eSDan Willemsen	t.Run("RangeExtensions", func(t *testing.T) {
619*1c12ee1eSDan Willemsen		want := []protoreflect.ExtensionType{xt1, xt2}
620*1c12ee1eSDan Willemsen		var got []protoreflect.ExtensionType
621*1c12ee1eSDan Willemsen		var gotCnt int
622*1c12ee1eSDan Willemsen		wantCnt := registry.NumExtensions()
623*1c12ee1eSDan Willemsen		registry.RangeExtensions(func(xt protoreflect.ExtensionType) bool {
624*1c12ee1eSDan Willemsen			got = append(got, xt)
625*1c12ee1eSDan Willemsen			gotCnt++
626*1c12ee1eSDan Willemsen			return true
627*1c12ee1eSDan Willemsen		})
628*1c12ee1eSDan Willemsen
629*1c12ee1eSDan Willemsen		if gotCnt != wantCnt {
630*1c12ee1eSDan Willemsen			t.Errorf("NumExtensions() = %v, want %v", gotCnt, wantCnt)
631*1c12ee1eSDan Willemsen		}
632*1c12ee1eSDan Willemsen		if diff := cmp.Diff(want, got, sortTypes, compare); diff != "" {
633*1c12ee1eSDan Willemsen			t.Errorf("RangeExtensions() mismatch (-want +got):\n%v", diff)
634*1c12ee1eSDan Willemsen		}
635*1c12ee1eSDan Willemsen	})
636*1c12ee1eSDan Willemsen
637*1c12ee1eSDan Willemsen	t.Run("RangeExtensionsByMessage", func(t *testing.T) {
638*1c12ee1eSDan Willemsen		want := []protoreflect.ExtensionType{xt1, xt2}
639*1c12ee1eSDan Willemsen		var got []protoreflect.ExtensionType
640*1c12ee1eSDan Willemsen		var gotCnt int
641*1c12ee1eSDan Willemsen		wantCnt := registry.NumExtensionsByMessage("testprotos.Message1")
642*1c12ee1eSDan Willemsen		registry.RangeExtensionsByMessage("testprotos.Message1", func(xt protoreflect.ExtensionType) bool {
643*1c12ee1eSDan Willemsen			got = append(got, xt)
644*1c12ee1eSDan Willemsen			gotCnt++
645*1c12ee1eSDan Willemsen			return true
646*1c12ee1eSDan Willemsen		})
647*1c12ee1eSDan Willemsen
648*1c12ee1eSDan Willemsen		if gotCnt != wantCnt {
649*1c12ee1eSDan Willemsen			t.Errorf("NumExtensionsByMessage() = %v, want %v", gotCnt, wantCnt)
650*1c12ee1eSDan Willemsen		}
651*1c12ee1eSDan Willemsen		if diff := cmp.Diff(want, got, sortTypes, compare); diff != "" {
652*1c12ee1eSDan Willemsen			t.Errorf("RangeExtensionsByMessage() mismatch (-want +got):\n%v", diff)
653*1c12ee1eSDan Willemsen		}
654*1c12ee1eSDan Willemsen	})
655*1c12ee1eSDan Willemsen}
656