1package pgs 2 3import ( 4 "errors" 5 "testing" 6 7 desc "github.com/golang/protobuf/descriptor" 8 "github.com/golang/protobuf/proto" 9 "github.com/golang/protobuf/protoc-gen-go/descriptor" 10 "github.com/golang/protobuf/ptypes/any" 11 "github.com/stretchr/testify/assert" 12) 13 14func TestMsg_Name(t *testing.T) { 15 t.Parallel() 16 17 m := &msg{desc: &descriptor.DescriptorProto{Name: proto.String("msg")}} 18 19 assert.Equal(t, "msg", m.Name().String()) 20} 21 22func TestMsg_FullyQualifiedName(t *testing.T) { 23 t.Parallel() 24 25 m := &msg{fqn: "msg"} 26 assert.Equal(t, m.fqn, m.FullyQualifiedName()) 27} 28 29func TestMsg_Syntax(t *testing.T) { 30 t.Parallel() 31 32 m := &msg{} 33 f := dummyFile() 34 f.addMessage(m) 35 36 assert.Equal(t, f.Syntax(), m.Syntax()) 37} 38 39func TestMsg_Package(t *testing.T) { 40 t.Parallel() 41 42 m := &msg{} 43 f := dummyFile() 44 f.addMessage(m) 45 46 assert.NotNil(t, m.Package()) 47 assert.Equal(t, f.Package(), m.Package()) 48} 49 50func TestMsg_File(t *testing.T) { 51 t.Parallel() 52 53 m := &msg{} 54 pm := dummyMsg() 55 pm.addMessage(m) 56 57 assert.NotNil(t, m.File()) 58 assert.Equal(t, pm.File(), m.File()) 59} 60 61func TestMsg_BuildTarget(t *testing.T) { 62 t.Parallel() 63 64 m := &msg{} 65 f := dummyFile() 66 f.addMessage(m) 67 68 assert.False(t, m.BuildTarget()) 69 f.buildTarget = true 70 assert.True(t, m.BuildTarget()) 71} 72 73func TestMsg_Descriptor(t *testing.T) { 74 t.Parallel() 75 76 m := &msg{desc: &descriptor.DescriptorProto{}} 77 assert.Equal(t, m.desc, m.Descriptor()) 78} 79 80func TestMsg_Parent(t *testing.T) { 81 t.Parallel() 82 83 m := &msg{} 84 pm := dummyMsg() 85 pm.addMessage(m) 86 87 assert.Equal(t, pm, m.Parent()) 88} 89 90func TestMsg_IsMapEntry(t *testing.T) { 91 t.Parallel() 92 93 m := &msg{desc: &descriptor.DescriptorProto{}} 94 assert.False(t, m.IsMapEntry()) 95 96 m.desc.Options = &descriptor.MessageOptions{ 97 MapEntry: proto.Bool(true), 98 } 99 assert.True(t, m.IsMapEntry()) 100} 101 102func TestMsg_Enums(t *testing.T) { 103 t.Parallel() 104 105 m := &msg{} 106 assert.Empty(t, m.Enums()) 107 108 sm := &msg{} 109 sm.addEnum(&enum{}) 110 m.addMessage(sm) 111 112 m.addEnum(&enum{}) 113 assert.Len(t, m.Enums(), 1) 114} 115 116func TestMsg_AllEnums(t *testing.T) { 117 t.Parallel() 118 119 m := &msg{} 120 assert.Empty(t, m.AllEnums()) 121 122 sm := &msg{} 123 sm.addEnum(&enum{}) 124 m.addMessage(sm) 125 126 m.addEnum(&enum{}) 127 assert.Len(t, m.AllEnums(), 2) 128} 129 130func TestMsg_Messages(t *testing.T) { 131 t.Parallel() 132 133 m := &msg{} 134 assert.Empty(t, m.Messages()) 135 136 sm := &msg{} 137 sm.addMessage(&msg{}) 138 m.addMessage(sm) 139 140 assert.Len(t, m.Messages(), 1) 141} 142 143func TestMsg_AllMessages(t *testing.T) { 144 t.Parallel() 145 146 m := &msg{} 147 assert.Empty(t, m.AllMessages()) 148 149 sm := &msg{} 150 sm.addMessage(&msg{}) 151 m.addMessage(sm) 152 153 assert.Len(t, m.AllMessages(), 2) 154} 155 156func TestMsg_MapEntries(t *testing.T) { 157 t.Parallel() 158 159 m := &msg{} 160 assert.Empty(t, m.MapEntries()) 161 162 m.addMapEntry(&msg{}) 163 assert.Len(t, m.MapEntries(), 1) 164} 165 166func TestMsg_Fields(t *testing.T) { 167 t.Parallel() 168 169 m := &msg{} 170 assert.Empty(t, m.Fields()) 171 172 m.addField(&field{}) 173 m.addField(&field{oneof: &oneof{}}) 174 assert.Len(t, m.Fields(), 2) 175} 176 177func TestMsg_NonOneOfFields(t *testing.T) { 178 t.Parallel() 179 180 m := &msg{} 181 assert.Empty(t, m.NonOneOfFields()) 182 183 m.addField(&field{}) 184 m.addField(&field{oneof: &oneof{}}) 185 m.addField(&field{}) 186 assert.Len(t, m.NonOneOfFields(), 2) 187} 188 189func TestMsg_OneOfFields(t *testing.T) { 190 t.Parallel() 191 192 o := &oneof{} 193 o.addField(&field{}) 194 195 m := &msg{} 196 m.addField(&field{}) 197 m.addField(&field{}) 198 199 assert.Empty(t, m.OneOfFields()) 200 m.addOneOf(o) 201 assert.Len(t, m.OneOfFields(), 1) 202} 203 204func TestMsg_OneOfs(t *testing.T) { 205 t.Parallel() 206 207 m := &msg{} 208 assert.Empty(t, m.OneOfs()) 209 210 m.addOneOf(&oneof{}) 211 assert.Len(t, m.OneOfs(), 1) 212} 213 214func TestMsg_Extension(t *testing.T) { 215 // cannot be parallel 216 m := &msg{desc: &descriptor.DescriptorProto{}} 217 assert.NotPanics(t, func() { m.Extension(nil, nil) }) 218} 219 220func TestMsg_Extensions(t *testing.T) { 221 t.Parallel() 222 223 m := &msg{} 224 assert.Empty(t, m.Extensions()) 225 226 ext := &ext{} 227 m.addExtension(ext) 228 assert.Len(t, m.Extensions(), 1) 229} 230 231func TestMsg_DefinedExtensions(t *testing.T) { 232 t.Parallel() 233 234 m := &msg{} 235 assert.Empty(t, m.DefinedExtensions()) 236 237 ext := &ext{} 238 m.addDefExtension(ext) 239 assert.Len(t, m.DefinedExtensions(), 1) 240} 241 242func TestMsg_Accept(t *testing.T) { 243 t.Parallel() 244 245 m := &msg{} 246 m.addMessage(&msg{}) 247 m.addEnum(&enum{}) 248 m.addField(&field{}) 249 m.addOneOf(&oneof{}) 250 m.addDefExtension(&ext{}) 251 252 assert.NoError(t, m.accept(nil)) 253 254 v := &mockVisitor{} 255 assert.NoError(t, m.accept(v)) 256 assert.Equal(t, 1, v.message) 257 assert.Zero(t, v.enum) 258 assert.Zero(t, v.field) 259 assert.Zero(t, v.oneof) 260 assert.Zero(t, v.extension) 261 262 v.Reset() 263 v.v = v 264 v.err = errors.New("") 265 assert.Error(t, m.accept(v)) 266 assert.Equal(t, 1, v.message) 267 assert.Zero(t, v.enum) 268 assert.Zero(t, v.field) 269 assert.Zero(t, v.oneof) 270 assert.Zero(t, v.extension) 271 272 v.Reset() 273 assert.NoError(t, m.accept(v)) 274 assert.Equal(t, 2, v.message) 275 assert.Equal(t, 1, v.enum) 276 assert.Equal(t, 1, v.field) 277 assert.Equal(t, 1, v.oneof) 278 assert.Equal(t, 1, v.extension) 279 280 v.Reset() 281 m.addDefExtension(&mockExtension{err: errors.New("")}) 282 assert.Error(t, m.accept(v)) 283 assert.Equal(t, 2, v.message) 284 assert.Equal(t, 1, v.enum) 285 assert.Equal(t, 1, v.field) 286 assert.Equal(t, 1, v.oneof) 287 assert.Equal(t, 2, v.extension) 288 289 v.Reset() 290 m.addOneOf(&mockOneOf{err: errors.New("")}) 291 assert.Error(t, m.accept(v)) 292 assert.Equal(t, 2, v.message) 293 assert.Equal(t, 1, v.enum) 294 assert.Equal(t, 1, v.field) 295 assert.Equal(t, 2, v.oneof) 296 assert.Zero(t, v.extension) 297 298 v.Reset() 299 m.addField(&mockField{err: errors.New("")}) 300 assert.Error(t, m.accept(v)) 301 assert.Equal(t, 2, v.message) 302 assert.Equal(t, 1, v.enum) 303 assert.Equal(t, 2, v.field) 304 assert.Zero(t, v.oneof) 305 assert.Zero(t, v.extension) 306 307 v.Reset() 308 m.addMessage(&mockMessage{err: errors.New("")}) 309 assert.Error(t, m.accept(v)) 310 assert.Equal(t, 3, v.message) 311 assert.Equal(t, 1, v.enum) 312 assert.Zero(t, v.field) 313 assert.Zero(t, v.oneof) 314 assert.Zero(t, v.extension) 315 316 v.Reset() 317 m.addEnum(&mockEnum{err: errors.New("")}) 318 assert.Error(t, m.accept(v)) 319 assert.Equal(t, 2, v.enum) 320 assert.Equal(t, 1, v.message) 321 assert.Zero(t, v.field) 322 assert.Zero(t, v.oneof) 323 assert.Zero(t, v.extension) 324} 325 326func TestMsg_Imports(t *testing.T) { 327 t.Parallel() 328 329 m := &msg{} 330 assert.Empty(t, m.Imports()) 331 332 m.addField(&mockField{i: []File{&file{}, &file{}}}) 333 assert.Len(t, m.Imports(), 1) 334 335 nf := &file{desc: &descriptor.FileDescriptorProto{ 336 Name: proto.String("foobar"), 337 }} 338 m.addField(&mockField{i: []File{nf, nf}}) 339 assert.Len(t, m.Imports(), 2) 340} 341 342func TestMsg_ChildAtPath(t *testing.T) { 343 t.Parallel() 344 345 m := &msg{} 346 assert.Equal(t, m, m.childAtPath(nil)) 347 assert.Nil(t, m.childAtPath([]int32{1})) 348 assert.Nil(t, m.childAtPath([]int32{999, 456})) 349} 350 351func TestMsg_WellKnownType(t *testing.T) { 352 fd, md := desc.ForMessage(&any.Any{}) 353 p := &pkg{fd: fd} 354 f := &file{desc: fd} 355 m := &msg{desc: md} 356 f.addMessage(m) 357 p.addFile(f) 358 359 assert.True(t, m.IsWellKnown()) 360 assert.Equal(t, AnyWKT, m.WellKnownType()) 361 362 m.desc.Name = proto.String("Foobar") 363 assert.False(t, m.IsWellKnown()) 364 assert.Equal(t, UnknownWKT, m.WellKnownType()) 365 366 m.desc.Name = proto.String("Any") 367 f.desc.Package = proto.String("fizz.buzz") 368 assert.False(t, m.IsWellKnown()) 369 assert.Equal(t, UnknownWKT, m.WellKnownType()) 370} 371 372type mockMessage struct { 373 Message 374 i []File 375 p ParentEntity 376 err error 377} 378 379func (m *mockMessage) Imports() []File { return m.i } 380 381func (m *mockMessage) setParent(p ParentEntity) { m.p = p } 382 383func (m *mockMessage) accept(v Visitor) error { 384 _, err := v.VisitMessage(m) 385 if m.err != nil { 386 return m.err 387 } 388 return err 389} 390 391func dummyMsg() *msg { 392 f := dummyFile() 393 394 m := &msg{ 395 desc: &descriptor.DescriptorProto{Name: proto.String("message")}, 396 } 397 398 f.addMessage(m) 399 return m 400} 401