diff --git a/Makefile b/Makefile index 6b1f875..a9fcafc 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ BINARY=ptg GOBUILD=go build -ldflags "-s -w" -o ${BINARY} GOCLEAN=go clean RMTARGZ=rm -rf *.gz -VERSION=0.0.1 +VERSION=0.0.2 # Build build: @@ -39,4 +39,16 @@ release: $(GOCLEAN) CGO_ENABLED=0 GOOS=windows GOARCH=amd64 $(GOBUILD).exe tar czvf ${BINARY}-win64-${VERSION}.tar.gz ./${BINARY}.exe - $(GOCLEAN) \ No newline at end of file + $(GOCLEAN) + + +gen-go-proto: + @protoc --go_out=. --go_opt=paths=source_relative \ + --go-grpc_out=. --go-grpc_opt=paths=source_relative \ + reflect/gen/user.proto + +pkg-win: + fyne package -os windows -src gui/ -icon pic/gopher.png -name ${BINARY} -appVersion $(VERSION) + +pkg-macos: + fyne package -os darwin -src gui/ -icon pic/gopher.png -name ${BINARY} -appVersion $(VERSION) \ No newline at end of file diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..c4afe89 --- /dev/null +++ b/client/client.go @@ -0,0 +1,38 @@ +package client + +import ( + "github.com/crossoverJie/ptg/meta" + "net/http" + "time" +) + +type ( + Client interface { + Request() (*meta.Response, error) + } +) + +const ( + Http = "http" + Grpc = "grpc" +) + +func NewClient(method, url, requestBody string, meta *meta.Meta) Client { + if meta.Protocol() == Http { + return &httpClient{ + Method: method, + Url: url, + RequestBody: requestBody, + httpClient: &http.Client{ + Transport: &http.Transport{ + ResponseHeaderTimeout: time.Millisecond * time.Duration(1000), + DisableKeepAlives: true, + }, + }, + meta: meta, + } + } else { + return NewGrpcClient(meta) + } + +} diff --git a/client/grpc_client.go b/client/grpc_client.go new file mode 100644 index 0000000..73016b1 --- /dev/null +++ b/client/grpc_client.go @@ -0,0 +1,79 @@ +package client + +import ( + "context" + "fmt" + "github.com/crossoverJie/ptg/meta" + "github.com/crossoverJie/ptg/reflect" + "github.com/jhump/protoreflect/desc" + "github.com/jhump/protoreflect/dynamic/grpcdynamic" + "google.golang.org/grpc" + "sync" + "time" +) + +var ( + one sync.Once + g *grpcClient +) + +type grpcClient struct { + stub grpcdynamic.Stub + mds *desc.MethodDescriptor + meta *meta.Meta + parseReflect *reflect.ParseReflect +} + +func NewGrpcClient(meta *meta.Meta) Client { + one.Do(func() { + if g == nil { + var ( + opts []grpc.DialOption + ) + + g = &grpcClient{ + meta: meta, + } + opts = append(opts, grpc.WithInsecure()) + conn, err := grpc.DialContext(context.Background(), meta.Target(), opts...) + if err != nil { + panic(fmt.Sprintf("create grpc connection err %v", err)) + } + g.stub = grpcdynamic.NewStub(conn) + + parse, err := reflect.NewParse(meta.ProtocolFile()) + if err != nil { + panic(fmt.Sprintf("create grpc parse reflect err %v", err)) + } + g.parseReflect = parse + serviceName, methodName, err := reflect.ParseServiceMethod(meta.Fqn()) + if err != nil { + panic(fmt.Sprintf("parse MethodDescriptor err %v", err)) + } + g.mds, err = g.parseReflect.MethodDescriptor(serviceName, methodName) + if err != nil { + panic(fmt.Sprintf("create grpc MethodDescriptor err %v", err)) + } + + } + }) + return g +} + +func (g *grpcClient) Request() (*meta.Response, error) { + //fmt.Printf("%p \n", &*g)\ + start := time.Now() + rpc, err := g.parseReflect.InvokeRpc(context.Background(), g.stub, g.mds, g.meta.Body()) + r := &meta.Response{ + RequestTime: time.Since(start), + } + //SlowRequestTime = r.slowRequest() + //FastRequestTime = r.fastRequest() + meta.GetResult().SetSlowRequestTime(r.SlowRequest()). + SetFastRequestTime(r.FastRequest()) + if err != nil { + return nil, err + } + r.ResponseSize = len(rpc.String()) + return r, nil +} diff --git a/client.go b/client/http_client.go similarity index 51% rename from client.go rename to client/http_client.go index 9a90324..bd87b73 100644 --- a/client.go +++ b/client/http_client.go @@ -1,8 +1,9 @@ -package main +package client import ( - "errors" "fmt" + "github.com/crossoverJie/ptg/meta" + "github.com/pkg/errors" "io" "io/ioutil" "net/http" @@ -10,44 +11,15 @@ import ( "time" ) -type ( - Client interface { - Request() (*Response, error) - } - - httpClient struct { - Method string - Url string - RequestBody string - httpClient *http.Client - } - - Response struct { - RequestTime time.Duration - ResponseSize int - } -) - -func NewClient(method, url, requestBody string) Client { - if protocol == Http { - return &httpClient{ - Method: method, - Url: url, - RequestBody: requestBody, - httpClient: &http.Client{ - Transport: &http.Transport{ - ResponseHeaderTimeout: time.Millisecond * time.Duration(1000), - DisableKeepAlives: true, - }, - }, - } - } else { - return NewGrpcClient() - } - +type httpClient struct { + Method string + Url string + RequestBody string + httpClient *http.Client + meta *meta.Meta } -func (c *httpClient) Request() (*Response, error) { +func (c *httpClient) Request() (*meta.Response, error) { var payload io.Reader if len(c.RequestBody) > 0 { payload = strings.NewReader(`{"name":"abc"}`) @@ -59,7 +31,7 @@ func (c *httpClient) Request() (*Response, error) { return nil, err } req.Header.Add("User-Agent", "ptg") - for k, v := range headerMap { + for k, v := range c.meta.HeaderMap() { req.Header.Add(k, v) } @@ -72,11 +44,13 @@ func (c *httpClient) Request() (*Response, error) { start := time.Now() response, err := c.httpClient.Do(req) - r := &Response{ + r := &meta.Response{ RequestTime: time.Since(start), } - SlowRequestTime = r.slowRequest() - FastRequestTime = r.fastRequest() + //SlowRequestTime = r.slowRequest() + //FastRequestTime = r.fastRequest() + meta.GetResult().SetSlowRequestTime(r.SlowRequest()). + SetFastRequestTime(r.FastRequest()) if err != nil { return nil, err } @@ -100,16 +74,3 @@ func (c *httpClient) Request() (*Response, error) { r.ResponseSize = len(body) return r, nil } - -func (r *Response) fastRequest() time.Duration { - if r.RequestTime < FastRequestTime { - return r.RequestTime - } - return FastRequestTime -} -func (r *Response) slowRequest() time.Duration { - if r.RequestTime > SlowRequestTime { - return r.RequestTime - } - return SlowRequestTime -} diff --git a/client_test.go b/client/http_client_test.go similarity index 50% rename from client_test.go rename to client/http_client_test.go index d34b664..bbf3298 100644 --- a/client_test.go +++ b/client/http_client_test.go @@ -1,21 +1,18 @@ -package main +package client import ( "fmt" + "github.com/crossoverJie/ptg/meta" "github.com/docker/go-units" "testing" ) -func Test_client_Request(t *testing.T) { - httpClient := NewClient("GET", "http://gobyexample.com", "") - request, err := httpClient.Request() - if err != nil { - fmt.Println(err) - } - fmt.Println(request) -} -func Test_client_Request2(t *testing.T) { - httpClient := NewClient("POST", "http://localhost:8080/post", `{"name":"abc"}`) +func Test_httpClient_Request(t *testing.T) { + meta.NewResult() + httpClient := NewClient("GET", + "http://gobyexample.com", "", + meta.NewMeta("http://gobyexample.com", "GET", "", "", Http, "", + "", 1, 1, nil, nil)) request, err := httpClient.Request() if err != nil { fmt.Println(err) diff --git a/count.go b/count.go index fbca934..5110877 100644 --- a/count.go +++ b/count.go @@ -1,35 +1,39 @@ package main import ( + ptgclient "github.com/crossoverJie/ptg/client" + "github.com/crossoverJie/ptg/meta" + "github.com/crossoverJie/ptg/model" "github.com/docker/go-units" "github.com/fatih/color" "os" "sync" - "sync/atomic" "time" ) type CountModel struct { wait sync.WaitGroup count int - workCh chan *Job + workCh chan *model.Job start time.Time + result *meta.Result + meta *meta.Meta } -func NewCountModel(count int) Model { - return &CountModel{count: count, start: time.Now()} +func NewCountModel(count int) model.Model { + return &CountModel{count: count, start: time.Now(), result: meta.GetResult(), meta: meta.GetMeta()} } func (c *CountModel) Init() { c.wait.Add(c.count) - c.workCh = make(chan *Job, c.count) + c.workCh = make(chan *model.Job, c.count) for i := 0; i < c.count; i++ { go func() { - c.workCh <- &Job{ - thread: thread, - duration: duration, - count: c.count, - target: target, + c.workCh <- &model.Job{ + Thread: thread, + Duration: duration, + Count: c.count, + Target: target, } }() } @@ -43,12 +47,13 @@ func (c *CountModel) Run() { if !ok { return } - httpClient := NewClient(method, job.target, body) + httpClient := ptgclient.NewClient(method, job.Target, body, c.meta) response, err := httpClient.Request() - respCh <- response + c.meta.RespCh() <- response if err != nil { color.Red("request err %v\n", err) - atomic.AddInt32(&ErrorCount, 1) + //atomic.AddInt32(&ErrorCount, 1) + c.result.IncrementErrorCount() } Bar.Increment() c.wait.Done() @@ -62,10 +67,12 @@ func (c *CountModel) Run() { func (c *CountModel) Finish() { for i := 0; i < c.count; i++ { select { - case res := <-respCh: + case res := <-c.meta.RespCh(): if res != nil { - totalRequestTime += res.RequestTime - totalResponseSize += res.ResponseSize + //totalRequestTime += res.RequestTime + //totalResponseSize += res.ResponseSize + meta.GetResult().SetTotalRequestTime(res.RequestTime). + SetTotalResponseSize(res.ResponseSize) } } } @@ -79,9 +86,9 @@ func (c *CountModel) Shutdown() { } func (c *CountModel) PrintSate() { - color.Green("%v requests in %v, %v read, and cost %v.\n", c.count, units.HumanDuration(totalRequestTime), units.HumanSize(float64(totalResponseSize)), units.HumanDuration(time.Since(c.start))) - color.Green("Avg Req Time:\t\t%v\n", totalRequestTime/time.Duration(c.count)) - color.Green("Fastest Request:\t%v\n", FastRequestTime) - color.Green("Slowest Request:\t%v\n", SlowRequestTime) - color.Green("Number of Errors:\t%v\n", ErrorCount) + color.Green("%v requests in %v, %v read, and cost %v.\n", c.count, units.HumanDuration(c.result.TotalRequestTime()), units.HumanSize(float64(c.result.TotalResponseSize())), units.HumanDuration(time.Since(c.start))) + color.Green("Avg Req Time:\t\t%v\n", c.result.TotalRequestTime()/time.Duration(c.count)) + color.Green("Fastest Request:\t%v\n", c.result.FastRequestTime()) + color.Green("Slowest Request:\t%v\n", c.result.SlowRequestTime()) + color.Green("Number of Errors:\t%v\n", c.result.ErrorCount()) } diff --git a/duration.go b/duration.go index 919f675..0833f7b 100644 --- a/duration.go +++ b/duration.go @@ -2,6 +2,9 @@ package main import ( "fmt" + ptgclient "github.com/crossoverJie/ptg/client" + "github.com/crossoverJie/ptg/meta" + "github.com/crossoverJie/ptg/model" "github.com/docker/go-units" "github.com/fatih/color" "sync/atomic" @@ -14,13 +17,17 @@ type DurationModel struct { close chan struct{} totalRequest int32 shutdown int32 + result *meta.Result + meta *meta.Meta } -func NewDurationModel(duration int64) Model { +func NewDurationModel(duration int64) model.Model { return &DurationModel{ duration: duration, timeCh: make(chan struct{}), close: make(chan struct{}), + result: meta.GetResult(), + meta: meta.GetMeta(), } } @@ -52,13 +59,14 @@ func (c *DurationModel) Run() { if atomic.LoadInt32(&c.shutdown) == 1 { return } - httpClient := NewClient(method, target, body) - response, err := httpClient.Request() + ptgClient := ptgclient.NewClient(method, target, body, c.meta) + response, err := ptgClient.Request() atomic.AddInt32(&c.totalRequest, 1) - respCh <- response + c.meta.RespCh() <- response if err != nil { color.Red("request err %v\n", err) - atomic.AddInt32(&ErrorCount, 1) + //atomic.AddInt32(&ErrorCount, 1) + c.result.IncrementErrorCount() } } }() @@ -74,10 +82,12 @@ func (c *DurationModel) Finish() { atomic.StoreInt32(&c.shutdown, 1) return } - case res := <-respCh: + case res := <-c.meta.RespCh(): if res != nil { - totalRequestTime += res.RequestTime - totalResponseSize += res.ResponseSize + //totalRequestTime += res.RequestTime + //totalResponseSize += res.ResponseSize + c.result.SetTotalRequestTime(res.RequestTime). + SetTotalResponseSize(res.ResponseSize) } } } @@ -89,9 +99,9 @@ func (c *DurationModel) Shutdown() { func (c *DurationModel) PrintSate() { fmt.Println("") - color.Green("%v requests in %v, %v read.\n", c.totalRequest, units.HumanDuration(totalRequestTime), units.HumanSize(float64(totalResponseSize))) - color.Green("Avg Req Time:\t\t%v\n", totalRequestTime/time.Duration(c.totalRequest)) - color.Green("Fastest Request:\t%v\n", FastRequestTime) - color.Green("Slowest Request:\t%v\n", SlowRequestTime) - color.Green("Number of Errors:\t%v\n", ErrorCount) + color.Green("%v requests in %v, %v read.\n", c.totalRequest, units.HumanDuration(c.result.TotalRequestTime()), units.HumanSize(float64(c.result.TotalResponseSize()))) + color.Green("Avg Req Time:\t\t%v\n", c.result.TotalRequestTime()/time.Duration(c.totalRequest)) + color.Green("Fastest Request:\t%v\n", c.result.FastRequestTime()) + color.Green("Slowest Request:\t%v\n", c.result.SlowRequestTime()) + color.Green("Number of Errors:\t%v\n", c.result.ErrorCount()) } diff --git a/go.mod b/go.mod index 6e7ce53..3d13eda 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,14 @@ module github.com/crossoverJie/ptg go 1.16 require ( + fyne.io/fyne/v2 v2.1.1 github.com/cheggaaa/pb/v3 v3.0.5 github.com/docker/go-units v0.4.0 github.com/fatih/color v1.13.0 - github.com/golang/protobuf v1.4.2 // indirect + github.com/golang/protobuf v1.5.2 github.com/jhump/protoreflect v1.10.1 + github.com/pkg/errors v0.9.1 github.com/urfave/cli/v2 v2.3.0 - google.golang.org/grpc v1.27.0 + google.golang.org/grpc v1.38.0 + google.golang.org/protobuf v1.27.1 ) diff --git a/go.sum b/go.sum index 57affbb..e39e55b 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,48 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +fyne.io/fyne/v2 v2.1.1 h1:3p39SwQ/rBiYODVYI4ggTuwMufWYmqaRMJvXTFg7jSw= +fyne.io/fyne/v2 v2.1.1/go.mod h1:c1vwI38Ebd0dAdxVa6H1Pj6/+cK1xtDy61+I31g+s14= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE= github.com/cheggaaa/pb/v3 v3.0.5/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA= +github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUvMTGHnXf/6OExw/Dz2ivDj48nVg7Lg8= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f h1:s0O46d8fPwk9kU4k1jj76wBquMVETx7uveQD9MCIQoU= +github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb h1:T6gaWBvRzJjuOrdCtg8fXXjKai2xSDqWTcKFUPuw8Tw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -26,22 +53,33 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526 h1:NfuKjkj/Xc2z1xZIj+EmNCm5p1nKJPyw3F4E20usXvg= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= github.com/jhump/protoreflect v1.10.1 h1:iH+UZfsbRE6vpyZH7asAjTPWJf7RJbpZ9j/N3lDlKs0= github.com/jhump/protoreflect v1.10.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca h1:ozPUX9TKQZVek4lZWYRsQo7uS8vJ+q4OOHvRhHiCLfU= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b h1:tLSDWcFhT0WRlnsFszh4iaFTexWF8mmccGTk88Siq7Q= +github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -51,7 +89,14 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -60,21 +105,38 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.3.8 h1:Nw158Q8QN+CPgTmVRByhVwapp8Mm1e2blinhmx4wx5E= +github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -82,25 +144,35 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -109,10 +181,13 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -121,8 +196,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaR google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -131,12 +208,21 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12 h1:OwhZOOMuf7leLaSCuxtQ9FW7ui2L2L6UKOtKAUqovUQ= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= diff --git a/grpc_client.go b/grpc_client.go deleted file mode 100644 index 2a43aa5..0000000 --- a/grpc_client.go +++ /dev/null @@ -1,208 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "github.com/golang/protobuf/jsonpb" - "github.com/jhump/protoreflect/desc" - "github.com/jhump/protoreflect/desc/protoparse" - "github.com/jhump/protoreflect/dynamic" - "github.com/jhump/protoreflect/dynamic/grpcdynamic" - "google.golang.org/grpc" - "path/filepath" - "strings" - "sync" - "time" -) - -var errNoMethodNameSpecified = errors.New("no method name specified") - -var ( - one sync.Once - client *grpcClient -) - -type grpcClient struct { - stub grpcdynamic.Stub - mtd *desc.MethodDescriptor - message []*dynamic.Message -} - -func NewGrpcClient() Client { - one.Do(func() { - if client == nil { - var ( - opts []grpc.DialOption - importPath []string - ) - - client = &grpcClient{} - opts = append(opts, grpc.WithInsecure()) - conn, err := grpc.DialContext(context.Background(), target, opts...) - if err != nil { - panic(fmt.Sprintf("create grpc connection err %v", err)) - } - client.stub = grpcdynamic.NewStub(conn) - - dir := filepath.Dir(protocolFile) - importPath = append(importPath, dir) - client.mtd, err = GetMethodDescFromProto(fqn, protocolFile, importPath) - if err != nil { - panic(fmt.Sprintf("create grpc MethodDescriptor err %v", err)) - } - - client.message, err = getDataForCall(client.mtd) - if err != nil { - panic(fmt.Sprintf("create grpc message err %v", err)) - } - - } - }) - return client -} - -func (g *grpcClient) Request() (*Response, error) { - //fmt.Printf("%p \n", &*g)\ - start := time.Now() - rpc, err := g.stub.InvokeRpc(context.Background(), g.mtd, g.message[0]) - r := &Response{ - RequestTime: time.Since(start), - } - SlowRequestTime = r.slowRequest() - FastRequestTime = r.fastRequest() - if err != nil { - return nil, err - } - r.ResponseSize = len(rpc.String()) - return r, nil -} - -func GetMethodDescFromProto(call, proto string, imports []string) (*desc.MethodDescriptor, error) { - p := &protoparse.Parser{ImportPaths: imports} - - filename := proto - if filepath.IsAbs(filename) { - filename = filepath.Base(proto) - } - - fds, err := p.ParseFiles(filename) - if err != nil { - return nil, err - } - - fileDesc := fds[0] - - files := map[string]*desc.FileDescriptor{} - files[fileDesc.GetName()] = fileDesc - - return getMethodDesc(call, files) -} - -func getMethodDesc(call string, files map[string]*desc.FileDescriptor) (*desc.MethodDescriptor, error) { - svc, mth, err := parseServiceMethod(call) - if err != nil { - return nil, err - } - - dsc, err := findServiceSymbol(files, svc) - if err != nil { - return nil, err - } - if dsc == nil { - return nil, fmt.Errorf("cannot find service %q", svc) - } - - sd, ok := dsc.(*desc.ServiceDescriptor) - if !ok { - return nil, fmt.Errorf("cannot find service %q", svc) - } - - mtd := sd.FindMethodByName(mth) - if mtd == nil { - return nil, fmt.Errorf("service %q does not include a method named %q", svc, mth) - } - - return mtd, nil -} - -func parseServiceMethod(svcAndMethod string) (string, string, error) { - if len(svcAndMethod) == 0 { - return "", "", errNoMethodNameSpecified - } - if svcAndMethod[0] == '.' { - svcAndMethod = svcAndMethod[1:] - } - if len(svcAndMethod) == 0 { - return "", "", errNoMethodNameSpecified - } - switch strings.Count(svcAndMethod, "/") { - case 0: - pos := strings.LastIndex(svcAndMethod, ".") - if pos < 0 { - return "", "", newInvalidMethodNameError(svcAndMethod) - } - return svcAndMethod[:pos], svcAndMethod[pos+1:], nil - case 1: - split := strings.Split(svcAndMethod, "/") - return split[0], split[1], nil - default: - return "", "", newInvalidMethodNameError(svcAndMethod) - } -} - -func newInvalidMethodNameError(svcAndMethod string) error { - return fmt.Errorf("method name must be package.Service.Method or package.Service/Method: %q", svcAndMethod) -} - -func findServiceSymbol(resolved map[string]*desc.FileDescriptor, fullyQualifiedName string) (desc.Descriptor, error) { - for _, fd := range resolved { - if dsc := fd.FindSymbol(fullyQualifiedName); dsc != nil { - return dsc, nil - } - } - return nil, fmt.Errorf("cannot find service %q", fullyQualifiedName) -} - -func getDataForCall(mtd *desc.MethodDescriptor) ([]*dynamic.Message, error) { - var inputs []*dynamic.Message - var err error - if inputs, err = getPayloadMessages([]byte(body), mtd); err != nil { - return nil, err - } - - if len(inputs) > 0 { - unaryInput := inputs[0] - - return []*dynamic.Message{unaryInput}, nil - } - - return inputs, nil -} - -func getPayloadMessages(inputData []byte, mtd *desc.MethodDescriptor) ([]*dynamic.Message, error) { - var inputs []*dynamic.Message - data := inputData - inputs, err := createPayloadsFromJSON(mtd, string(data)) - if err != nil { - return nil, err - } - - return inputs, nil -} - -func createPayloadsFromJSON(mtd *desc.MethodDescriptor, data string) ([]*dynamic.Message, error) { - md := mtd.GetInputType() - var inputs []*dynamic.Message - - if len(data) > 0 { - inputs = make([]*dynamic.Message, 1) - inputs[0] = dynamic.NewMessage(md) - err := jsonpb.UnmarshalString(data, inputs[0]) - if err != nil { - return nil, errors.New(fmt.Sprintf("create payload json err %v \n", err)) - } - } - - return inputs, nil -} diff --git a/grpc_client_test.go b/grpc_client_test.go deleted file mode 100644 index 5f34e56..0000000 --- a/grpc_client_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "testing" - -func TestRequest(t *testing.T) { - //Request() -} diff --git a/gui/app.go b/gui/app.go new file mode 100644 index 0000000..a7592e1 --- /dev/null +++ b/gui/app.go @@ -0,0 +1,44 @@ +package main + +const ( + AppName = "PTG gRPC client" + AppWeight = 1000 + AppHeight = 500 + HelpUrl = "https://github.com/crossoverJie/ptg" + RequestEntryPlaceHolder = "Input request json" + TargetInputText = "127.0.0.1:6001" + RequestButtonText = "RUN" + ResponseLabelText = "Response:" +) + +type App struct { + AppName string + AppWidth, AppHeight float32 + HelpUrl string + RightRequest *RightRequest + RightResponse *RightResponse +} + +type RightRequest struct { + RequestEntryPlaceHolder, TargetInputText string + RequestButtonText string +} + +type RightResponse struct { + ResponseLabelText string +} + +func InitApp() *App { + return &App{ + AppName: AppName, + AppWidth: AppWeight, + AppHeight: AppHeight, + HelpUrl: HelpUrl, + RightRequest: &RightRequest{ + RequestEntryPlaceHolder: RequestEntryPlaceHolder, + TargetInputText: TargetInputText, + RequestButtonText: RequestButtonText, + }, + RightResponse: &RightResponse{ResponseLabelText: ResponseLabelText}, + } +} diff --git a/gui/main.go b/gui/main.go new file mode 100644 index 0000000..6a815fd --- /dev/null +++ b/gui/main.go @@ -0,0 +1,197 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/dialog" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" + "github.com/crossoverJie/ptg/reflect" + _ "github.com/crossoverJie/ptg/reflect" + "github.com/jhump/protoreflect/dynamic/grpcdynamic" + "google.golang.org/grpc" + "image/color" + "net/url" + "strings" +) + +func main() { + ptgApp := InitApp() + app := app.New() + window := app.NewWindow(ptgApp.AppName) + window.Resize(fyne.NewSize(ptgApp.AppWidth, ptgApp.AppHeight)) + + requestEntry := widget.NewMultiLineEntry() + requestEntry.SetPlaceHolder(ptgApp.RightRequest.RequestEntryPlaceHolder) + requestEntry.Wrapping = fyne.TextWrapWord + responseEntry := widget.NewMultiLineEntry() + responseEntry.Wrapping = fyne.TextWrapWord + reqLabel := widget.NewLabel("") + targetInput := widget.NewEntry() + targetInput.SetText(ptgApp.RightRequest.TargetInputText) + targetInput.SetPlaceHolder("") + processBar := widget.NewProgressBarInfinite() + processBar.Hide() + serviceAccordionRemove := false + serviceAccordion := widget.NewAccordion() + + content := container.NewVBox() + fileOpen := dialog.NewFileOpen(func(uri fyne.URIReadCloser, err error) { + if err != nil { + dialog.ShowError(err, window) + return + } + if uri != nil { + parseAdapter, exit, err := RegisterReflect(uri.URI().Path()) + if err != nil { + dialog.ShowError(err, window) + return + } + if exit { + dialog.ShowError(errors.New("proto file already exists"), window) + return + } + + maps := parseAdapter.Parse().ServiceInfoMaps() + if serviceAccordionRemove { + content.Add(serviceAccordion) + serviceAccordionRemove = false + } + for k, v := range maps { + var methods []string + for _, s := range v { + methods = append(methods, k+"."+s+"-"+fmt.Sprint(parseAdapter.Index())) + } + serviceAccordion.Append(&widget.AccordionItem{ + Title: k, + Detail: widget.NewRadioGroup(methods, func(s string) { + if s == "" { + return + } + methodInfo := strings.Split(s, "-") + service, method, err := reflect.ParseServiceMethod(methodInfo[0]) + if err != nil { + dialog.ShowError(err, window) + return + } + json, err := GetParseAdapter(methodInfo[1]).Parse().RequestJSON(service, method) + if err != nil { + dialog.ShowError(err, window) + return + } + requestEntry.SetText(json) + reqLabel.SetText(s) + + }), + Open: false, + }) + + } + } + }, window) + + toolbar := widget.NewToolbar( + widget.NewToolbarAction(theme.ContentAddIcon(), func() { + fileOpen.Show() + }), + widget.NewToolbarAction(theme.ViewRefreshIcon(), func() { + dialog.ShowInformation("Notice", "coming soon", window) + }), + widget.NewToolbarAction(theme.DeleteIcon(), func() { + ClearReflect() + content.Remove(serviceAccordion) + serviceAccordionRemove = true + serviceAccordion.Items = nil + dialog.ShowInformation("Notice", "all proto files have been reset", window) + }), + widget.NewToolbarSeparator(), + widget.NewToolbarAction(theme.HelpIcon(), func() { + w := fyne.CurrentApp().NewWindow("Help") + u, _ := url.Parse(ptgApp.HelpUrl) + w.SetContent(container.New(layout.NewCenterLayout(), widget.NewHyperlink("help?", u))) + w.Resize(fyne.NewSize(130, 100)) + w.SetFixedSize(true) + w.Show() + }), + ) + content.Add(toolbar) + content.Add(serviceAccordion) + leftTool := container.New(layout.NewGridLayout(1), content) + + // Right + form := widget.NewForm(&widget.FormItem{ + Text: "Target:", + Widget: targetInput, + HintText: "Input target url", + }) + + requestContainer := container.New(layout.NewGridLayoutWithColumns(1)) + requestContainer.Add(requestEntry) + requestButton := widget.NewButtonWithIcon("RUN", theme.MediaPlayIcon(), func() { + if requestEntry.Text == "" { + dialog.ShowError(errors.New("request json can not nil"), window) + return + } + if reqLabel.Text == "" { + dialog.ShowError(errors.New("proto can not nil"), window) + return + } + methodInfo := strings.Split(reqLabel.Text, "-") + service, method, err := reflect.ParseServiceMethod(methodInfo[0]) + if err != nil { + dialog.ShowError(err, window) + return + } + index := methodInfo[1] + parse := GetParseAdapter(index).Parse() + mds, err := parse.MethodDescriptor(service, method) + if err != nil { + dialog.ShowError(err, window) + return + } + var opts []grpc.DialOption + opts = append(opts, grpc.WithInsecure()) + ctx := context.Background() + conn, err := grpc.DialContext(ctx, targetInput.Text, opts...) + if err != nil { + dialog.ShowError(err, window) + return + } + stub := grpcdynamic.NewStub(conn) + processBar.Show() + rpc, err := parse.InvokeRpc(ctx, stub, mds, requestEntry.Text) + if err != nil { + processBar.Hide() + dialog.ShowError(err, window) + return + } + processBar.Hide() + marshalIndent, _ := json.MarshalIndent(rpc, "", "\t") + responseEntry.SetText(string(marshalIndent)) + }) + bottomBox := container.NewVBox(canvas.NewLine(color.Black), requestButton) + bottomBox.Add(canvas.NewLine(color.Black)) + bottomBox.Add(processBar) + requestPanel := container.NewBorder(form, bottomBox, nil, nil) + requestPanel.Add(requestContainer) + + responseContainer := container.New(layout.NewGridLayoutWithColumns(1)) + responseContainer.Add(responseEntry) + responseLabel := widget.NewLabel(ptgApp.RightResponse.ResponseLabelText) + responsePanel := container.NewBorder(responseLabel, nil, nil, nil) + responsePanel.Add(responseContainer) + + rightTool := container.NewGridWithColumns(1, + requestPanel, responsePanel) + split := container.NewHSplit(leftTool, rightTool) + + window.SetContent(split) + window.ShowAndRun() +} diff --git a/gui/reflect.go b/gui/reflect.go new file mode 100644 index 0000000..88a83a9 --- /dev/null +++ b/gui/reflect.go @@ -0,0 +1,84 @@ +package main + +import ( + "fmt" + "github.com/crossoverJie/ptg/reflect" + "sync/atomic" +) + +var ( + parseContainerMap map[string]*ParseReflectAdapter + // index->filename + containerMap map[string]string + index int64 +) + +type ParseReflectAdapter struct { + parse *reflect.ParseReflect + index string +} + +func (p *ParseReflectAdapter) Parse() *reflect.ParseReflect { + return p.parse +} +func (p *ParseReflectAdapter) Index() string { + return p.index +} + +func RegisterReflect(filename string) (*ParseReflectAdapter, bool, error) { + parseAdapter, ok := parseContainerMap[filename] + if ok { + return parseAdapter, true, nil + } + newParse, err := reflect.NewParse(filename) + if err != nil { + return nil, false, err + } + if parseContainerMap == nil { + parseContainerMap = make(map[string]*ParseReflectAdapter) + } + if containerMap == nil { + containerMap = make(map[string]string) + } + + index := genIndex() + containerMap[index] = filename + parseAdapter = &ParseReflectAdapter{ + parse: newParse, + index: index, + } + parseContainerMap[filename] = parseAdapter + + return parseAdapter, false, nil +} + +func ClearReflect() { + parseContainerMap = nil + containerMap = nil + index = 0 +} + +func ResetReflect() { + var filenameList []string + for k := range parseContainerMap { + filenameList = append(filenameList, k) + } + ClearReflect() + for _, filename := range filenameList { + RegisterReflect(filename) + } +} + +func ParseContainer() map[string]*ParseReflectAdapter { + return parseContainerMap +} + +func genIndex() string { + return fmt.Sprint(atomic.AddInt64(&index, 1)) +} + +func GetParseAdapter(index string) *ParseReflectAdapter { + filename := containerMap[index] + registerReflect, _, _ := RegisterReflect(filename) + return registerReflect +} diff --git a/main.go b/main.go index c8e72db..1a8c2ac 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,8 @@ package main import ( "errors" "github.com/cheggaaa/pb/v3" + "github.com/crossoverJie/ptg/meta" + "github.com/crossoverJie/ptg/model" "github.com/fatih/color" "github.com/urfave/cli/v2" "io/ioutil" @@ -10,13 +12,12 @@ import ( "os" "os/signal" "strings" - "time" ) // init bind variable var ( - target string - respCh chan *Response + target string + //respCh chan *meta.Response thread int duration int64 method string @@ -30,12 +31,12 @@ var ( ) var ( - totalRequestTime time.Duration - totalResponseSize int - SlowRequestTime time.Duration - FastRequestTime = time.Minute - ErrorCount int32 - Bar *pb.ProgressBar + //totalRequestTime time.Duration + //totalResponseSize int + //SlowRequestTime time.Duration + //FastRequestTime = time.Minute + //ErrorCount int32 + Bar *pb.ProgressBar ) const ( @@ -44,23 +45,6 @@ const ( Grpc = "grpc" ) -type ( - Model interface { - Init() - Run() - Finish() - PrintSate() - Shutdown() - } - - Job struct { - thread int - duration int64 - count int - target string - } -) - func main() { var count int app := &cli.App{Name: "ptg", Usage: "Performance testing tool (Go)", @@ -176,21 +160,24 @@ func main() { headerMap[splitN[0]] = splitN[1] } } - // ##########App init########## - - var model Model + meta.NewResult() + newMeta := meta.NewMeta(target, method, bodyPath, body, protocol, protocolFile, fqn, thread, duration, &headerSlice, headerMap) + var model model.Model if count > 0 { - respCh = make(chan *Response, count) + respCh := make(chan *meta.Response, count) + newMeta.SetRespCh(respCh) model = NewCountModel(count) Bar = pb.ProgressBarTemplate(PbTmpl).Start(count) } else { // 防止写入 goroutine 阻塞,导致泄露。 - respCh = make(chan *Response, 3*thread) + respCh := make(chan *meta.Response, 3*thread) + newMeta.SetRespCh(respCh) model = NewDurationModel(duration) Bar = pb.ProgressBarTemplate(PbTmpl).Start(int(duration)) } Bar.Set("target", target). SetWidth(120) + // ##########App init########## // shutdown signCh := make(chan os.Signal, 1) diff --git a/meta/meta.go b/meta/meta.go new file mode 100644 index 0000000..9c98b7a --- /dev/null +++ b/meta/meta.go @@ -0,0 +1,163 @@ +package meta + +import ( + "github.com/urfave/cli/v2" + "sync/atomic" + "time" +) + +type Response struct { + RequestTime time.Duration + ResponseSize int +} + +func (r *Response) FastRequest() time.Duration { + if r.RequestTime < GetResult().FastRequestTime() { + return r.RequestTime + } + return GetResult().FastRequestTime() +} +func (r *Response) SlowRequest() time.Duration { + if r.RequestTime > GetResult().SlowRequestTime() { + return r.RequestTime + } + return GetResult().SlowRequestTime() +} + +var result *Result + +type Result struct { + totalRequestTime time.Duration + totalResponseSize int + slowRequestTime time.Duration + fastRequestTime time.Duration + errorCount int32 +} + +func GetResult() *Result { + return result +} + +func NewResult() *Result { + if result != nil { + return result + } + result = &Result{fastRequestTime: time.Minute} + return GetResult() +} + +func (m *Result) SetTotalRequestTime(req time.Duration) *Result { + m.totalRequestTime += req + return m +} + +func (m *Result) TotalRequestTime() time.Duration { + return m.totalRequestTime +} + +func (m *Result) SetTotalResponseSize(req int) *Result { + m.totalResponseSize += req + return m +} + +func (m *Result) TotalResponseSize() int { + return m.totalResponseSize +} + +func (m *Result) SetSlowRequestTime(req time.Duration) *Result { + GetResult().slowRequestTime = req + return m +} +func (m *Result) SlowRequestTime() time.Duration { + return m.slowRequestTime +} + +func (m *Result) SetFastRequestTime(req time.Duration) *Result { + GetResult().fastRequestTime = req + return m +} +func (m *Result) FastRequestTime() time.Duration { + return m.fastRequestTime +} + +func (m *Result) IncrementErrorCount() *Result { + atomic.AddInt32(&m.errorCount, 1) + return m +} + +func (m *Result) ErrorCount() int32 { + return m.errorCount +} + +type Meta struct { + target string + respCh chan *Response + thread int + duration int64 + method string + bodyPath string + body string + headerSlice *cli.StringSlice + headerMap map[string]string + protocol string // http/grpc + protocolFile string // xx/xx/xx.proto + fqn string // fully-qualified method name:[package.Service.Method] +} + +var meta *Meta + +func NewMeta(target, method, bodyPath, body, protocol, protocolFile, fqn string, thread int, duration int64, + headerSlice *cli.StringSlice, headerMap map[string]string) *Meta { + + if meta != nil { + return meta + } + + meta = &Meta{ + target: target, + thread: thread, + duration: duration, + method: method, + bodyPath: bodyPath, + body: body, + headerSlice: headerSlice, + headerMap: headerMap, + protocol: protocol, + protocolFile: protocolFile, + fqn: fqn, + } + return meta +} + +func GetMeta() *Meta { + return meta +} + +func (m *Meta) Protocol() string { + return m.protocol +} +func (m *Meta) ProtocolFile() string { + return m.protocolFile +} +func (m *Meta) Fqn() string { + return m.fqn +} +func (m *Meta) Target() string { + return m.target +} +func (m *Meta) Body() string { + return m.body +} + +func (m *Meta) HeaderMap() map[string]string { + return m.headerMap +} + +func (m *Meta) SetRespCh(respCh chan *Response) *Meta { + m.respCh = respCh + return meta +} + +func (m *Meta) RespCh() chan *Response { + return meta.respCh +} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..1468900 --- /dev/null +++ b/model/model.go @@ -0,0 +1,18 @@ +package model + +type ( + Model interface { + Init() + Run() + Finish() + PrintSate() + Shutdown() + } + + Job struct { + Thread int + Duration int64 + Count int + Target string + } +) diff --git a/pic/gopher.png b/pic/gopher.png new file mode 100644 index 0000000..007e1d6 Binary files /dev/null and b/pic/gopher.png differ diff --git a/reflect/gen/test.pb.go b/reflect/gen/test.pb.go new file mode 100644 index 0000000..d8acdc1 --- /dev/null +++ b/reflect/gen/test.pb.go @@ -0,0 +1,526 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.5.1 +// source: reflect/gen/test.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ReasonApi struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ReasonApi) Reset() { + *x = ReasonApi{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReasonApi) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReasonApi) ProtoMessage() {} + +func (x *ReasonApi) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReasonApi.ProtoReflect.Descriptor instead. +func (*ReasonApi) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{0} +} + +func (x *ReasonApi) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type Reasons struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Reason []*Reason `protobuf:"bytes,1,rep,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *Reasons) Reset() { + *x = Reasons{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Reasons) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Reasons) ProtoMessage() {} + +func (x *Reasons) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Reasons.ProtoReflect.Descriptor instead. +func (*Reasons) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Reasons) GetReason() []*Reason { + if x != nil { + return x.Reason + } + return nil +} + +type Reason struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Remark string `protobuf:"bytes,2,opt,name=remark,proto3" json:"remark,omitempty"` +} + +func (x *Reason) Reset() { + *x = Reason{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Reason) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Reason) ProtoMessage() {} + +func (x *Reason) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Reason.ProtoReflect.Descriptor instead. +func (*Reason) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{2} +} + +func (x *Reason) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Reason) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +type CloseApiCreate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderId int64 `protobuf:"varint,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` +} + +func (x *CloseApiCreate) Reset() { + *x = CloseApiCreate{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CloseApiCreate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseApiCreate) ProtoMessage() {} + +func (x *CloseApiCreate) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CloseApiCreate.ProtoReflect.Descriptor instead. +func (*CloseApiCreate) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{3} +} + +func (x *CloseApiCreate) GetOrderId() int64 { + if x != nil { + return x.OrderId + } + return 0 +} + +type OrderApiCreate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderId int64 `protobuf:"varint,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + UserId []int64 `protobuf:"varint,2,rep,packed,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Remark string `protobuf:"bytes,3,opt,name=remark,proto3" json:"remark,omitempty"` + ReasonId []int32 `protobuf:"varint,4,rep,packed,name=reason_id,json=reasonId,proto3" json:"reason_id,omitempty"` +} + +func (x *OrderApiCreate) Reset() { + *x = OrderApiCreate{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OrderApiCreate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrderApiCreate) ProtoMessage() {} + +func (x *OrderApiCreate) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrderApiCreate.ProtoReflect.Descriptor instead. +func (*OrderApiCreate) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{4} +} + +func (x *OrderApiCreate) GetOrderId() int64 { + if x != nil { + return x.OrderId + } + return 0 +} + +func (x *OrderApiCreate) GetUserId() []int64 { + if x != nil { + return x.UserId + } + return nil +} + +func (x *OrderApiCreate) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *OrderApiCreate) GetReasonId() []int32 { + if x != nil { + return x.ReasonId + } + return nil +} + +type Order struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderId int64 `protobuf:"varint,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + Reason []*Reason `protobuf:"bytes,2,rep,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *Order) Reset() { + *x = Order{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Order) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Order) ProtoMessage() {} + +func (x *Order) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_test_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Order.ProtoReflect.Descriptor instead. +func (*Order) Descriptor() ([]byte, []int) { + return file_reflect_gen_test_proto_rawDescGZIP(), []int{5} +} + +func (x *Order) GetOrderId() int64 { + if x != nil { + return x.OrderId + } + return 0 +} + +func (x *Order) GetReason() []*Reason { + if x != nil { + return x.Reason + } + return nil +} + +var File_reflect_gen_test_proto protoreflect.FileDescriptor + +var file_reflect_gen_test_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, + 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x22, 0x1b, 0x0a, 0x09, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, + 0x33, 0x0a, 0x07, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x22, 0x2b, 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, + 0x70, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x49, 0x64, 0x22, 0x79, 0x0a, 0x0e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x70, 0x69, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, + 0x61, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, + 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x4c, + 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x28, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x32, 0x7b, 0x0a, 0x0c, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x06, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x70, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x1a, 0x0f, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x05, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x70, 0x69, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x1a, 0x0f, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x32, 0x43, 0x0a, 0x0b, 0x54, 0x65, 0x73, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x1a, 0x11, 0x2e, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x22, 0x00, 0x42, 0x2c, + 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, + 0x73, 0x73, 0x6f, 0x76, 0x65, 0x72, 0x4a, 0x69, 0x65, 0x2f, 0x70, 0x74, 0x67, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_reflect_gen_test_proto_rawDescOnce sync.Once + file_reflect_gen_test_proto_rawDescData = file_reflect_gen_test_proto_rawDesc +) + +func file_reflect_gen_test_proto_rawDescGZIP() []byte { + file_reflect_gen_test_proto_rawDescOnce.Do(func() { + file_reflect_gen_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflect_gen_test_proto_rawDescData) + }) + return file_reflect_gen_test_proto_rawDescData +} + +var file_reflect_gen_test_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_reflect_gen_test_proto_goTypes = []interface{}{ + (*ReasonApi)(nil), // 0: order.v1.ReasonApi + (*Reasons)(nil), // 1: order.v1.Reasons + (*Reason)(nil), // 2: order.v1.Reason + (*CloseApiCreate)(nil), // 3: order.v1.CloseApiCreate + (*OrderApiCreate)(nil), // 4: order.v1.OrderApiCreate + (*Order)(nil), // 5: order.v1.Order +} +var file_reflect_gen_test_proto_depIdxs = []int32{ + 2, // 0: order.v1.Reasons.reason:type_name -> order.v1.Reason + 2, // 1: order.v1.Order.reason:type_name -> order.v1.Reason + 4, // 2: order.v1.OrderService.Create:input_type -> order.v1.OrderApiCreate + 3, // 3: order.v1.OrderService.Close:input_type -> order.v1.CloseApiCreate + 0, // 4: order.v1.TestService.TestList:input_type -> order.v1.ReasonApi + 5, // 5: order.v1.OrderService.Create:output_type -> order.v1.Order + 5, // 6: order.v1.OrderService.Close:output_type -> order.v1.Order + 1, // 7: order.v1.TestService.TestList:output_type -> order.v1.Reasons + 5, // [5:8] is the sub-list for method output_type + 2, // [2:5] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_reflect_gen_test_proto_init() } +func file_reflect_gen_test_proto_init() { + if File_reflect_gen_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_reflect_gen_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReasonApi); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Reasons); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Reason); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CloseApiCreate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OrderApiCreate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Order); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_reflect_gen_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_reflect_gen_test_proto_goTypes, + DependencyIndexes: file_reflect_gen_test_proto_depIdxs, + MessageInfos: file_reflect_gen_test_proto_msgTypes, + }.Build() + File_reflect_gen_test_proto = out.File + file_reflect_gen_test_proto_rawDesc = nil + file_reflect_gen_test_proto_goTypes = nil + file_reflect_gen_test_proto_depIdxs = nil +} diff --git a/reflect/gen/test.proto b/reflect/gen/test.proto new file mode 100644 index 0000000..7bf60cb --- /dev/null +++ b/reflect/gen/test.proto @@ -0,0 +1,49 @@ + +syntax = "proto3"; +option go_package = "github.com/crossoverJie/ptg/proto/order/v1"; + +package order.v1; + +service OrderService{ + + rpc Create(OrderApiCreate) returns (Order) {} + + rpc Close(CloseApiCreate) returns (Order) {} + +} + +service TestService{ + rpc TestList(ReasonApi) returns (Reasons){} +} +message ReasonApi{ + int32 id = 1; +} + +message Reasons{ + repeated Reason reason = 1; +} + +message Reason{ + int32 id = 1; + string remark = 2; +} + + + +message CloseApiCreate{ + int64 order_id = 1; +} + + +message OrderApiCreate{ + int64 order_id = 1; + repeated int64 user_id = 2; + string remark = 3; + repeated int32 reason_id = 4; +} + +message Order{ + int64 order_id = 1; + repeated Reason reason = 2; +} + diff --git a/reflect/gen/test_grpc.pb.go b/reflect/gen/test_grpc.pb.go new file mode 100644 index 0000000..4b025d3 --- /dev/null +++ b/reflect/gen/test_grpc.pb.go @@ -0,0 +1,223 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// OrderServiceClient is the client API for OrderService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type OrderServiceClient interface { + Create(ctx context.Context, in *OrderApiCreate, opts ...grpc.CallOption) (*Order, error) + Close(ctx context.Context, in *CloseApiCreate, opts ...grpc.CallOption) (*Order, error) +} + +type orderServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewOrderServiceClient(cc grpc.ClientConnInterface) OrderServiceClient { + return &orderServiceClient{cc} +} + +func (c *orderServiceClient) Create(ctx context.Context, in *OrderApiCreate, opts ...grpc.CallOption) (*Order, error) { + out := new(Order) + err := c.cc.Invoke(ctx, "/order.v1.OrderService/Create", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *orderServiceClient) Close(ctx context.Context, in *CloseApiCreate, opts ...grpc.CallOption) (*Order, error) { + out := new(Order) + err := c.cc.Invoke(ctx, "/order.v1.OrderService/Close", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// OrderServiceServer is the server API for OrderService service. +// All implementations must embed UnimplementedOrderServiceServer +// for forward compatibility +type OrderServiceServer interface { + Create(context.Context, *OrderApiCreate) (*Order, error) + Close(context.Context, *CloseApiCreate) (*Order, error) + mustEmbedUnimplementedOrderServiceServer() +} + +// UnimplementedOrderServiceServer must be embedded to have forward compatible implementations. +type UnimplementedOrderServiceServer struct { +} + +func (UnimplementedOrderServiceServer) Create(context.Context, *OrderApiCreate) (*Order, error) { + return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") +} +func (UnimplementedOrderServiceServer) Close(context.Context, *CloseApiCreate) (*Order, error) { + return nil, status.Errorf(codes.Unimplemented, "method Close not implemented") +} +func (UnimplementedOrderServiceServer) mustEmbedUnimplementedOrderServiceServer() {} + +// UnsafeOrderServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to OrderServiceServer will +// result in compilation errors. +type UnsafeOrderServiceServer interface { + mustEmbedUnimplementedOrderServiceServer() +} + +func RegisterOrderServiceServer(s grpc.ServiceRegistrar, srv OrderServiceServer) { + s.RegisterService(&OrderService_ServiceDesc, srv) +} + +func _OrderService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(OrderApiCreate) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/order.v1.OrderService/Create", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).Create(ctx, req.(*OrderApiCreate)) + } + return interceptor(ctx, in, info, handler) +} + +func _OrderService_Close_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CloseApiCreate) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).Close(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/order.v1.OrderService/Close", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).Close(ctx, req.(*CloseApiCreate)) + } + return interceptor(ctx, in, info, handler) +} + +// OrderService_ServiceDesc is the grpc.ServiceDesc for OrderService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var OrderService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "order.v1.OrderService", + HandlerType: (*OrderServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Create", + Handler: _OrderService_Create_Handler, + }, + { + MethodName: "Close", + Handler: _OrderService_Close_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "reflect/gen/test.proto", +} + +// TestServiceClient is the client API for TestService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestServiceClient interface { + TestList(ctx context.Context, in *ReasonApi, opts ...grpc.CallOption) (*Reasons, error) +} + +type testServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) TestList(ctx context.Context, in *ReasonApi, opts ...grpc.CallOption) (*Reasons, error) { + out := new(Reasons) + err := c.cc.Invoke(ctx, "/order.v1.TestService/TestList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TestServiceServer is the server API for TestService service. +// All implementations must embed UnimplementedTestServiceServer +// for forward compatibility +type TestServiceServer interface { + TestList(context.Context, *ReasonApi) (*Reasons, error) + mustEmbedUnimplementedTestServiceServer() +} + +// UnimplementedTestServiceServer must be embedded to have forward compatible implementations. +type UnimplementedTestServiceServer struct { +} + +func (UnimplementedTestServiceServer) TestList(context.Context, *ReasonApi) (*Reasons, error) { + return nil, status.Errorf(codes.Unimplemented, "method TestList not implemented") +} +func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {} + +// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to TestServiceServer will +// result in compilation errors. +type UnsafeTestServiceServer interface { + mustEmbedUnimplementedTestServiceServer() +} + +func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) { + s.RegisterService(&TestService_ServiceDesc, srv) +} + +func _TestService_TestList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReasonApi) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).TestList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/order.v1.TestService/TestList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).TestList(ctx, req.(*ReasonApi)) + } + return interceptor(ctx, in, info, handler) +} + +// TestService_ServiceDesc is the grpc.ServiceDesc for TestService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var TestService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "order.v1.TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "TestList", + Handler: _TestService_TestList_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "reflect/gen/test.proto", +} diff --git a/reflect/gen/user.proto b/reflect/gen/user.proto new file mode 100644 index 0000000..17b8833 --- /dev/null +++ b/reflect/gen/user.proto @@ -0,0 +1,29 @@ + +syntax = "proto3"; +option go_package = "github.com/crossoverJie/ptg/proto/user/v2"; + +package user.v2; + +service UserService{ + + rpc Create(UserApiCreate) returns (User) {} + + rpc List(Empty) returns (UserList) {} + +} + +message Empty{} + + + +message UserApiCreate{ + int64 user_id = 1; +} +message User{ + int64 user_id = 1; +} + +message UserList{ + repeated User userList=1; +} + diff --git a/reflect/gen/user/user.pb.go b/reflect/gen/user/user.pb.go new file mode 100644 index 0000000..54981d8 --- /dev/null +++ b/reflect/gen/user/user.pb.go @@ -0,0 +1,333 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.5.1 +// source: reflect/gen/user.proto + +package user + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Empty struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Empty) Reset() { + *x = Empty{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_user_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_reflect_gen_user_proto_rawDescGZIP(), []int{0} +} + +type UserApiCreate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` +} + +func (x *UserApiCreate) Reset() { + *x = UserApiCreate{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserApiCreate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserApiCreate) ProtoMessage() {} + +func (x *UserApiCreate) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_user_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserApiCreate.ProtoReflect.Descriptor instead. +func (*UserApiCreate) Descriptor() ([]byte, []int) { + return file_reflect_gen_user_proto_rawDescGZIP(), []int{1} +} + +func (x *UserApiCreate) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_user_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_user_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_reflect_gen_user_proto_rawDescGZIP(), []int{2} +} + +func (x *User) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type UserList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserList []*User `protobuf:"bytes,1,rep,name=userList,proto3" json:"userList,omitempty"` +} + +func (x *UserList) Reset() { + *x = UserList{} + if protoimpl.UnsafeEnabled { + mi := &file_reflect_gen_user_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserList) ProtoMessage() {} + +func (x *UserList) ProtoReflect() protoreflect.Message { + mi := &file_reflect_gen_user_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserList.ProtoReflect.Descriptor instead. +func (*UserList) Descriptor() ([]byte, []int) { + return file_reflect_gen_user_proto_rawDescGZIP(), []int{3} +} + +func (x *UserList) GetUserList() []*User { + if x != nil { + return x.UserList + } + return nil +} + +var File_reflect_gen_user_proto protoreflect.FileDescriptor + +var file_reflect_gen_user_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x32, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x28, 0x0a, 0x0d, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x70, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x22, 0x1f, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x35, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x29, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x32, 0x6d, 0x0a, 0x0b, + 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x1a, 0x0d, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x00, 0x12, 0x2b, + 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x0e, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x32, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6f, + 0x76, 0x65, 0x72, 0x4a, 0x69, 0x65, 0x2f, 0x70, 0x74, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_reflect_gen_user_proto_rawDescOnce sync.Once + file_reflect_gen_user_proto_rawDescData = file_reflect_gen_user_proto_rawDesc +) + +func file_reflect_gen_user_proto_rawDescGZIP() []byte { + file_reflect_gen_user_proto_rawDescOnce.Do(func() { + file_reflect_gen_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflect_gen_user_proto_rawDescData) + }) + return file_reflect_gen_user_proto_rawDescData +} + +var file_reflect_gen_user_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_reflect_gen_user_proto_goTypes = []interface{}{ + (*Empty)(nil), // 0: user.v2.Empty + (*UserApiCreate)(nil), // 1: user.v2.UserApiCreate + (*User)(nil), // 2: user.v2.User + (*UserList)(nil), // 3: user.v2.UserList +} +var file_reflect_gen_user_proto_depIdxs = []int32{ + 2, // 0: user.v2.UserList.userList:type_name -> user.v2.User + 1, // 1: user.v2.UserService.Create:input_type -> user.v2.UserApiCreate + 0, // 2: user.v2.UserService.List:input_type -> user.v2.Empty + 2, // 3: user.v2.UserService.Create:output_type -> user.v2.User + 3, // 4: user.v2.UserService.List:output_type -> user.v2.UserList + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_reflect_gen_user_proto_init() } +func file_reflect_gen_user_proto_init() { + if File_reflect_gen_user_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_reflect_gen_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Empty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserApiCreate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_reflect_gen_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_reflect_gen_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_reflect_gen_user_proto_goTypes, + DependencyIndexes: file_reflect_gen_user_proto_depIdxs, + MessageInfos: file_reflect_gen_user_proto_msgTypes, + }.Build() + File_reflect_gen_user_proto = out.File + file_reflect_gen_user_proto_rawDesc = nil + file_reflect_gen_user_proto_goTypes = nil + file_reflect_gen_user_proto_depIdxs = nil +} diff --git a/reflect/gen/user/user_grpc.pb.go b/reflect/gen/user/user_grpc.pb.go new file mode 100644 index 0000000..56e48b2 --- /dev/null +++ b/reflect/gen/user/user_grpc.pb.go @@ -0,0 +1,137 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package user + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// UserServiceClient is the client API for UserService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UserServiceClient interface { + Create(ctx context.Context, in *UserApiCreate, opts ...grpc.CallOption) (*User, error) + List(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*UserList, error) +} + +type userServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient { + return &userServiceClient{cc} +} + +func (c *userServiceClient) Create(ctx context.Context, in *UserApiCreate, opts ...grpc.CallOption) (*User, error) { + out := new(User) + err := c.cc.Invoke(ctx, "/user.v2.UserService/Create", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userServiceClient) List(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*UserList, error) { + out := new(UserList) + err := c.cc.Invoke(ctx, "/user.v2.UserService/List", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UserServiceServer is the server API for UserService service. +// All implementations must embed UnimplementedUserServiceServer +// for forward compatibility +type UserServiceServer interface { + Create(context.Context, *UserApiCreate) (*User, error) + List(context.Context, *Empty) (*UserList, error) + mustEmbedUnimplementedUserServiceServer() +} + +// UnimplementedUserServiceServer must be embedded to have forward compatible implementations. +type UnimplementedUserServiceServer struct { +} + +func (UnimplementedUserServiceServer) Create(context.Context, *UserApiCreate) (*User, error) { + return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") +} +func (UnimplementedUserServiceServer) List(context.Context, *Empty) (*UserList, error) { + return nil, status.Errorf(codes.Unimplemented, "method List not implemented") +} +func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {} + +// UnsafeUserServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UserServiceServer will +// result in compilation errors. +type UnsafeUserServiceServer interface { + mustEmbedUnimplementedUserServiceServer() +} + +func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) { + s.RegisterService(&UserService_ServiceDesc, srv) +} + +func _UserService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UserApiCreate) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/user.v2.UserService/Create", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).Create(ctx, req.(*UserApiCreate)) + } + return interceptor(ctx, in, info, handler) +} + +func _UserService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).List(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/user.v2.UserService/List", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).List(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var UserService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "user.v2.UserService", + HandlerType: (*UserServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Create", + Handler: _UserService_Create_Handler, + }, + { + MethodName: "List", + Handler: _UserService_List_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "reflect/gen/user.proto", +} diff --git a/reflect/reflect.go b/reflect/reflect.go new file mode 100644 index 0000000..71b50d3 --- /dev/null +++ b/reflect/reflect.go @@ -0,0 +1,150 @@ +package reflect + +import ( + "context" + "encoding/json" + "fmt" + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/jhump/protoreflect/desc" + "github.com/jhump/protoreflect/desc/protoparse" + "github.com/jhump/protoreflect/dynamic" + "github.com/jhump/protoreflect/dynamic/grpcdynamic" + "github.com/pkg/errors" + "google.golang.org/grpc" + "strings" +) + +type ParseReflect struct { + filename string + // serviceInfoMap[sds.GetFullyQualifiedName()] = methodInfos + serviceInfoMap map[string][]string + fds *desc.FileDescriptor +} + +func NewParse(filename string) (*ParseReflect, error) { + p := &ParseReflect{filename: filename} + err := p.parseProto() + return p, err +} + +// Init: parse proto +func (p *ParseReflect) parseProto() error { + var parser protoparse.Parser + fds, err := parser.ParseFiles(p.filename) + if err != nil { + return errors.WithStack(err) + } + p.fds = fds[0] + + serviceInfoMap := make(map[string][]string) + for _, sds := range fds[0].GetServices() { + + var methodInfos []string + for _, mds := range sds.GetMethods() { + methodInfos = append(methodInfos, mds.GetName()) + } + + serviceInfoMap[sds.GetFullyQualifiedName()] = methodInfos + + } + p.serviceInfoMap = serviceInfoMap + return nil +} + +func (p *ParseReflect) ServiceInfoMaps() map[string][]string { + return p.serviceInfoMap +} + +func (p *ParseReflect) RequestJSON(serviceName, methodName string) (string, error) { + _, ok := p.serviceInfoMap[serviceName] + if !ok { + return "", errors.New("service not found!") + } + + sds := p.fds.FindService(serviceName) + mds := sds.FindMethodByName(methodName) + messageToMap := convertMessageToMap(mds.GetInputType()) + marshalIndent, err := json.MarshalIndent(messageToMap, "", "\t") + return string(marshalIndent), err +} + +// Get Method desc +func (p *ParseReflect) MethodDescriptor(serviceName, methodName string) (*desc.MethodDescriptor, error) { + _, ok := p.serviceInfoMap[serviceName] + if !ok { + return nil, errors.New("service not found!") + } + sds := p.fds.FindService(serviceName) + return sds.FindMethodByName(methodName), nil +} + +func (p *ParseReflect) InvokeRpc(ctx context.Context, stub grpcdynamic.Stub, mds *desc.MethodDescriptor, data string, opts ...grpc.CallOption) (proto.Message, error) { + + messages, err := createPayloadsFromJSON(mds, data) + if err != nil { + return nil, err + } + return stub.InvokeRpc(ctx, mds, messages[0]) +} + +func convertMessageToMap(message *desc.MessageDescriptor) map[string]interface{} { + m := make(map[string]interface{}) + for _, fieldDescriptor := range message.GetFields() { + fieldName := fieldDescriptor.GetName() + if fieldDescriptor.IsRepeated() { + // Array temporary nil + m[fieldName] = nil + continue + } + switch fieldDescriptor.GetType() { + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + m[fieldName] = convertMessageToMap(fieldDescriptor.GetMessageType()) + continue + } + m[fieldName] = fieldDescriptor.GetDefaultValue() + } + return m +} + +func ParseServiceMethod(svcAndMethod string) (string, string, error) { + if len(svcAndMethod) == 0 { + return "", "", errors.New("service not found!") + } + if svcAndMethod[0] == '.' { + svcAndMethod = svcAndMethod[1:] + } + if len(svcAndMethod) == 0 { + return "", "", errors.New("service not found!") + } + switch strings.Count(svcAndMethod, "/") { + case 0: + pos := strings.LastIndex(svcAndMethod, ".") + if pos < 0 { + return "", "", errors.New("service not found!") + } + return svcAndMethod[:pos], svcAndMethod[pos+1:], nil + case 1: + split := strings.Split(svcAndMethod, "/") + return split[0], split[1], nil + default: + return "", "", errors.New("service not found!") + } +} + +func createPayloadsFromJSON(mds *desc.MethodDescriptor, data string) ([]*dynamic.Message, error) { + md := mds.GetInputType() + var inputs []*dynamic.Message + + if len(data) > 0 { + inputs = make([]*dynamic.Message, 1) + inputs[0] = dynamic.NewMessage(md) + err := jsonpb.UnmarshalString(data, inputs[0]) + if err != nil { + return nil, errors.New(fmt.Sprintf("create payload json err %v \n", err)) + } + } + + return inputs, nil +} diff --git a/reflect/reflect_test.go b/reflect/reflect_test.go new file mode 100644 index 0000000..c67a1ad --- /dev/null +++ b/reflect/reflect_test.go @@ -0,0 +1,140 @@ +package reflect + +import ( + "context" + "encoding/json" + "fmt" + v1 "github.com/crossoverJie/ptg/reflect/gen" + "github.com/crossoverJie/ptg/reflect/gen/user" + "github.com/jhump/protoreflect/dynamic/grpcdynamic" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + "log" + "net" + "strings" + "testing" + "time" +) + +func TestParseProto(t *testing.T) { + filename := "gen/test.proto" + parse, err := NewParse(filename) + if err != nil { + panic(err) + } + maps := parse.ServiceInfoMaps() + fmt.Println(maps) +} + +func TestRequestJSON(t *testing.T) { + filename := "gen/test.proto" + parse, err := NewParse(filename) + if err != nil { + panic(err) + } + if err != nil { + panic(err) + } + + json, err := parse.RequestJSON("order.v1.OrderService", "Create") + if err != nil { + panic(err) + } + fmt.Println(json) +} + +func TestParseReflect_InvokeRpc(t *testing.T) { + data := `{"order_id":20,"user_id":[20],"remark":"Hello","reason_id":[10]}` + filename := "gen/test.proto" + parse, err := NewParse(filename) + if err != nil { + panic(err) + } + if err != nil { + panic(err) + } + + mds, err := parse.MethodDescriptor("order.v1.OrderService", "Create") + if err != nil { + panic(err) + } + var opts []grpc.DialOption + opts = append(opts, grpc.WithInsecure()) + conn, err := grpc.DialContext(context.Background(), "127.0.0.1:5000", opts...) + stub := grpcdynamic.NewStub(conn) + rpc, err := parse.InvokeRpc(context.Background(), stub, mds, data) + if err != nil { + panic(err) + } + fmt.Println(rpc.String()) + fmt.Println("=========") + //marshal ,_:= proto.Marshal(rpc) + marshalIndent, _ := json.MarshalIndent(rpc, "", "\t") + fmt.Println(string(marshalIndent)) +} + +func TestServer(t *testing.T) { + port := 6001 + lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + var opts []grpc.ServerOption + grpcServer := grpc.NewServer(opts...) + v1.RegisterOrderServiceServer(grpcServer, &Order{}) + reflection.Register(grpcServer) + + fmt.Println("gRPC server started at ", port) + if err := grpcServer.Serve(lis); err != nil { + panic(err) + } +} + +type Order struct { + v1.UnimplementedOrderServiceServer +} + +func (o *Order) Create(ctx context.Context, in *v1.OrderApiCreate) (*v1.Order, error) { + + time.Sleep(200 * time.Millisecond) + fmt.Println(in.OrderId) + return &v1.Order{ + OrderId: in.OrderId, + Reason: nil, + }, nil +} + +func TestParseServiceMethod(t *testing.T) { + s, m, err := ParseServiceMethod("order.v1.OrderService.Create") + fmt.Println(s, m, err) +} + +func TestUserServer(t *testing.T) { + port := 7001 + lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + var opts []grpc.ServerOption + grpcServer := grpc.NewServer(opts...) + user.RegisterUserServiceServer(grpcServer, &User{}) + + fmt.Println("gRPC user server started at ", port) + if err := grpcServer.Serve(lis); err != nil { + panic(err) + } +} + +type User struct { + user.UnimplementedUserServiceServer +} + +func (*User) Create(ctx context.Context, in *user.UserApiCreate) (*user.User, error) { + time.Sleep(200 * time.Millisecond) + return &user.User{UserId: in.UserId}, nil +} + +func TestCommon(t *testing.T) { + x := "order.v1.OrderService.Detail-2" + fmt.Println(strings.Split(x, "-")[1]) +} diff --git a/test.json b/test.json index 10ffc76..7ae94bc 100644 --- a/test.json +++ b/test.json @@ -1 +1 @@ -{"order_id":27669403038384131} \ No newline at end of file +{"order_id":6760383805128707} \ No newline at end of file