github.com/jhump/protoreflect@v1.16.0/desc/descriptor_test.go (about) 1 package desc 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "math" 7 "os" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/golang/protobuf/proto" 13 "google.golang.org/protobuf/types/descriptorpb" 14 _ "google.golang.org/protobuf/types/known/apipb" 15 _ "google.golang.org/protobuf/types/known/emptypb" 16 _ "google.golang.org/protobuf/types/known/fieldmaskpb" 17 _ "google.golang.org/protobuf/types/known/sourcecontextpb" 18 _ "google.golang.org/protobuf/types/known/typepb" 19 _ "google.golang.org/protobuf/types/pluginpb" 20 21 "github.com/jhump/protoreflect/internal" 22 "github.com/jhump/protoreflect/internal/testprotos" 23 "github.com/jhump/protoreflect/internal/testutil" 24 ) 25 26 func TestFileDescriptorObjectGraph(t *testing.T) { 27 // This checks the structure of the descriptor for desc_test1.proto to make sure 28 // the "rich descriptor" accurately models everything therein. 29 fd, err := loadProtoset("../internal/testprotos/desc_test1.protoset") 30 testutil.Ok(t, err) 31 checkDescriptor(t, "file", 0, fd, nil, fd, descCase{ 32 name: "desc_test1.proto", 33 references: map[string]childCases{ 34 "messages": {(*FileDescriptor).GetMessageTypes, []descCase{ 35 { 36 name: "testprotos.TestMessage", 37 references: map[string]childCases{ 38 "fields": {(*MessageDescriptor).GetFields, []descCase{ 39 { 40 name: "testprotos.TestMessage.nm", 41 references: map[string]childCases{ 42 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")}, 43 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 44 "one of": {(*FieldDescriptor).GetOneOf, nil}, 45 }, 46 }, 47 { 48 name: "testprotos.TestMessage.anm", 49 references: map[string]childCases{ 50 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")}, 51 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 52 "one of": {(*FieldDescriptor).GetOneOf, nil}, 53 }, 54 }, 55 { 56 name: "testprotos.TestMessage.yanm", 57 references: map[string]childCases{ 58 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")}, 59 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 60 "one of": {(*FieldDescriptor).GetOneOf, nil}, 61 }, 62 }, 63 { 64 name: "testprotos.TestMessage.ne", 65 references: map[string]childCases{ 66 "message type": {(*FieldDescriptor).GetMessageType, nil}, 67 "enum type": {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")}, 68 "one of": {(*FieldDescriptor).GetOneOf, nil}, 69 }, 70 }, 71 }}, 72 // this rabbit hole goes pretty deep... 73 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{ 74 { 75 name: "testprotos.TestMessage.NestedMessage", 76 references: map[string]childCases{ 77 "fields": {(*MessageDescriptor).GetFields, []descCase{ 78 { 79 name: "testprotos.TestMessage.NestedMessage.anm", 80 references: map[string]childCases{ 81 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")}, 82 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 83 "one of": {(*FieldDescriptor).GetOneOf, nil}, 84 }, 85 }, 86 { 87 name: "testprotos.TestMessage.NestedMessage.yanm", 88 references: map[string]childCases{ 89 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")}, 90 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 91 "one of": {(*FieldDescriptor).GetOneOf, nil}, 92 }, 93 }, 94 }}, 95 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{ 96 { 97 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage", 98 references: map[string]childCases{ 99 "fields": {(*MessageDescriptor).GetFields, []descCase{ 100 { 101 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.yanm", 102 references: map[string]childCases{ 103 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage")}, 104 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 105 "one of": {(*FieldDescriptor).GetOneOf, nil}, 106 }, 107 }, 108 }}, 109 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{ 110 { 111 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage", 112 references: map[string]childCases{ 113 "nested fields": {(*MessageDescriptor).GetFields, []descCase{ 114 { 115 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.foo", 116 references: map[string]childCases{ 117 "message type": {(*FieldDescriptor).GetMessageType, nil}, 118 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 119 "one of": {(*FieldDescriptor).GetOneOf, nil}, 120 }, 121 }, 122 { 123 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.bar", 124 references: map[string]childCases{ 125 "message type": {(*FieldDescriptor).GetMessageType, nil}, 126 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 127 "one of": {(*FieldDescriptor).GetOneOf, nil}, 128 }, 129 }, 130 { 131 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.baz", 132 references: map[string]childCases{ 133 "message type": {(*FieldDescriptor).GetMessageType, nil}, 134 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 135 "one of": {(*FieldDescriptor).GetOneOf, nil}, 136 }, 137 }, 138 { 139 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.dne", 140 references: map[string]childCases{ 141 "message type": {(*FieldDescriptor).GetMessageType, nil}, 142 "enum type": {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum")}, 143 "one of": {(*FieldDescriptor).GetOneOf, nil}, 144 }, 145 }, 146 { 147 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.anm", 148 references: map[string]childCases{ 149 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage")}, 150 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 151 "one of": {(*FieldDescriptor).GetOneOf, nil}, 152 }, 153 }, 154 { 155 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.nm", 156 references: map[string]childCases{ 157 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")}, 158 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 159 "one of": {(*FieldDescriptor).GetOneOf, nil}, 160 }, 161 }, 162 { 163 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.tm", 164 references: map[string]childCases{ 165 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")}, 166 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 167 "one of": {(*FieldDescriptor).GetOneOf, nil}, 168 }, 169 }, 170 }}, 171 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 172 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, []descCase{ 173 { 174 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum", 175 references: map[string]childCases{ 176 "values": {(*EnumDescriptor).GetValues, children( 177 "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum.VALUE1", 178 "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum.VALUE2"), 179 }, 180 }, 181 }, 182 }}, 183 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 184 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 185 }, 186 }, 187 }}, 188 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 189 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, []descCase{ 190 { 191 name: "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.flags", 192 number: 200, 193 references: map[string]childCases{ 194 "owner": {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")}, 195 "message type": {(*FieldDescriptor).GetMessageType, nil}, 196 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 197 "one of": {(*FieldDescriptor).GetOneOf, nil}, 198 }, 199 }, 200 }}, 201 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 202 }, 203 }, 204 }}, 205 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 206 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 207 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 208 }, 209 }, 210 }}, 211 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, []descCase{ 212 { 213 name: "testprotos.TestMessage.NestedEnum", 214 references: map[string]childCases{ 215 "values": {(*EnumDescriptor).GetValues, children( 216 "testprotos.TestMessage.NestedEnum.VALUE1", "testprotos.TestMessage.NestedEnum.VALUE2"), 217 }, 218 }, 219 }, 220 }}, 221 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 222 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 223 }, 224 }, 225 { 226 name: "testprotos.AnotherTestMessage", 227 references: map[string]childCases{ 228 "fields": {(*MessageDescriptor).GetFields, []descCase{ 229 { 230 name: "testprotos.AnotherTestMessage.dne", 231 references: map[string]childCases{ 232 "message type": {(*FieldDescriptor).GetMessageType, nil}, 233 "enum type": {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum")}, 234 "one of": {(*FieldDescriptor).GetOneOf, nil}, 235 }, 236 }, 237 { 238 name: "testprotos.AnotherTestMessage.map_field1", 239 references: map[string]childCases{ 240 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField1Entry")}, 241 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 242 "one of": {(*FieldDescriptor).GetOneOf, nil}, 243 }, 244 }, 245 { 246 name: "testprotos.AnotherTestMessage.map_field2", 247 references: map[string]childCases{ 248 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField2Entry")}, 249 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 250 "one of": {(*FieldDescriptor).GetOneOf, nil}, 251 }, 252 }, 253 { 254 name: "testprotos.AnotherTestMessage.map_field3", 255 references: map[string]childCases{ 256 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField3Entry")}, 257 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 258 "one of": {(*FieldDescriptor).GetOneOf, nil}, 259 }, 260 }, 261 { 262 name: "testprotos.AnotherTestMessage.map_field4", 263 references: map[string]childCases{ 264 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.MapField4Entry")}, 265 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 266 "one of": {(*FieldDescriptor).GetOneOf, nil}, 267 }, 268 }, 269 { 270 name: "testprotos.AnotherTestMessage.rocknroll", 271 references: map[string]childCases{ 272 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.RockNRoll")}, 273 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 274 "one of": {(*FieldDescriptor).GetOneOf, nil}, 275 }, 276 }, 277 { 278 name: "testprotos.AnotherTestMessage.str", 279 references: map[string]childCases{ 280 "message type": {(*FieldDescriptor).GetMessageType, nil}, 281 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 282 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.AnotherTestMessage.atmoo")}, 283 }, 284 }, 285 { 286 name: "testprotos.AnotherTestMessage.int", 287 references: map[string]childCases{ 288 "message type": {(*FieldDescriptor).GetMessageType, nil}, 289 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 290 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.AnotherTestMessage.atmoo")}, 291 }, 292 }, 293 { 294 name: "testprotos.AnotherTestMessage.withoptions", 295 references: map[string]childCases{ 296 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage.WithOptions")}, 297 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 298 "one of": {(*FieldDescriptor).GetOneOf, nil}, 299 }, 300 }, 301 }}, 302 "one ofs": {(*MessageDescriptor).GetOneOfs, []descCase{ 303 { 304 name: "testprotos.AnotherTestMessage.atmoo", 305 skipParent: true, 306 references: map[string]childCases{ 307 "fields": {(*OneOfDescriptor).GetChoices, fields( 308 fld{"testprotos.AnotherTestMessage.str", 7}, 309 fld{"testprotos.AnotherTestMessage.int", 8}), 310 }, 311 }, 312 }, 313 }}, 314 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, []descCase{ 315 { 316 name: "testprotos.AnotherTestMessage.MapField1Entry", 317 references: map[string]childCases{ 318 "fields": {(*MessageDescriptor).GetFields, []descCase{ 319 { 320 name: "testprotos.AnotherTestMessage.MapField1Entry.key", 321 references: map[string]childCases{ 322 "message type": {(*FieldDescriptor).GetMessageType, nil}, 323 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 324 "one of": {(*FieldDescriptor).GetOneOf, nil}, 325 }, 326 }, 327 { 328 name: "testprotos.AnotherTestMessage.MapField1Entry.value", 329 references: map[string]childCases{ 330 "message type": {(*FieldDescriptor).GetMessageType, nil}, 331 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 332 "one of": {(*FieldDescriptor).GetOneOf, nil}, 333 }, 334 }, 335 }}, 336 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 337 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 338 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 339 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 340 }, 341 }, 342 { 343 name: "testprotos.AnotherTestMessage.MapField2Entry", 344 references: map[string]childCases{ 345 "fields": {(*MessageDescriptor).GetFields, []descCase{ 346 { 347 name: "testprotos.AnotherTestMessage.MapField2Entry.key", 348 references: map[string]childCases{ 349 "message type": {(*FieldDescriptor).GetMessageType, nil}, 350 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 351 "one of": {(*FieldDescriptor).GetOneOf, nil}, 352 }, 353 }, 354 { 355 name: "testprotos.AnotherTestMessage.MapField2Entry.value", 356 references: map[string]childCases{ 357 "message type": {(*FieldDescriptor).GetMessageType, nil}, 358 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 359 "one of": {(*FieldDescriptor).GetOneOf, nil}, 360 }, 361 }, 362 }}, 363 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 364 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 365 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 366 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 367 }, 368 }, 369 { 370 name: "testprotos.AnotherTestMessage.MapField3Entry", 371 references: map[string]childCases{ 372 "fields": {(*MessageDescriptor).GetFields, []descCase{ 373 { 374 name: "testprotos.AnotherTestMessage.MapField3Entry.key", 375 references: map[string]childCases{ 376 "message type": {(*FieldDescriptor).GetMessageType, nil}, 377 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 378 "one of": {(*FieldDescriptor).GetOneOf, nil}, 379 }, 380 }, 381 { 382 name: "testprotos.AnotherTestMessage.MapField3Entry.value", 383 references: map[string]childCases{ 384 "message type": {(*FieldDescriptor).GetMessageType, nil}, 385 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 386 "one of": {(*FieldDescriptor).GetOneOf, nil}, 387 }, 388 }, 389 }}, 390 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 391 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 392 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 393 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 394 }, 395 }, 396 { 397 name: "testprotos.AnotherTestMessage.MapField4Entry", 398 references: map[string]childCases{ 399 "fields": {(*MessageDescriptor).GetFields, []descCase{ 400 { 401 name: "testprotos.AnotherTestMessage.MapField4Entry.key", 402 references: map[string]childCases{ 403 "message type": {(*FieldDescriptor).GetMessageType, nil}, 404 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 405 "one of": {(*FieldDescriptor).GetOneOf, nil}, 406 }, 407 }, 408 { 409 name: "testprotos.AnotherTestMessage.MapField4Entry.value", 410 references: map[string]childCases{ 411 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage")}, 412 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 413 "one of": {(*FieldDescriptor).GetOneOf, nil}, 414 }, 415 }, 416 }}, 417 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 418 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 419 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 420 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 421 }, 422 }, 423 { 424 name: "testprotos.AnotherTestMessage.RockNRoll", 425 references: map[string]childCases{ 426 "fields": {(*MessageDescriptor).GetFields, []descCase{ 427 { 428 name: "testprotos.AnotherTestMessage.RockNRoll.beatles", 429 references: map[string]childCases{ 430 "message type": {(*FieldDescriptor).GetMessageType, nil}, 431 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 432 "one of": {(*FieldDescriptor).GetOneOf, nil}, 433 }, 434 }, 435 { 436 name: "testprotos.AnotherTestMessage.RockNRoll.stones", 437 references: map[string]childCases{ 438 "message type": {(*FieldDescriptor).GetMessageType, nil}, 439 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 440 "one of": {(*FieldDescriptor).GetOneOf, nil}, 441 }, 442 }, 443 { 444 name: "testprotos.AnotherTestMessage.RockNRoll.doors", 445 references: map[string]childCases{ 446 "message type": {(*FieldDescriptor).GetMessageType, nil}, 447 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 448 "one of": {(*FieldDescriptor).GetOneOf, nil}, 449 }, 450 }, 451 }}, 452 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 453 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 454 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 455 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 456 }, 457 }, 458 { 459 name: "testprotos.AnotherTestMessage.WithOptions", 460 references: map[string]childCases{ 461 "fields": {(*MessageDescriptor).GetFields, nil}, 462 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 463 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 464 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 465 "one ofs": {(*MessageDescriptor).GetOneOfs, nil}, 466 }, 467 }, 468 }}, 469 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 470 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 471 }, 472 }, 473 }}, 474 "enums": {(*FileDescriptor).GetEnumTypes, nil}, 475 "services": {(*FileDescriptor).GetServices, nil}, 476 "extensions": {(*FileDescriptor).GetExtensions, []descCase{ 477 { 478 name: "testprotos.xtm", 479 number: 100, 480 references: map[string]childCases{ 481 "owner": {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")}, 482 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")}, 483 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 484 "one of": {(*FieldDescriptor).GetOneOf, nil}, 485 }, 486 }, 487 { 488 name: "testprotos.xs", 489 number: 101, 490 references: map[string]childCases{ 491 "owner": {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")}, 492 "message type": {(*FieldDescriptor).GetMessageType, nil}, 493 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 494 "one of": {(*FieldDescriptor).GetOneOf, nil}, 495 }, 496 }, 497 { 498 name: "testprotos.xi", 499 number: 102, 500 references: map[string]childCases{ 501 "owner": {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")}, 502 "message type": {(*FieldDescriptor).GetMessageType, nil}, 503 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 504 "one of": {(*FieldDescriptor).GetOneOf, nil}, 505 }, 506 }, 507 { 508 name: "testprotos.xui", 509 number: 103, 510 references: map[string]childCases{ 511 "owner": {(*FieldDescriptor).GetOwner, refs("testprotos.AnotherTestMessage")}, 512 "message type": {(*FieldDescriptor).GetMessageType, nil}, 513 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 514 "one of": {(*FieldDescriptor).GetOneOf, nil}, 515 }, 516 }, 517 }}, 518 }, 519 }) 520 } 521 522 func TestOneOfDescriptors(t *testing.T) { 523 fd, err := LoadFileDescriptor("desc_test2.proto") 524 testutil.Ok(t, err) 525 md, err := LoadMessageDescriptor("testprotos.Frobnitz") 526 testutil.Ok(t, err) 527 checkDescriptor(t, "message", 0, md, fd, fd, descCase{ 528 name: "testprotos.Frobnitz", 529 references: map[string]childCases{ 530 "fields": {(*MessageDescriptor).GetFields, []descCase{ 531 { 532 name: "testprotos.Frobnitz.a", 533 references: map[string]childCases{ 534 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage")}, 535 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 536 "one of": {(*FieldDescriptor).GetOneOf, nil}, 537 }, 538 }, 539 { 540 name: "testprotos.Frobnitz.b", 541 references: map[string]childCases{ 542 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.AnotherTestMessage")}, 543 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 544 "one of": {(*FieldDescriptor).GetOneOf, nil}, 545 }, 546 }, 547 { 548 name: "testprotos.Frobnitz.c1", 549 references: map[string]childCases{ 550 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")}, 551 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 552 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.abc")}, 553 }, 554 }, 555 { 556 name: "testprotos.Frobnitz.c2", 557 references: map[string]childCases{ 558 "message type": {(*FieldDescriptor).GetMessageType, nil}, 559 "enum type": {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")}, 560 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.abc")}, 561 }, 562 }, 563 { 564 name: "testprotos.Frobnitz.d", 565 references: map[string]childCases{ 566 "message type": {(*FieldDescriptor).GetMessageType, refs("testprotos.TestMessage.NestedMessage")}, 567 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 568 "one of": {(*FieldDescriptor).GetOneOf, nil}, 569 }, 570 }, 571 { 572 name: "testprotos.Frobnitz.e", 573 references: map[string]childCases{ 574 "message type": {(*FieldDescriptor).GetMessageType, nil}, 575 "enum type": {(*FieldDescriptor).GetEnumType, refs("testprotos.TestMessage.NestedEnum")}, 576 "one of": {(*FieldDescriptor).GetOneOf, nil}, 577 }, 578 }, 579 { 580 name: "testprotos.Frobnitz.f", 581 references: map[string]childCases{ 582 "message type": {(*FieldDescriptor).GetMessageType, nil}, 583 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 584 "one of": {(*FieldDescriptor).GetOneOf, nil}, 585 }, 586 }, 587 { 588 name: "testprotos.Frobnitz.g1", 589 references: map[string]childCases{ 590 "message type": {(*FieldDescriptor).GetMessageType, nil}, 591 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 592 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")}, 593 }, 594 }, 595 { 596 name: "testprotos.Frobnitz.g2", 597 references: map[string]childCases{ 598 "message type": {(*FieldDescriptor).GetMessageType, nil}, 599 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 600 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")}, 601 }, 602 }, 603 { 604 name: "testprotos.Frobnitz.g3", 605 references: map[string]childCases{ 606 "message type": {(*FieldDescriptor).GetMessageType, nil}, 607 "enum type": {(*FieldDescriptor).GetEnumType, nil}, 608 "one of": {(*FieldDescriptor).GetOneOf, refs("testprotos.Frobnitz.def")}, 609 }, 610 }, 611 }}, 612 "nested messages": {(*MessageDescriptor).GetNestedMessageTypes, nil}, 613 "nested enums": {(*MessageDescriptor).GetNestedEnumTypes, nil}, 614 "nested extensions": {(*MessageDescriptor).GetNestedExtensions, nil}, 615 "one ofs": {(*MessageDescriptor).GetOneOfs, []descCase{ 616 { 617 name: "testprotos.Frobnitz.abc", 618 skipParent: true, 619 references: map[string]childCases{ 620 "fields": {(*OneOfDescriptor).GetChoices, fields( 621 fld{"testprotos.Frobnitz.c1", 3}, 622 fld{"testprotos.Frobnitz.c2", 4}), 623 }, 624 }, 625 }, 626 { 627 name: "testprotos.Frobnitz.def", 628 skipParent: true, 629 references: map[string]childCases{ 630 "fields": {(*OneOfDescriptor).GetChoices, fields( 631 fld{"testprotos.Frobnitz.g1", 8}, 632 fld{"testprotos.Frobnitz.g2", 9}, 633 fld{"testprotos.Frobnitz.g3", 10}), 634 }, 635 }, 636 }, 637 }}, 638 }, 639 }) 640 } 641 642 func TestMessageDescriptorFindField(t *testing.T) { 643 md, err := LoadMessageDescriptor("testprotos.Frobnitz") 644 testutil.Ok(t, err) 645 for _, fd := range md.GetFields() { 646 found := md.FindFieldByName(fd.GetName()) 647 testutil.Eq(t, fd, found) 648 found = md.FindFieldByNumber(fd.GetNumber()) 649 testutil.Eq(t, fd, found) 650 } 651 testutil.Eq(t, (*FieldDescriptor)(nil), md.FindFieldByName("junk name")) 652 testutil.Eq(t, (*FieldDescriptor)(nil), md.FindFieldByNumber(99999)) 653 } 654 655 func TestEnumDescriptorFindValue(t *testing.T) { 656 fd, err := LoadFileDescriptor("desc_test_defaults.proto") 657 testutil.Ok(t, err) 658 ed, ok := fd.FindSymbol("testprotos.Number").(*EnumDescriptor) 659 testutil.Eq(t, true, ok) 660 lastNumber := int32(-1) 661 for _, vd := range ed.GetValues() { 662 found := ed.FindValueByName(vd.GetName()) 663 testutil.Eq(t, vd, found) 664 found = ed.FindValueByNumber(vd.GetNumber()) 665 if lastNumber == vd.GetNumber() { 666 // found value will be the first one with the given number, not this one 667 testutil.Eq(t, false, vd == found) 668 } else { 669 testutil.Eq(t, vd, found) 670 lastNumber = vd.GetNumber() 671 } 672 } 673 testutil.Eq(t, (*EnumValueDescriptor)(nil), ed.FindValueByName("junk name")) 674 testutil.Eq(t, (*EnumValueDescriptor)(nil), ed.FindValueByNumber(99999)) 675 } 676 677 func TestServiceDescriptors(t *testing.T) { 678 fd, err := LoadFileDescriptor("desc_test_proto3.proto") 679 testutil.Ok(t, err) 680 sd := fd.FindSymbol("testprotos.TestService").(*ServiceDescriptor) 681 // check the descriptor graph for this service and its descendants 682 checkDescriptor(t, "service", 0, sd, fd, fd, descCase{ 683 name: "testprotos.TestService", 684 references: map[string]childCases{ 685 "methods": {(*ServiceDescriptor).GetMethods, []descCase{ 686 { 687 name: "testprotos.TestService.DoSomething", 688 references: map[string]childCases{ 689 "request": {(*MethodDescriptor).GetInputType, refs("testprotos.TestRequest")}, 690 "response": {(*MethodDescriptor).GetOutputType, refs("jhump.protoreflect.desc.Bar")}, 691 }, 692 }, 693 { 694 name: "testprotos.TestService.DoSomethingElse", 695 references: map[string]childCases{ 696 "request": {(*MethodDescriptor).GetInputType, refs("testprotos.TestMessage")}, 697 "response": {(*MethodDescriptor).GetOutputType, refs("testprotos.TestResponse")}, 698 }, 699 }, 700 { 701 name: "testprotos.TestService.DoSomethingAgain", 702 references: map[string]childCases{ 703 "request": {(*MethodDescriptor).GetInputType, refs("jhump.protoreflect.desc.Bar")}, 704 "response": {(*MethodDescriptor).GetOutputType, refs("testprotos.AnotherTestMessage")}, 705 }, 706 }, 707 { 708 name: "testprotos.TestService.DoSomethingForever", 709 references: map[string]childCases{ 710 "request": {(*MethodDescriptor).GetInputType, refs("testprotos.TestRequest")}, 711 "response": {(*MethodDescriptor).GetOutputType, refs("testprotos.TestResponse")}, 712 }, 713 }, 714 }}, 715 }, 716 }) 717 // now verify that FindMethodByName works correctly 718 for _, md := range sd.GetMethods() { 719 found := sd.FindMethodByName(md.GetName()) 720 testutil.Eq(t, md, found) 721 } 722 testutil.Eq(t, (*MethodDescriptor)(nil), sd.FindMethodByName("junk name")) 723 } 724 725 type descCase struct { 726 name string 727 number int32 728 skipParent bool 729 references map[string]childCases 730 } 731 732 type childCases struct { 733 query interface{} 734 cases []descCase 735 } 736 737 func refs(names ...string) []descCase { 738 r := make([]descCase, len(names)) 739 for i, n := range names { 740 r[i] = descCase{name: n, skipParent: true} 741 } 742 return r 743 } 744 745 func children(names ...string) []descCase { 746 ch := make([]descCase, len(names)) 747 for i, n := range names { 748 ch[i] = descCase{name: n} 749 } 750 return ch 751 } 752 753 type fld struct { 754 name string 755 number int32 756 } 757 758 func fields(flds ...fld) []descCase { 759 f := make([]descCase, len(flds)) 760 for i, field := range flds { 761 f[i] = descCase{name: field.name, number: field.number, skipParent: true} 762 } 763 return f 764 } 765 766 func checkDescriptor(t *testing.T, caseName string, num int32, d Descriptor, parent Descriptor, fd *FileDescriptor, c descCase) { 767 // name and fully-qualified name 768 testutil.Eq(t, c.name, d.GetFullyQualifiedName(), caseName) 769 if _, ok := d.(*FileDescriptor); ok { 770 testutil.Eq(t, c.name, d.GetName(), caseName) 771 } else { 772 pos := strings.LastIndex(c.name, ".") 773 n := c.name 774 if pos >= 0 { 775 n = c.name[pos+1:] 776 } 777 testutil.Eq(t, n, d.GetName(), caseName) 778 // check that this object matches the canonical one returned by file descriptor 779 testutil.Eq(t, d, d.GetFile().FindSymbol(d.GetFullyQualifiedName()), caseName) 780 } 781 782 // number 783 switch d := d.(type) { 784 case (*FieldDescriptor): 785 n := num + 1 786 if c.number != 0 { 787 n = c.number 788 } 789 testutil.Eq(t, n, d.GetNumber(), caseName) 790 case (*EnumValueDescriptor): 791 n := num + 1 792 if c.number != 0 { 793 n = c.number 794 } 795 testutil.Eq(t, n, d.GetNumber(), caseName) 796 default: 797 if c.number != 0 { 798 panic(fmt.Sprintf("%s: number should only be specified by fields and enum values! numnber = %d, desc = %v", caseName, c.number, d)) 799 } 800 } 801 802 // parent and file 803 if !c.skipParent { 804 testutil.Eq(t, parent, d.GetParent(), caseName) 805 testutil.Eq(t, fd, d.GetFile(), caseName) 806 } 807 808 // comment 809 if fd.GetName() == "desc_test1.proto" && d.GetName() != "desc_test1.proto" { 810 expectedComment := "Comment for " + d.GetName() 811 if msg, ok := d.(*MessageDescriptor); ok && msg.IsMapEntry() { 812 // There are no comments on synthetic map-entry messages. 813 expectedComment = "" 814 } else if field, ok := d.(*FieldDescriptor); ok { 815 if field.GetOwner().IsMapEntry() || field.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP { 816 // There are no comments for fields of synthetic map-entry messages either. 817 // And comments for group fields end up on the synthetic message, not the field. 818 expectedComment = "" 819 } 820 } 821 testutil.Eq(t, expectedComment, strings.TrimSpace(d.GetSourceInfo().GetLeadingComments()), caseName) 822 } 823 824 // references 825 for name, cases := range c.references { 826 caseName := fmt.Sprintf("%s>%s", caseName, name) 827 children := runQuery(d, cases.query) 828 if testutil.Eq(t, len(cases.cases), len(children), caseName+" length") { 829 for i, childCase := range cases.cases { 830 caseName := fmt.Sprintf("%s[%d]", caseName, i) 831 checkDescriptor(t, caseName, int32(i), children[i], d, fd, childCase) 832 } 833 } 834 } 835 } 836 837 func runQuery(d Descriptor, query interface{}) []Descriptor { 838 r := reflect.ValueOf(query).Call([]reflect.Value{reflect.ValueOf(d)})[0] 839 if r.Kind() == reflect.Slice { 840 ret := make([]Descriptor, r.Len()) 841 for i := 0; i < r.Len(); i++ { 842 ret[i] = r.Index(i).Interface().(Descriptor) 843 } 844 return ret 845 } else if r.IsNil() { 846 return []Descriptor{} 847 } else { 848 return []Descriptor{r.Interface().(Descriptor)} 849 } 850 } 851 852 func TestFileDescriptorDeps(t *testing.T) { 853 // tests accessors for public and weak dependencies 854 fd1 := createDesc(t, &descriptorpb.FileDescriptorProto{Name: proto.String("a")}) 855 fd2 := createDesc(t, &descriptorpb.FileDescriptorProto{Name: proto.String("b")}) 856 fd3 := createDesc(t, &descriptorpb.FileDescriptorProto{Name: proto.String("c")}) 857 fd4 := createDesc(t, &descriptorpb.FileDescriptorProto{Name: proto.String("d")}) 858 fd5 := createDesc(t, &descriptorpb.FileDescriptorProto{Name: proto.String("e")}) 859 fd := createDesc(t, &descriptorpb.FileDescriptorProto{ 860 Name: proto.String("f"), 861 Dependency: []string{"a", "b", "c", "d", "e"}, 862 PublicDependency: []int32{1, 3}, 863 WeakDependency: []int32{2, 4}, 864 }, fd1, fd2, fd3, fd4, fd5) 865 866 deps := fd.GetDependencies() 867 testutil.Eq(t, 5, len(deps)) 868 testutil.Eq(t, fd1, deps[0]) 869 testutil.Eq(t, fd2, deps[1]) 870 testutil.Eq(t, fd3, deps[2]) 871 testutil.Eq(t, fd4, deps[3]) 872 testutil.Eq(t, fd5, deps[4]) 873 874 deps = fd.GetPublicDependencies() 875 testutil.Eq(t, 2, len(deps)) 876 testutil.Eq(t, fd2, deps[0]) 877 testutil.Eq(t, fd4, deps[1]) 878 879 deps = fd.GetWeakDependencies() 880 testutil.Eq(t, 2, len(deps)) 881 testutil.Eq(t, fd3, deps[0]) 882 testutil.Eq(t, fd5, deps[1]) 883 884 // Now try on a simple descriptor emitted by protoc 885 fd6, err := LoadFileDescriptor("nopkg/desc_test_nopkg.proto") 886 testutil.Ok(t, err) 887 fd7, err := LoadFileDescriptor("nopkg/desc_test_nopkg_new.proto") 888 testutil.Ok(t, err) 889 deps = fd6.GetPublicDependencies() 890 testutil.Eq(t, 1, len(deps)) 891 testutil.Eq(t, fd7, deps[0]) 892 } 893 894 func createDesc(t *testing.T, fd *descriptorpb.FileDescriptorProto, deps ...*FileDescriptor) *FileDescriptor { 895 desc, err := CreateFileDescriptor(fd, deps...) 896 testutil.Ok(t, err) 897 return desc 898 } 899 900 func TestLoadFileDescriptor(t *testing.T) { 901 fd, err := LoadFileDescriptor("desc_test1.proto") 902 testutil.Ok(t, err) 903 // some very shallow tests (we have more detailed ones in other test cases) 904 testutil.Eq(t, "desc_test1.proto", fd.GetName()) 905 testutil.Eq(t, "desc_test1.proto", fd.GetFullyQualifiedName()) 906 testutil.Eq(t, "testprotos", fd.GetPackage()) 907 } 908 909 func TestLoadMessageDescriptor(t *testing.T) { 910 // loading enclosed messages should return the same descriptor 911 // and have a reference to the same file descriptor 912 md, err := LoadMessageDescriptor("testprotos.TestMessage") 913 testutil.Ok(t, err) 914 testutil.Eq(t, "TestMessage", md.GetName()) 915 testutil.Eq(t, "testprotos.TestMessage", md.GetFullyQualifiedName()) 916 fd := md.GetFile() 917 testutil.Eq(t, "desc_test1.proto", fd.GetName()) 918 testutil.Eq(t, fd, md.GetParent()) 919 920 md2, err := LoadMessageDescriptorForMessage((*testprotos.TestMessage)(nil)) 921 testutil.Ok(t, err) 922 testutil.Eq(t, md, md2) 923 924 md3, err := LoadMessageDescriptorForType(reflect.TypeOf((*testprotos.TestMessage)(nil))) 925 testutil.Ok(t, err) 926 testutil.Eq(t, md, md3) 927 } 928 929 func TestLoadEnumDescriptor(t *testing.T) { 930 ed, err := LoadEnumDescriptorForEnum(testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage_DeeplyNestedEnum(0)) 931 testutil.Ok(t, err) 932 testutil.Eq(t, "DeeplyNestedEnum", ed.GetName()) 933 testutil.Eq(t, "testprotos.TestMessage.NestedMessage.AnotherNestedMessage.YetAnotherNestedMessage.DeeplyNestedEnum", ed.GetFullyQualifiedName()) 934 fd := ed.GetFile() 935 testutil.Eq(t, "desc_test1.proto", fd.GetName()) 936 ofd, err := LoadFileDescriptor("desc_test1.proto") 937 testutil.Ok(t, err) 938 testutil.Eq(t, ofd, fd) 939 940 ed2, err := LoadEnumDescriptorForEnum((*testprotos.TestEnum)(nil)) // pointer type for interface 941 testutil.Ok(t, err) 942 testutil.Eq(t, "TestEnum", ed2.GetName()) 943 testutil.Eq(t, "testprotos.TestEnum", ed2.GetFullyQualifiedName()) 944 fd = ed2.GetFile() 945 testutil.Eq(t, "desc_test_field_types.proto", fd.GetName()) 946 ofd, err = LoadFileDescriptor("desc_test_field_types.proto") 947 testutil.Ok(t, err) 948 testutil.Eq(t, ofd, fd) 949 testutil.Eq(t, fd, ed2.GetParent()) 950 951 // now use the APIs that take reflect.Type 952 ed3, err := LoadEnumDescriptorForType(reflect.TypeOf((*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage_DeeplyNestedEnum)(nil))) 953 testutil.Ok(t, err) 954 testutil.Eq(t, ed, ed3) 955 956 ed4, err := LoadEnumDescriptorForType(reflect.TypeOf(testprotos.TestEnum_FIRST)) 957 testutil.Ok(t, err) 958 testutil.Eq(t, ed2, ed4) 959 } 960 961 func TestLoadFileDescriptorWithDeps(t *testing.T) { 962 // Try one with some imports 963 fd, err := LoadFileDescriptor("desc_test2.proto") 964 testutil.Ok(t, err) 965 testutil.Eq(t, "desc_test2.proto", fd.GetName()) 966 testutil.Eq(t, "desc_test2.proto", fd.GetFullyQualifiedName()) 967 testutil.Eq(t, "testprotos", fd.GetPackage()) 968 969 deps := fd.GetDependencies() 970 testutil.Eq(t, 3, len(deps)) 971 testutil.Eq(t, "desc_test1.proto", deps[0].GetName()) 972 testutil.Eq(t, "pkg/desc_test_pkg.proto", deps[1].GetName()) 973 testutil.Eq(t, "nopkg/desc_test_nopkg.proto", deps[2].GetName()) 974 975 // loading the dependencies yields same descriptor objects 976 fd, err = LoadFileDescriptor("desc_test1.proto") 977 testutil.Ok(t, err) 978 testutil.Eq(t, deps[0], fd) 979 fd, err = LoadFileDescriptor("pkg/desc_test_pkg.proto") 980 testutil.Ok(t, err) 981 testutil.Eq(t, deps[1], fd) 982 fd, err = LoadFileDescriptor("nopkg/desc_test_nopkg.proto") 983 testutil.Ok(t, err) 984 testutil.Eq(t, deps[2], fd) 985 } 986 987 func TestLoadFileDescriptorForWellKnownProtos(t *testing.T) { 988 wellKnownProtos := map[string][]string{ 989 "google/protobuf/any.proto": {"google.protobuf.Any"}, 990 "google/protobuf/api.proto": {"google.protobuf.Api", "google.protobuf.Method", "google.protobuf.Mixin"}, 991 "google/protobuf/descriptor.proto": {"google.protobuf.FileDescriptorSet", "google.protobuf.DescriptorProto"}, 992 "google/protobuf/duration.proto": {"google.protobuf.Duration"}, 993 "google/protobuf/empty.proto": {"google.protobuf.Empty"}, 994 "google/protobuf/field_mask.proto": {"google.protobuf.FieldMask"}, 995 "google/protobuf/source_context.proto": {"google.protobuf.SourceContext"}, 996 "google/protobuf/struct.proto": {"google.protobuf.Struct", "google.protobuf.Value", "google.protobuf.NullValue"}, 997 "google/protobuf/timestamp.proto": {"google.protobuf.Timestamp"}, 998 "google/protobuf/type.proto": {"google.protobuf.Type", "google.protobuf.Field", "google.protobuf.Syntax"}, 999 "google/protobuf/wrappers.proto": {"google.protobuf.DoubleValue", "google.protobuf.Int32Value", "google.protobuf.StringValue"}, 1000 "google/protobuf/compiler/plugin.proto": {"google.protobuf.compiler.CodeGeneratorRequest"}, 1001 } 1002 1003 for file, types := range wellKnownProtos { 1004 fd, err := LoadFileDescriptor(file) 1005 testutil.Ok(t, err) 1006 testutil.Eq(t, file, fd.GetName()) 1007 for _, typ := range types { 1008 d := fd.FindSymbol(typ) 1009 testutil.Require(t, d != nil, "file %q does not have type %s", file, typ) 1010 d2 := fd.FindSymbol("." + typ) 1011 testutil.Eq(t, d, d2) 1012 } 1013 1014 // also try loading via alternate name 1015 file = internal.StdFileAliases[file] 1016 if file == "" { 1017 // not a file that has a known alternate, so nothing else to check... 1018 continue 1019 } 1020 fd, err = LoadFileDescriptor(file) 1021 testutil.Ok(t, err, "failed to load %q", file) 1022 for _, typ := range types { 1023 d := fd.FindSymbol(typ) 1024 testutil.Require(t, d != nil, "file %q does not have type %s", file, typ) 1025 d2 := fd.FindSymbol("." + typ) 1026 testutil.Eq(t, d, d2) 1027 } 1028 } 1029 } 1030 1031 func TestDefaultValues(t *testing.T) { 1032 fd, err := LoadFileDescriptor("desc_test_defaults.proto") 1033 testutil.Ok(t, err) 1034 1035 testCases := []struct { 1036 message, field string 1037 defaultVal interface{} 1038 }{ 1039 {"testprotos.PrimitiveDefaults", "fl32", float32(3.14159)}, 1040 {"testprotos.PrimitiveDefaults", "fl64", 3.14159}, 1041 {"testprotos.PrimitiveDefaults", "fl32d", float32(6.022140857e23)}, 1042 {"testprotos.PrimitiveDefaults", "fl64d", 6.022140857e23}, 1043 {"testprotos.PrimitiveDefaults", "fl32inf", float32(math.Inf(1))}, 1044 {"testprotos.PrimitiveDefaults", "fl64inf", math.Inf(1)}, 1045 {"testprotos.PrimitiveDefaults", "fl32negInf", float32(math.Inf(-1))}, 1046 {"testprotos.PrimitiveDefaults", "fl64negInf", math.Inf(-1)}, 1047 {"testprotos.PrimitiveDefaults", "fl32nan", float32(math.NaN())}, 1048 {"testprotos.PrimitiveDefaults", "fl64nan", math.NaN()}, 1049 {"testprotos.PrimitiveDefaults", "bl1", true}, 1050 {"testprotos.PrimitiveDefaults", "bl2", false}, 1051 {"testprotos.PrimitiveDefaults", "i32", int32(10101)}, 1052 {"testprotos.PrimitiveDefaults", "i32n", int32(-10101)}, 1053 {"testprotos.PrimitiveDefaults", "i32x", int32(0x20202)}, 1054 {"testprotos.PrimitiveDefaults", "i32xn", int32(-0x20202)}, 1055 {"testprotos.PrimitiveDefaults", "i64", int64(10101)}, 1056 {"testprotos.PrimitiveDefaults", "i64n", int64(-10101)}, 1057 {"testprotos.PrimitiveDefaults", "i64x", int64(0x20202)}, 1058 {"testprotos.PrimitiveDefaults", "i64xn", int64(-0x20202)}, 1059 {"testprotos.PrimitiveDefaults", "i32s", int32(10101)}, 1060 {"testprotos.PrimitiveDefaults", "i32sn", int32(-10101)}, 1061 {"testprotos.PrimitiveDefaults", "i32sx", int32(0x20202)}, 1062 {"testprotos.PrimitiveDefaults", "i32sxn", int32(-0x20202)}, 1063 {"testprotos.PrimitiveDefaults", "i64s", int64(10101)}, 1064 {"testprotos.PrimitiveDefaults", "i64sn", int64(-10101)}, 1065 {"testprotos.PrimitiveDefaults", "i64sx", int64(0x20202)}, 1066 {"testprotos.PrimitiveDefaults", "i64sxn", int64(-0x20202)}, 1067 {"testprotos.PrimitiveDefaults", "i32f", int32(10101)}, 1068 {"testprotos.PrimitiveDefaults", "i32fn", int32(-10101)}, 1069 {"testprotos.PrimitiveDefaults", "i32fx", int32(0x20202)}, 1070 {"testprotos.PrimitiveDefaults", "i32fxn", int32(-0x20202)}, 1071 {"testprotos.PrimitiveDefaults", "i64f", int64(10101)}, 1072 {"testprotos.PrimitiveDefaults", "i64fn", int64(-10101)}, 1073 {"testprotos.PrimitiveDefaults", "i64fx", int64(0x20202)}, 1074 {"testprotos.PrimitiveDefaults", "i64fxn", int64(-0x20202)}, 1075 {"testprotos.PrimitiveDefaults", "u32", uint32(10101)}, 1076 {"testprotos.PrimitiveDefaults", "u32x", uint32(0x20202)}, 1077 {"testprotos.PrimitiveDefaults", "u64", uint64(10101)}, 1078 {"testprotos.PrimitiveDefaults", "u64x", uint64(0x20202)}, 1079 {"testprotos.PrimitiveDefaults", "u32f", uint32(10101)}, 1080 {"testprotos.PrimitiveDefaults", "u32fx", uint32(0x20202)}, 1081 {"testprotos.PrimitiveDefaults", "u64f", uint64(10101)}, 1082 {"testprotos.PrimitiveDefaults", "u64fx", uint64(0x20202)}, 1083 1084 {"testprotos.StringAndBytesDefaults", "dq", "this is a string with \"nested quotes\""}, 1085 {"testprotos.StringAndBytesDefaults", "sq", "this is a string with \"nested quotes\""}, 1086 {"testprotos.StringAndBytesDefaults", "escaped_bytes", []byte("\000\001\a\b\f\n\r\t\v\\'\"\xfe")}, 1087 {"testprotos.StringAndBytesDefaults", "utf8_string", "\341\210\264"}, 1088 {"testprotos.StringAndBytesDefaults", "string_with_zero", "hel\000lo"}, 1089 {"testprotos.StringAndBytesDefaults", "bytes_with_zero", []byte("wor\000ld")}, 1090 1091 {"testprotos.EnumDefaults", "red", int32(0)}, 1092 {"testprotos.EnumDefaults", "green", int32(1)}, 1093 {"testprotos.EnumDefaults", "blue", int32(2)}, 1094 {"testprotos.EnumDefaults", "zero", int32(0)}, 1095 {"testprotos.EnumDefaults", "zed", int32(0)}, 1096 {"testprotos.EnumDefaults", "one", int32(1)}, 1097 {"testprotos.EnumDefaults", "dos", int32(2)}, 1098 } 1099 for i, tc := range testCases { 1100 def := fd.FindMessage(tc.message).FindFieldByName(tc.field).GetDefaultValue() 1101 testutil.Eq(t, tc.defaultVal, def, "wrong default value for case %d: %s.%s", i, tc.message, tc.field) 1102 } 1103 } 1104 1105 func TestUnescape(t *testing.T) { 1106 testCases := []struct { 1107 in, out string 1108 }{ 1109 // EOF, bad escapes 1110 {"\\", "\\"}, 1111 {"\\y", "\\y"}, 1112 // octal escapes 1113 {"\\0", "\000"}, 1114 {"\\7", "\007"}, 1115 {"\\07", "\007"}, 1116 {"\\77", "\077"}, 1117 {"\\78", "\0078"}, 1118 {"\\077", "\077"}, 1119 {"\\377", "\377"}, 1120 {"\\128", "\0128"}, 1121 {"\\0001", "\0001"}, 1122 {"\\0008", "\0008"}, 1123 // bad octal escape 1124 {"\\8", "\\8"}, 1125 // hex escapes 1126 {"\\x0", "\x00"}, 1127 {"\\x7", "\x07"}, 1128 {"\\x07", "\x07"}, 1129 {"\\x77", "\x77"}, 1130 {"\\x7g", "\x07g"}, 1131 {"\\xcc", "\xcc"}, 1132 {"\\xfff", "\xfff"}, 1133 // bad hex escape 1134 {"\\xg7", "\\xg7"}, 1135 {"\\x", "\\x"}, 1136 // short unicode escapes 1137 {"\\u0020", "\u0020"}, 1138 {"\\u007e", "\u007e"}, 1139 {"\\u1234", "\u1234"}, 1140 {"\\uffff", "\uffff"}, 1141 // long unicode escapes 1142 {"\\U00000024", "\U00000024"}, 1143 {"\\U00000076", "\U00000076"}, 1144 {"\\U00001234", "\U00001234"}, 1145 {"\\U0010FFFF", "\U0010FFFF"}, 1146 // bad unicode escapes 1147 {"\\u12", "\\u12"}, 1148 {"\\ug1232", "\\ug1232"}, 1149 {"\\u", "\\u"}, 1150 {"\\U1234567", "\\U1234567"}, 1151 {"\\U12345678", "\\U12345678"}, 1152 {"\\U0010Fghi", "\\U0010Fghi"}, 1153 {"\\U", "\\U"}, 1154 } 1155 for _, tc := range testCases { 1156 for _, p := range []string{"", "prefix"} { 1157 for _, s := range []string{"", "suffix"} { 1158 i := p + tc.in + s 1159 o := p + tc.out + s 1160 u := unescape(i) 1161 testutil.Eq(t, o, u, "unescaped %q into %q, but should have been %q", i, u, o) 1162 } 1163 } 1164 } 1165 } 1166 1167 func loadProtoset(path string) (*FileDescriptor, error) { 1168 var fds descriptorpb.FileDescriptorSet 1169 f, err := os.Open(path) 1170 if err != nil { 1171 return nil, err 1172 } 1173 defer f.Close() 1174 bb, err := ioutil.ReadAll(f) 1175 if err != nil { 1176 return nil, err 1177 } 1178 if err = proto.Unmarshal(bb, &fds); err != nil { 1179 return nil, err 1180 } 1181 return CreateFileDescriptorFromSet(&fds) 1182 } 1183 1184 func TestToFileDescriptorSet(t *testing.T) { 1185 fd, err := LoadFileDescriptor("desc_test2.proto") 1186 testutil.Ok(t, err, "failed to load descriptor") 1187 fdset := ToFileDescriptorSet(fd) 1188 expectedOrder := []string{ 1189 "desc_test1.proto", 1190 "pkg/desc_test_pkg.proto", 1191 "nopkg/desc_test_nopkg_new.proto", 1192 "nopkg/desc_test_nopkg.proto", 1193 "desc_test2.proto", 1194 } 1195 testutil.Eq(t, len(expectedOrder), len(fdset.File), "wrong number of files in set") 1196 for i, f := range fdset.File { 1197 testutil.Eq(t, expectedOrder[i], f.GetName(), "wrong file at index %d", i+1) 1198 expectedFile, err := LoadFileDescriptor(f.GetName()) 1199 testutil.Ok(t, err, "failed to load descriptor for %q", f.GetName()) 1200 testutil.Eq(t, expectedFile.AsFileDescriptorProto(), f) 1201 } 1202 } 1203 1204 func TestJsonCamelCase(t *testing.T) { 1205 testCases := map[string]string{ 1206 // NB: these simple test cases come from protoc's descriptor_unittest.cc: 1207 "field_name1": "fieldName1", 1208 "fieldName2": "fieldName2", 1209 "FieldName3": "FieldName3", 1210 "_field_name4": "FieldName4", 1211 "FIELD_NAME5": "FIELDNAME5", 1212 1213 // NB: these are more interesting examples; all keys were all run through 1214 // protoc and the values below are the json_name values computed by protoc 1215 // (to make sure we correctly mirror protoc behavior) 1216 "abc": "abc", 1217 "__def": "Def", 1218 "a_b_": "aB", 1219 "d_e": "dE", 1220 "abc_def": "abcDef", 1221 "c_d_e": "cDE", 1222 "_a_b_c_d": "ABCD", 1223 "a_b_c_d_e": "aBCDE", 1224 "abc1": "abc1", 1225 "__2def": "2def", 1226 "a_b_3": "aB3", 1227 "d_e4_": "dE4", 1228 "abc4_5def": "abc45def", 1229 } 1230 for k, v := range testCases { 1231 testutil.Eq(t, v, jsonCamelCase(k)) 1232 } 1233 } 1234 1235 func TestProto3Optional(t *testing.T) { 1236 fd, err := loadProtoset("../internal/testprotos/proto3_optional/desc_test_proto3_optional.protoset") 1237 testutil.Ok(t, err) 1238 md := fd.FindSymbol("MessageWithOptionalFields").(*MessageDescriptor) 1239 testutil.Eq(t, 2, len(md.GetOneOfs())) 1240 testutil.Eq(t, 2, len(md.GetFields())) 1241 for i, fld := range md.GetFields() { 1242 testutil.Require(t, fld.IsProto3Optional()) 1243 testutil.Eq(t, fld.GetOneOf(), md.GetOneOfs()[i]) 1244 testutil.Require(t, md.GetOneOfs()[i].IsSynthetic()) 1245 } 1246 fld := fd.FindSymbol("some_custom_options").(*FieldDescriptor) 1247 testutil.Require(t, fld.IsProto3Optional()) 1248 }