From c35039ecde1bdf78d5fd38e7baf32989681aad89 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 1 May 2020 14:55:01 -0500 Subject: [PATCH] added formatter and tests --- cmd/grpcurl/grpcurl.go | 8 +++++++- format.go | 9 +++++++++ format_test.go | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cmd/grpcurl/grpcurl.go b/cmd/grpcurl/grpcurl.go index 70712a6..073dbd1 100644 --- a/cmd/grpcurl/grpcurl.go +++ b/cmd/grpcurl/grpcurl.go @@ -109,6 +109,8 @@ var ( will accept. If not specified, defaults to 4,194,304 (4 megabytes).`)) emitDefaults = flags.Bool("emit-defaults", false, prettify(` Emit default values for JSON-encoded responses.`)) + jsonError = flags.Bool("json-error", false, prettify(` + Emit error response as JSON.`)) protosetOut = flags.String("protoset-out", "", prettify(` The name of a file to be written that will contain a FileDescriptorSet proto. With the list and describe verbs, the listed or described @@ -652,7 +654,11 @@ func main() { fmt.Printf("Sent %d request%s and received %d response%s\n", reqCount, reqSuffix, h.NumResponses, respSuffix) } if h.Status.Code() != codes.OK { - grpcurl.PrintStatus(os.Stderr, h.Status, formatter) + if *jsonError { + grpcurl.PrintJSONStatus(os.Stderr, h.Status) + } else { + grpcurl.PrintStatus(os.Stderr, h.Status, formatter) + } exit(1) } } diff --git a/format.go b/format.go index a3dc444..bc40b69 100644 --- a/format.go +++ b/format.go @@ -467,3 +467,12 @@ func PrintStatus(w io.Writer, stat *status.Status, formatter Formatter) { } } } + +// PrintJSONStatus returns the grpc status response as a JSON object +func PrintJSONStatus(w io.Writer, stat *status.Status) { + jsonStatus, err := (&jsonpb.Marshaler{}).MarshalToString(stat.Proto()) + if err != nil { + fmt.Fprintf(w, "ERROR: %v", err.Error()) + } + fmt.Fprint(w, jsonStatus) +} diff --git a/format_test.go b/format_test.go index 30be9e2..f767ef3 100644 --- a/format_test.go +++ b/format_test.go @@ -11,7 +11,9 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/struct" "github.com/jhump/protoreflect/desc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" ) func TestRequestParser(t *testing.T) { @@ -173,6 +175,25 @@ func TestHandler(t *testing.T) { } } +func TestPrintJSONStatus(t *testing.T) { + testCases := []struct { + input *status.Status + expectedOutput string + }{{ + input: status.New(codes.InvalidArgument, "Missing Argument"), + expectedOutput: statusAsJSON, + }} + + for _, tc := range testCases { + var b bytes.Buffer + PrintJSONStatus(&b, tc.input) + got := b.String() + if !compare(tc.expectedOutput, got) { + t.Errorf("Incorrect output. Expected:\n%s\nGot:\n%s", tc.expectedOutput, got) + } + } +} + // compare checks that actual and expected are equal, returning true if so. // A simple equality check (==) does not suffice because jsonpb formats // structpb.Value strangely. So if that formatting gets fixed, we don't @@ -244,6 +265,7 @@ Response contents: "null": null } ` + statusAsJSON = `{"code":3,"message":"Missing Argument"} ` messageAsText = `struct_value: < fields: < key: "bar"