github.com/grpc-ecosystem/grpc-gateway/v2@v2.19.1/runtime/marshal_json_test.go (about)

     1  package runtime_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"reflect"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    12  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime/internal/examplepb"
    13  	"google.golang.org/protobuf/proto"
    14  	"google.golang.org/protobuf/testing/protocmp"
    15  	"google.golang.org/protobuf/types/known/emptypb"
    16  	"google.golang.org/protobuf/types/known/timestamppb"
    17  	"google.golang.org/protobuf/types/known/wrapperspb"
    18  )
    19  
    20  func TestJSONBuiltinMarshal(t *testing.T) {
    21  	var m runtime.JSONBuiltin
    22  	msg := &examplepb.SimpleMessage{
    23  		Id: "foo",
    24  	}
    25  
    26  	buf, err := m.Marshal(msg)
    27  	if err != nil {
    28  		t.Errorf("m.Marshal(%v) failed with %v; want success", msg, err)
    29  	}
    30  
    31  	got := new(examplepb.SimpleMessage)
    32  	if err := json.Unmarshal(buf, got); err != nil {
    33  		t.Errorf("json.Unmarshal(%q, got) failed with %v; want success", buf, err)
    34  	}
    35  	if diff := cmp.Diff(got, msg, protocmp.Transform()); diff != "" {
    36  		t.Error(diff)
    37  	}
    38  }
    39  
    40  func TestJSONBuiltinMarshalField(t *testing.T) {
    41  	var m runtime.JSONBuiltin
    42  	for _, fixt := range builtinFieldFixtures {
    43  		buf, err := m.Marshal(fixt.data)
    44  		if err != nil {
    45  			t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
    46  		}
    47  		if got, want := string(buf), fixt.json; got != want {
    48  			t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
    49  		}
    50  	}
    51  }
    52  
    53  func TestJSONBuiltinMarshalFieldKnownErrors(t *testing.T) {
    54  	var m runtime.JSONBuiltin
    55  	for _, fixt := range builtinKnownErrors {
    56  		buf, err := m.Marshal(fixt.data)
    57  		if err != nil {
    58  			t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
    59  		}
    60  		if got, want := string(buf), fixt.json; got == want {
    61  			t.Errorf("surprisingly got = %q; as want %q; data = %#v", got, want, fixt.data)
    62  		}
    63  	}
    64  }
    65  
    66  func TestJSONBuiltinsnmarshal(t *testing.T) {
    67  	var (
    68  		m   runtime.JSONBuiltin
    69  		got = new(examplepb.SimpleMessage)
    70  
    71  		data = []byte(`{"id": "foo"}`)
    72  	)
    73  	if err := m.Unmarshal(data, got); err != nil {
    74  		t.Errorf("m.Unmarshal(%q, got) failed with %v; want success", data, err)
    75  	}
    76  
    77  	want := &examplepb.SimpleMessage{
    78  		Id: "foo",
    79  	}
    80  	if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
    81  		t.Errorf(diff)
    82  	}
    83  }
    84  
    85  func TestJSONBuiltinUnmarshalField(t *testing.T) {
    86  	var m runtime.JSONBuiltin
    87  	for _, fixt := range builtinFieldFixtures {
    88  		dest := alloc(reflect.TypeOf(fixt.data))
    89  		if err := m.Unmarshal([]byte(fixt.json), dest.Interface()); err != nil {
    90  			t.Errorf("m.Unmarshal(%q, dest) failed with %v; want success", fixt.json, err)
    91  		}
    92  
    93  		got, want := dest.Elem().Interface(), fixt.data
    94  		if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
    95  			t.Error(diff)
    96  		}
    97  	}
    98  }
    99  
   100  func alloc(t reflect.Type) reflect.Value {
   101  	if t == nil {
   102  		return reflect.ValueOf(new(interface{}))
   103  	}
   104  	return reflect.New(t)
   105  }
   106  
   107  func TestJSONBuiltinUnmarshalFieldKnownErrors(t *testing.T) {
   108  	var m runtime.JSONBuiltin
   109  	for _, fixt := range builtinKnownErrors {
   110  		dest := reflect.New(reflect.TypeOf(fixt.data))
   111  		if err := m.Unmarshal([]byte(fixt.json), dest.Interface()); err == nil {
   112  			t.Errorf("m.Unmarshal(%q, dest) succeeded; want ane error", fixt.json)
   113  		}
   114  	}
   115  }
   116  
   117  func TestJSONBuiltinEncoder(t *testing.T) {
   118  	var m runtime.JSONBuiltin
   119  	msg := &examplepb.SimpleMessage{
   120  		Id: "foo",
   121  	}
   122  
   123  	var buf bytes.Buffer
   124  	enc := m.NewEncoder(&buf)
   125  	if err := enc.Encode(msg); err != nil {
   126  		t.Errorf("enc.Encode(%v) failed with %v; want success", msg, err)
   127  	}
   128  
   129  	got := new(examplepb.SimpleMessage)
   130  	if err := json.Unmarshal(buf.Bytes(), got); err != nil {
   131  		t.Errorf("json.Unmarshal(%q, got) failed with %v; want success", buf.String(), err)
   132  	}
   133  	if diff := cmp.Diff(got, msg, protocmp.Transform()); diff != "" {
   134  		t.Error(diff)
   135  	}
   136  }
   137  
   138  func TestJSONBuiltinEncoderFields(t *testing.T) {
   139  	var m runtime.JSONBuiltin
   140  	for _, fixt := range builtinFieldFixtures {
   141  		var buf bytes.Buffer
   142  		enc := m.NewEncoder(&buf)
   143  		if err := enc.Encode(fixt.data); err != nil {
   144  			t.Errorf("enc.Encode(%#v) failed with %v; want success", fixt.data, err)
   145  		}
   146  
   147  		if got, want := buf.String(), fixt.json+"\n"; got != want {
   148  			t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
   149  		}
   150  	}
   151  }
   152  
   153  func TestJSONBuiltinDecoder(t *testing.T) {
   154  	var (
   155  		m   runtime.JSONBuiltin
   156  		got = new(examplepb.SimpleMessage)
   157  
   158  		data = `{"id": "foo"}`
   159  	)
   160  	r := strings.NewReader(data)
   161  	dec := m.NewDecoder(r)
   162  	if err := dec.Decode(got); err != nil {
   163  		t.Errorf("m.Unmarshal(got) failed with %v; want success", err)
   164  	}
   165  
   166  	want := &examplepb.SimpleMessage{
   167  		Id: "foo",
   168  	}
   169  	if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
   170  		t.Errorf("got = %v; want = %v", got, want)
   171  	}
   172  }
   173  
   174  func TestJSONBuiltinDecoderFields(t *testing.T) {
   175  	var m runtime.JSONBuiltin
   176  	for _, fixt := range builtinFieldFixtures {
   177  		r := strings.NewReader(fixt.json)
   178  		dec := m.NewDecoder(r)
   179  		dest := alloc(reflect.TypeOf(fixt.data))
   180  		if err := dec.Decode(dest.Interface()); err != nil {
   181  			t.Errorf("dec.Decode(dest) failed with %v; want success; data = %q", err, fixt.json)
   182  		}
   183  
   184  		got, want := dest.Elem().Interface(), fixt.data
   185  		if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
   186  			t.Error(diff)
   187  		}
   188  	}
   189  }
   190  
   191  var (
   192  	builtinFieldFixtures = []struct {
   193  		data interface{}
   194  		json string
   195  	}{
   196  		{data: "", json: `""`},
   197  		{data: proto.String(""), json: `""`},
   198  		{data: "foo", json: `"foo"`},
   199  		{data: []byte("foo"), json: `"Zm9v"`},
   200  		{data: []byte{}, json: `""`},
   201  		{data: proto.String("foo"), json: `"foo"`},
   202  		{data: int32(-1), json: "-1"},
   203  		{data: proto.Int32(-1), json: "-1"},
   204  		{data: int64(-1), json: "-1"},
   205  		{data: proto.Int64(-1), json: "-1"},
   206  		{data: uint32(123), json: "123"},
   207  		{data: proto.Uint32(123), json: "123"},
   208  		{data: uint64(123), json: "123"},
   209  		{data: proto.Uint64(123), json: "123"},
   210  		{data: float32(-1.5), json: "-1.5"},
   211  		{data: proto.Float32(-1.5), json: "-1.5"},
   212  		{data: float64(-1.5), json: "-1.5"},
   213  		{data: proto.Float64(-1.5), json: "-1.5"},
   214  		{data: true, json: "true"},
   215  		{data: proto.Bool(true), json: "true"},
   216  		{data: (*string)(nil), json: "null"},
   217  		{data: new(emptypb.Empty), json: "{}"},
   218  		{data: examplepb.NumericEnum_ONE, json: "1"},
   219  		{data: nil, json: "null"},
   220  		{data: (*string)(nil), json: "null"},
   221  		{data: []interface{}{nil, "foo", -1.0, 1.234, true}, json: `[null,"foo",-1,1.234,true]`},
   222  		{
   223  			data: map[string]interface{}{"bar": nil, "baz": -1.0, "fiz": 1.234, "foo": true},
   224  			json: `{"bar":null,"baz":-1,"fiz":1.234,"foo":true}`,
   225  		},
   226  		{
   227  			data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
   228  			json: "1",
   229  		},
   230  	}
   231  	builtinKnownErrors = []struct {
   232  		data interface{}
   233  		json string
   234  	}{
   235  		{data: examplepb.NumericEnum_ONE, json: "ONE"},
   236  		{
   237  			data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
   238  			json: "ONE",
   239  		},
   240  		{
   241  			data: &examplepb.ABitOfEverything_OneofString{OneofString: "abc"},
   242  			json: `"abc"`,
   243  		},
   244  		{
   245  			data: &timestamppb.Timestamp{
   246  				Seconds: 1462875553,
   247  				Nanos:   123000000,
   248  			},
   249  			json: `"2016-05-10T10:19:13.123Z"`,
   250  		},
   251  		{
   252  			data: wrapperspb.Int32(123),
   253  			json: "123",
   254  		},
   255  	}
   256  )