609 lines
18 KiB
Go
609 lines
18 KiB
Go
|
// Protocol Buffers for Go with Gadgets
|
||
|
//
|
||
|
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||
|
// http://github.com/gogo/protobuf
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions are
|
||
|
// met:
|
||
|
//
|
||
|
// * Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
// * Redistributions in binary form must reproduce the above
|
||
|
// copyright notice, this list of conditions and the following disclaimer
|
||
|
// in the documentation and/or other materials provided with the
|
||
|
// distribution.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
/*
|
||
|
The testgen plugin generates Test and Benchmark functions for each message.
|
||
|
|
||
|
Tests are enabled using the following extensions:
|
||
|
|
||
|
- testgen
|
||
|
- testgen_all
|
||
|
|
||
|
Benchmarks are enabled using the following extensions:
|
||
|
|
||
|
- benchgen
|
||
|
- benchgen_all
|
||
|
|
||
|
Let us look at:
|
||
|
|
||
|
github.com/gogo/protobuf/test/example/example.proto
|
||
|
|
||
|
Btw all the output can be seen at:
|
||
|
|
||
|
github.com/gogo/protobuf/test/example/*
|
||
|
|
||
|
The following message:
|
||
|
|
||
|
option (gogoproto.testgen_all) = true;
|
||
|
option (gogoproto.benchgen_all) = true;
|
||
|
|
||
|
message A {
|
||
|
optional string Description = 1 [(gogoproto.nullable) = false];
|
||
|
optional int64 Number = 2 [(gogoproto.nullable) = false];
|
||
|
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
|
||
|
}
|
||
|
|
||
|
given to the testgen plugin, will generate the following test code:
|
||
|
|
||
|
func TestAProto(t *testing.T) {
|
||
|
popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
|
||
|
p := NewPopulatedA(popr, false)
|
||
|
data, err := github_com_gogo_protobuf_proto.Marshal(p)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
msg := &A{}
|
||
|
if err := github_com_gogo_protobuf_proto.Unmarshal(data, msg); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
for i := range data {
|
||
|
data[i] = byte(popr.Intn(256))
|
||
|
}
|
||
|
if err := p.VerboseEqual(msg); err != nil {
|
||
|
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
|
||
|
}
|
||
|
if !p.Equal(msg) {
|
||
|
t.Fatalf("%#v !Proto %#v", msg, p)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkAProtoMarshal(b *testing.B) {
|
||
|
popr := math_rand.New(math_rand.NewSource(616))
|
||
|
total := 0
|
||
|
pops := make([]*A, 10000)
|
||
|
for i := 0; i < 10000; i++ {
|
||
|
pops[i] = NewPopulatedA(popr, false)
|
||
|
}
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
data, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000])
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
total += len(data)
|
||
|
}
|
||
|
b.SetBytes(int64(total / b.N))
|
||
|
}
|
||
|
|
||
|
func BenchmarkAProtoUnmarshal(b *testing.B) {
|
||
|
popr := math_rand.New(math_rand.NewSource(616))
|
||
|
total := 0
|
||
|
datas := make([][]byte, 10000)
|
||
|
for i := 0; i < 10000; i++ {
|
||
|
data, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false))
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
datas[i] = data
|
||
|
}
|
||
|
msg := &A{}
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
total += len(datas[i%10000])
|
||
|
if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|
||
|
b.SetBytes(int64(total / b.N))
|
||
|
}
|
||
|
|
||
|
|
||
|
func TestAJSON(t *testing1.T) {
|
||
|
popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano()))
|
||
|
p := NewPopulatedA(popr, true)
|
||
|
jsondata, err := encoding_json.Marshal(p)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
msg := &A{}
|
||
|
err = encoding_json.Unmarshal(jsondata, msg)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
if err := p.VerboseEqual(msg); err != nil {
|
||
|
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
|
||
|
}
|
||
|
if !p.Equal(msg) {
|
||
|
t.Fatalf("%#v !Json Equal %#v", msg, p)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAProtoText(t *testing2.T) {
|
||
|
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
|
||
|
p := NewPopulatedA(popr, true)
|
||
|
data := github_com_gogo_protobuf_proto1.MarshalTextString(p)
|
||
|
msg := &A{}
|
||
|
if err := github_com_gogo_protobuf_proto1.UnmarshalText(data, msg); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
if err := p.VerboseEqual(msg); err != nil {
|
||
|
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
|
||
|
}
|
||
|
if !p.Equal(msg) {
|
||
|
t.Fatalf("%#v !Proto %#v", msg, p)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAProtoCompactText(t *testing2.T) {
|
||
|
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
|
||
|
p := NewPopulatedA(popr, true)
|
||
|
data := github_com_gogo_protobuf_proto1.CompactTextString(p)
|
||
|
msg := &A{}
|
||
|
if err := github_com_gogo_protobuf_proto1.UnmarshalText(data, msg); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
if err := p.VerboseEqual(msg); err != nil {
|
||
|
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
|
||
|
}
|
||
|
if !p.Equal(msg) {
|
||
|
t.Fatalf("%#v !Proto %#v", msg, p)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Other registered tests are also generated.
|
||
|
Tests are registered to this test plugin by calling the following function.
|
||
|
|
||
|
func RegisterTestPlugin(newFunc NewTestPlugin)
|
||
|
|
||
|
where NewTestPlugin is:
|
||
|
|
||
|
type NewTestPlugin func(g *generator.Generator) TestPlugin
|
||
|
|
||
|
and TestPlugin is an interface:
|
||
|
|
||
|
type TestPlugin interface {
|
||
|
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
|
||
|
}
|
||
|
|
||
|
Plugins that use this interface include:
|
||
|
|
||
|
- populate
|
||
|
- gostring
|
||
|
- equal
|
||
|
- union
|
||
|
- and more
|
||
|
|
||
|
Please look at these plugins as examples of how to create your own.
|
||
|
A good idea is to let each plugin generate its own tests.
|
||
|
|
||
|
*/
|
||
|
package testgen
|
||
|
|
||
|
import (
|
||
|
"github.com/gogo/protobuf/gogoproto"
|
||
|
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
|
||
|
)
|
||
|
|
||
|
type TestPlugin interface {
|
||
|
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
|
||
|
}
|
||
|
|
||
|
type NewTestPlugin func(g *generator.Generator) TestPlugin
|
||
|
|
||
|
var testplugins = make([]NewTestPlugin, 0)
|
||
|
|
||
|
func RegisterTestPlugin(newFunc NewTestPlugin) {
|
||
|
testplugins = append(testplugins, newFunc)
|
||
|
}
|
||
|
|
||
|
type plugin struct {
|
||
|
*generator.Generator
|
||
|
generator.PluginImports
|
||
|
tests []TestPlugin
|
||
|
}
|
||
|
|
||
|
func NewPlugin() *plugin {
|
||
|
return &plugin{}
|
||
|
}
|
||
|
|
||
|
func (p *plugin) Name() string {
|
||
|
return "testgen"
|
||
|
}
|
||
|
|
||
|
func (p *plugin) Init(g *generator.Generator) {
|
||
|
p.Generator = g
|
||
|
p.tests = make([]TestPlugin, 0, len(testplugins))
|
||
|
for i := range testplugins {
|
||
|
p.tests = append(p.tests, testplugins[i](g))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (p *plugin) Generate(file *generator.FileDescriptor) {
|
||
|
p.PluginImports = generator.NewPluginImports(p.Generator)
|
||
|
atLeastOne := false
|
||
|
for i := range p.tests {
|
||
|
used := p.tests[i].Generate(p.PluginImports, file)
|
||
|
if used {
|
||
|
atLeastOne = true
|
||
|
}
|
||
|
}
|
||
|
if atLeastOne {
|
||
|
p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type testProto struct {
|
||
|
*generator.Generator
|
||
|
}
|
||
|
|
||
|
func newProto(g *generator.Generator) TestPlugin {
|
||
|
return &testProto{g}
|
||
|
}
|
||
|
|
||
|
func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
|
||
|
used := false
|
||
|
testingPkg := imports.NewImport("testing")
|
||
|
randPkg := imports.NewImport("math/rand")
|
||
|
timePkg := imports.NewImport("time")
|
||
|
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
|
||
|
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
|
||
|
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
|
||
|
}
|
||
|
for _, message := range file.Messages() {
|
||
|
ccTypeName := generator.CamelCaseSlice(message.TypeName())
|
||
|
if message.DescriptorProto.GetOptions().GetMapEntry() {
|
||
|
continue
|
||
|
}
|
||
|
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
used = true
|
||
|
|
||
|
p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`)
|
||
|
p.In()
|
||
|
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
|
||
|
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
|
||
|
p.P(`data, err := `, protoPkg.Use(), `.Marshal(p)`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(data, msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`littlefuzz := make([]byte, len(data))`)
|
||
|
p.P(`copy(littlefuzz, data)`)
|
||
|
p.P(`for i := range data {`)
|
||
|
p.In()
|
||
|
p.P(`data[i] = byte(popr.Intn(256))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.P(`if !p.Equal(msg) {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`if len(littlefuzz) > 0 {`)
|
||
|
p.In()
|
||
|
p.P(`fuzzamount := 100`)
|
||
|
p.P(`for i := 0; i < fuzzamount; i++ {`)
|
||
|
p.In()
|
||
|
p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`)
|
||
|
p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`// shouldn't panic`)
|
||
|
p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
}
|
||
|
|
||
|
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`)
|
||
|
p.In()
|
||
|
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
|
||
|
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
|
||
|
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`size := p.ProtoSize()`)
|
||
|
} else {
|
||
|
p.P(`size := p.Size()`)
|
||
|
}
|
||
|
p.P(`data := make([]byte, size)`)
|
||
|
p.P(`for i := range data {`)
|
||
|
p.In()
|
||
|
p.P(`data[i] = byte(popr.Intn(256))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`_, err := p.MarshalTo(data)`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(data, msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`for i := range data {`)
|
||
|
p.In()
|
||
|
p.P(`data[i] = byte(popr.Intn(256))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.P(`if !p.Equal(msg) {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
used = true
|
||
|
p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`)
|
||
|
p.In()
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
|
||
|
p.P(`total := 0`)
|
||
|
p.P(`pops := make([]*`, ccTypeName, `, 10000)`)
|
||
|
p.P(`for i := 0; i < 10000; i++ {`)
|
||
|
p.In()
|
||
|
p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`b.ResetTimer()`)
|
||
|
p.P(`for i := 0; i < b.N; i++ {`)
|
||
|
p.In()
|
||
|
p.P(`data, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`panic(err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`total += len(data)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`b.SetBytes(int64(total / b.N))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
|
||
|
p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`)
|
||
|
p.In()
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
|
||
|
p.P(`total := 0`)
|
||
|
p.P(`datas := make([][]byte, 10000)`)
|
||
|
p.P(`for i := 0; i < 10000; i++ {`)
|
||
|
p.In()
|
||
|
p.P(`data, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`panic(err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`datas[i] = data`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`b.ResetTimer()`)
|
||
|
p.P(`for i := 0; i < b.N; i++ {`)
|
||
|
p.In()
|
||
|
p.P(`total += len(datas[i%10000])`)
|
||
|
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`panic(err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`b.SetBytes(int64(total / b.N))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
}
|
||
|
}
|
||
|
return used
|
||
|
}
|
||
|
|
||
|
type testJson struct {
|
||
|
*generator.Generator
|
||
|
}
|
||
|
|
||
|
func newJson(g *generator.Generator) TestPlugin {
|
||
|
return &testJson{g}
|
||
|
}
|
||
|
|
||
|
func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
|
||
|
used := false
|
||
|
testingPkg := imports.NewImport("testing")
|
||
|
randPkg := imports.NewImport("math/rand")
|
||
|
timePkg := imports.NewImport("time")
|
||
|
jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb")
|
||
|
for _, message := range file.Messages() {
|
||
|
ccTypeName := generator.CamelCaseSlice(message.TypeName())
|
||
|
if message.DescriptorProto.GetOptions().GetMapEntry() {
|
||
|
continue
|
||
|
}
|
||
|
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
used = true
|
||
|
p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`)
|
||
|
p.In()
|
||
|
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
|
||
|
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
|
||
|
p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`)
|
||
|
p.P(`jsondata, err := marshaler.MarshalToString(p)`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.P(`if !p.Equal(msg) {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
}
|
||
|
return used
|
||
|
}
|
||
|
|
||
|
type testText struct {
|
||
|
*generator.Generator
|
||
|
}
|
||
|
|
||
|
func newText(g *generator.Generator) TestPlugin {
|
||
|
return &testText{g}
|
||
|
}
|
||
|
|
||
|
func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
|
||
|
used := false
|
||
|
testingPkg := imports.NewImport("testing")
|
||
|
randPkg := imports.NewImport("math/rand")
|
||
|
timePkg := imports.NewImport("time")
|
||
|
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
|
||
|
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
|
||
|
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
|
||
|
}
|
||
|
//fmtPkg := imports.NewImport("fmt")
|
||
|
for _, message := range file.Messages() {
|
||
|
ccTypeName := generator.CamelCaseSlice(message.TypeName())
|
||
|
if message.DescriptorProto.GetOptions().GetMapEntry() {
|
||
|
continue
|
||
|
}
|
||
|
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
used = true
|
||
|
|
||
|
p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`)
|
||
|
p.In()
|
||
|
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
|
||
|
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
|
||
|
p.P(`data := `, protoPkg.Use(), `.MarshalTextString(p)`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(data, msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.P(`if !p.Equal(msg) {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
|
||
|
p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`)
|
||
|
p.In()
|
||
|
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
|
||
|
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
|
||
|
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
|
||
|
p.P(`data := `, protoPkg.Use(), `.CompactTextString(p)`)
|
||
|
p.P(`msg := &`, ccTypeName, `{}`)
|
||
|
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(data, msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.P(`if !p.Equal(msg) {`)
|
||
|
p.In()
|
||
|
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
|
||
|
}
|
||
|
}
|
||
|
return used
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
RegisterTestPlugin(newProto)
|
||
|
RegisterTestPlugin(newJson)
|
||
|
RegisterTestPlugin(newText)
|
||
|
}
|