github.com/gogo/protobuf@v1.3.2/plugin/testgen/testgen.go (about) 1 // Protocol Buffers for Go with Gadgets 2 // 3 // Copyright (c) 2013, The GoGo Authors. All rights reserved. 4 // http://github.com/gogo/protobuf 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 /* 30 The testgen plugin generates Test and Benchmark functions for each message. 31 32 Tests are enabled using the following extensions: 33 34 - testgen 35 - testgen_all 36 37 Benchmarks are enabled using the following extensions: 38 39 - benchgen 40 - benchgen_all 41 42 Let us look at: 43 44 github.com/gogo/protobuf/test/example/example.proto 45 46 Btw all the output can be seen at: 47 48 github.com/gogo/protobuf/test/example/* 49 50 The following message: 51 52 option (gogoproto.testgen_all) = true; 53 option (gogoproto.benchgen_all) = true; 54 55 message A { 56 optional string Description = 1 [(gogoproto.nullable) = false]; 57 optional int64 Number = 2 [(gogoproto.nullable) = false]; 58 optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false]; 59 } 60 61 given to the testgen plugin, will generate the following test code: 62 63 func TestAProto(t *testing.T) { 64 popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 65 p := NewPopulatedA(popr, false) 66 dAtA, err := github_com_gogo_protobuf_proto.Marshal(p) 67 if err != nil { 68 panic(err) 69 } 70 msg := &A{} 71 if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil { 72 panic(err) 73 } 74 for i := range dAtA { 75 dAtA[i] = byte(popr.Intn(256)) 76 } 77 if err := p.VerboseEqual(msg); err != nil { 78 t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 79 } 80 if !p.Equal(msg) { 81 t.Fatalf("%#v !Proto %#v", msg, p) 82 } 83 } 84 85 func BenchmarkAProtoMarshal(b *testing.B) { 86 popr := math_rand.New(math_rand.NewSource(616)) 87 total := 0 88 pops := make([]*A, 10000) 89 for i := 0; i < 10000; i++ { 90 pops[i] = NewPopulatedA(popr, false) 91 } 92 b.ResetTimer() 93 for i := 0; i < b.N; i++ { 94 dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000]) 95 if err != nil { 96 panic(err) 97 } 98 total += len(dAtA) 99 } 100 b.SetBytes(int64(total / b.N)) 101 } 102 103 func BenchmarkAProtoUnmarshal(b *testing.B) { 104 popr := math_rand.New(math_rand.NewSource(616)) 105 total := 0 106 datas := make([][]byte, 10000) 107 for i := 0; i < 10000; i++ { 108 dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false)) 109 if err != nil { 110 panic(err) 111 } 112 datas[i] = dAtA 113 } 114 msg := &A{} 115 b.ResetTimer() 116 for i := 0; i < b.N; i++ { 117 total += len(datas[i%10000]) 118 if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { 119 panic(err) 120 } 121 } 122 b.SetBytes(int64(total / b.N)) 123 } 124 125 126 func TestAJSON(t *testing1.T) { 127 popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano())) 128 p := NewPopulatedA(popr, true) 129 jsondata, err := encoding_json.Marshal(p) 130 if err != nil { 131 panic(err) 132 } 133 msg := &A{} 134 err = encoding_json.Unmarshal(jsondata, msg) 135 if err != nil { 136 panic(err) 137 } 138 if err := p.VerboseEqual(msg); err != nil { 139 t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 140 } 141 if !p.Equal(msg) { 142 t.Fatalf("%#v !Json Equal %#v", msg, p) 143 } 144 } 145 146 func TestAProtoText(t *testing2.T) { 147 popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 148 p := NewPopulatedA(popr, true) 149 dAtA := github_com_gogo_protobuf_proto1.MarshalTextString(p) 150 msg := &A{} 151 if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil { 152 panic(err) 153 } 154 if err := p.VerboseEqual(msg); err != nil { 155 t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 156 } 157 if !p.Equal(msg) { 158 t.Fatalf("%#v !Proto %#v", msg, p) 159 } 160 } 161 162 func TestAProtoCompactText(t *testing2.T) { 163 popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano())) 164 p := NewPopulatedA(popr, true) 165 dAtA := github_com_gogo_protobuf_proto1.CompactTextString(p) 166 msg := &A{} 167 if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil { 168 panic(err) 169 } 170 if err := p.VerboseEqual(msg); err != nil { 171 t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err) 172 } 173 if !p.Equal(msg) { 174 t.Fatalf("%#v !Proto %#v", msg, p) 175 } 176 } 177 178 Other registered tests are also generated. 179 Tests are registered to this test plugin by calling the following function. 180 181 func RegisterTestPlugin(newFunc NewTestPlugin) 182 183 where NewTestPlugin is: 184 185 type NewTestPlugin func(g *generator.Generator) TestPlugin 186 187 and TestPlugin is an interface: 188 189 type TestPlugin interface { 190 Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool) 191 } 192 193 Plugins that use this interface include: 194 195 - populate 196 - gostring 197 - equal 198 - union 199 - and more 200 201 Please look at these plugins as examples of how to create your own. 202 A good idea is to let each plugin generate its own tests. 203 204 */ 205 package testgen 206 207 import ( 208 "github.com/gogo/protobuf/gogoproto" 209 "github.com/gogo/protobuf/protoc-gen-gogo/generator" 210 ) 211 212 type TestPlugin interface { 213 Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool) 214 } 215 216 type NewTestPlugin func(g *generator.Generator) TestPlugin 217 218 var testplugins = make([]NewTestPlugin, 0) 219 220 func RegisterTestPlugin(newFunc NewTestPlugin) { 221 testplugins = append(testplugins, newFunc) 222 } 223 224 type plugin struct { 225 *generator.Generator 226 generator.PluginImports 227 tests []TestPlugin 228 } 229 230 func NewPlugin() *plugin { 231 return &plugin{} 232 } 233 234 func (p *plugin) Name() string { 235 return "testgen" 236 } 237 238 func (p *plugin) Init(g *generator.Generator) { 239 p.Generator = g 240 p.tests = make([]TestPlugin, 0, len(testplugins)) 241 for i := range testplugins { 242 p.tests = append(p.tests, testplugins[i](g)) 243 } 244 } 245 246 func (p *plugin) Generate(file *generator.FileDescriptor) { 247 p.PluginImports = generator.NewPluginImports(p.Generator) 248 atLeastOne := false 249 for i := range p.tests { 250 used := p.tests[i].Generate(p.PluginImports, file) 251 if used { 252 atLeastOne = true 253 } 254 } 255 if atLeastOne { 256 p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`) 257 } 258 } 259 260 type testProto struct { 261 *generator.Generator 262 } 263 264 func newProto(g *generator.Generator) TestPlugin { 265 return &testProto{g} 266 } 267 268 func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool { 269 used := false 270 testingPkg := imports.NewImport("testing") 271 randPkg := imports.NewImport("math/rand") 272 timePkg := imports.NewImport("time") 273 protoPkg := imports.NewImport("github.com/gogo/protobuf/proto") 274 if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) { 275 protoPkg = imports.NewImport("github.com/golang/protobuf/proto") 276 } 277 for _, message := range file.Messages() { 278 ccTypeName := generator.CamelCaseSlice(message.TypeName()) 279 if message.DescriptorProto.GetOptions().GetMapEntry() { 280 continue 281 } 282 if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) { 283 used = true 284 285 p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`) 286 p.In() 287 p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`) 288 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`) 289 p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`) 290 p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`) 291 p.P(`if err != nil {`) 292 p.In() 293 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 294 p.Out() 295 p.P(`}`) 296 p.P(`msg := &`, ccTypeName, `{}`) 297 p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`) 298 p.In() 299 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 300 p.Out() 301 p.P(`}`) 302 p.P(`littlefuzz := make([]byte, len(dAtA))`) 303 p.P(`copy(littlefuzz, dAtA)`) 304 p.P(`for i := range dAtA {`) 305 p.In() 306 p.P(`dAtA[i] = byte(popr.Intn(256))`) 307 p.Out() 308 p.P(`}`) 309 if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) { 310 p.P(`if err := p.VerboseEqual(msg); err != nil {`) 311 p.In() 312 p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`) 313 p.Out() 314 p.P(`}`) 315 } 316 p.P(`if !p.Equal(msg) {`) 317 p.In() 318 p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`) 319 p.Out() 320 p.P(`}`) 321 p.P(`if len(littlefuzz) > 0 {`) 322 p.In() 323 p.P(`fuzzamount := 100`) 324 p.P(`for i := 0; i < fuzzamount; i++ {`) 325 p.In() 326 p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`) 327 p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`) 328 p.Out() 329 p.P(`}`) 330 p.P(`// shouldn't panic`) 331 p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`) 332 p.Out() 333 p.P(`}`) 334 p.Out() 335 p.P(`}`) 336 p.P() 337 } 338 339 if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) { 340 if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) { 341 p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`) 342 p.In() 343 p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`) 344 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`) 345 p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`) 346 if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) { 347 p.P(`size := p.ProtoSize()`) 348 } else { 349 p.P(`size := p.Size()`) 350 } 351 p.P(`dAtA := make([]byte, size)`) 352 p.P(`for i := range dAtA {`) 353 p.In() 354 p.P(`dAtA[i] = byte(popr.Intn(256))`) 355 p.Out() 356 p.P(`}`) 357 p.P(`_, err := p.MarshalTo(dAtA)`) 358 p.P(`if err != nil {`) 359 p.In() 360 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 361 p.Out() 362 p.P(`}`) 363 p.P(`msg := &`, ccTypeName, `{}`) 364 p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`) 365 p.In() 366 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 367 p.Out() 368 p.P(`}`) 369 p.P(`for i := range dAtA {`) 370 p.In() 371 p.P(`dAtA[i] = byte(popr.Intn(256))`) 372 p.Out() 373 p.P(`}`) 374 if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) { 375 p.P(`if err := p.VerboseEqual(msg); err != nil {`) 376 p.In() 377 p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`) 378 p.Out() 379 p.P(`}`) 380 } 381 p.P(`if !p.Equal(msg) {`) 382 p.In() 383 p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`) 384 p.Out() 385 p.P(`}`) 386 p.Out() 387 p.P(`}`) 388 p.P() 389 } 390 } 391 392 if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) { 393 used = true 394 p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`) 395 p.In() 396 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`) 397 p.P(`total := 0`) 398 p.P(`pops := make([]*`, ccTypeName, `, 10000)`) 399 p.P(`for i := 0; i < 10000; i++ {`) 400 p.In() 401 p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`) 402 p.Out() 403 p.P(`}`) 404 p.P(`b.ResetTimer()`) 405 p.P(`for i := 0; i < b.N; i++ {`) 406 p.In() 407 p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`) 408 p.P(`if err != nil {`) 409 p.In() 410 p.P(`panic(err)`) 411 p.Out() 412 p.P(`}`) 413 p.P(`total += len(dAtA)`) 414 p.Out() 415 p.P(`}`) 416 p.P(`b.SetBytes(int64(total / b.N))`) 417 p.Out() 418 p.P(`}`) 419 p.P() 420 421 p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`) 422 p.In() 423 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`) 424 p.P(`total := 0`) 425 p.P(`datas := make([][]byte, 10000)`) 426 p.P(`for i := 0; i < 10000; i++ {`) 427 p.In() 428 p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`) 429 p.P(`if err != nil {`) 430 p.In() 431 p.P(`panic(err)`) 432 p.Out() 433 p.P(`}`) 434 p.P(`datas[i] = dAtA`) 435 p.Out() 436 p.P(`}`) 437 p.P(`msg := &`, ccTypeName, `{}`) 438 p.P(`b.ResetTimer()`) 439 p.P(`for i := 0; i < b.N; i++ {`) 440 p.In() 441 p.P(`total += len(datas[i%10000])`) 442 p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`) 443 p.In() 444 p.P(`panic(err)`) 445 p.Out() 446 p.P(`}`) 447 p.Out() 448 p.P(`}`) 449 p.P(`b.SetBytes(int64(total / b.N))`) 450 p.Out() 451 p.P(`}`) 452 p.P() 453 } 454 } 455 return used 456 } 457 458 type testJson struct { 459 *generator.Generator 460 } 461 462 func newJson(g *generator.Generator) TestPlugin { 463 return &testJson{g} 464 } 465 466 func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool { 467 used := false 468 testingPkg := imports.NewImport("testing") 469 randPkg := imports.NewImport("math/rand") 470 timePkg := imports.NewImport("time") 471 jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb") 472 for _, message := range file.Messages() { 473 ccTypeName := generator.CamelCaseSlice(message.TypeName()) 474 if message.DescriptorProto.GetOptions().GetMapEntry() { 475 continue 476 } 477 if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) { 478 used = true 479 p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`) 480 p.In() 481 p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`) 482 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`) 483 p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`) 484 p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`) 485 p.P(`jsondata, err := marshaler.MarshalToString(p)`) 486 p.P(`if err != nil {`) 487 p.In() 488 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 489 p.Out() 490 p.P(`}`) 491 p.P(`msg := &`, ccTypeName, `{}`) 492 p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`) 493 p.P(`if err != nil {`) 494 p.In() 495 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 496 p.Out() 497 p.P(`}`) 498 if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) { 499 p.P(`if err := p.VerboseEqual(msg); err != nil {`) 500 p.In() 501 p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`) 502 p.Out() 503 p.P(`}`) 504 } 505 p.P(`if !p.Equal(msg) {`) 506 p.In() 507 p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`) 508 p.Out() 509 p.P(`}`) 510 p.Out() 511 p.P(`}`) 512 } 513 } 514 return used 515 } 516 517 type testText struct { 518 *generator.Generator 519 } 520 521 func newText(g *generator.Generator) TestPlugin { 522 return &testText{g} 523 } 524 525 func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool { 526 used := false 527 testingPkg := imports.NewImport("testing") 528 randPkg := imports.NewImport("math/rand") 529 timePkg := imports.NewImport("time") 530 protoPkg := imports.NewImport("github.com/gogo/protobuf/proto") 531 if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) { 532 protoPkg = imports.NewImport("github.com/golang/protobuf/proto") 533 } 534 //fmtPkg := imports.NewImport("fmt") 535 for _, message := range file.Messages() { 536 ccTypeName := generator.CamelCaseSlice(message.TypeName()) 537 if message.DescriptorProto.GetOptions().GetMapEntry() { 538 continue 539 } 540 if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) { 541 used = true 542 543 p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`) 544 p.In() 545 p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`) 546 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`) 547 p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`) 548 p.P(`dAtA := `, protoPkg.Use(), `.MarshalTextString(p)`) 549 p.P(`msg := &`, ccTypeName, `{}`) 550 p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`) 551 p.In() 552 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 553 p.Out() 554 p.P(`}`) 555 if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) { 556 p.P(`if err := p.VerboseEqual(msg); err != nil {`) 557 p.In() 558 p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`) 559 p.Out() 560 p.P(`}`) 561 } 562 p.P(`if !p.Equal(msg) {`) 563 p.In() 564 p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`) 565 p.Out() 566 p.P(`}`) 567 p.Out() 568 p.P(`}`) 569 p.P() 570 571 p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`) 572 p.In() 573 p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`) 574 p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`) 575 p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`) 576 p.P(`dAtA := `, protoPkg.Use(), `.CompactTextString(p)`) 577 p.P(`msg := &`, ccTypeName, `{}`) 578 p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`) 579 p.In() 580 p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`) 581 p.Out() 582 p.P(`}`) 583 if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) { 584 p.P(`if err := p.VerboseEqual(msg); err != nil {`) 585 p.In() 586 p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`) 587 p.Out() 588 p.P(`}`) 589 } 590 p.P(`if !p.Equal(msg) {`) 591 p.In() 592 p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`) 593 p.Out() 594 p.P(`}`) 595 p.Out() 596 p.P(`}`) 597 p.P() 598 599 } 600 } 601 return used 602 } 603 604 func init() { 605 RegisterTestPlugin(newProto) 606 RegisterTestPlugin(newJson) 607 RegisterTestPlugin(newText) 608 }