github.com/whiteCcinn/protobuf-go@v1.0.9/types/known/structpb/struct_test.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package structpb_test
     6  
     7  import (
     8  	"encoding/json"
     9  	"math"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"github.com/google/go-cmp/cmp/cmpopts"
    14  	"github.com/whiteCcinn/protobuf-go/reflect/protoreflect"
    15  	"github.com/whiteCcinn/protobuf-go/testing/protocmp"
    16  
    17  	spb "github.com/whiteCcinn/protobuf-go/types/known/structpb"
    18  )
    19  
    20  var equateJSON = cmpopts.AcyclicTransformer("UnmarshalJSON", func(in []byte) (out interface{}) {
    21  	if err := json.Unmarshal(in, &out); err != nil {
    22  		return in
    23  	}
    24  	return out
    25  })
    26  
    27  func TestToStruct(t *testing.T) {
    28  	tests := []struct {
    29  		in      map[string]interface{}
    30  		wantPB  *spb.Struct
    31  		wantErr error
    32  	}{{
    33  		in:     nil,
    34  		wantPB: new(spb.Struct),
    35  	}, {
    36  		in:     make(map[string]interface{}),
    37  		wantPB: new(spb.Struct),
    38  	}, {
    39  		in: map[string]interface{}{
    40  			"nil":     nil,
    41  			"bool":    bool(false),
    42  			"int":     int(-123),
    43  			"int32":   int32(math.MinInt32),
    44  			"int64":   int64(math.MinInt64),
    45  			"uint":    uint(123),
    46  			"uint32":  uint32(math.MaxInt32),
    47  			"uint64":  uint64(math.MaxInt64),
    48  			"float32": float32(123.456),
    49  			"float64": float64(123.456),
    50  			"string":  string("hello, world!"),
    51  			"bytes":   []byte("\xde\xad\xbe\xef"),
    52  			"map":     map[string]interface{}{"k1": "v1", "k2": "v2"},
    53  			"slice":   []interface{}{"one", "two", "three"},
    54  		},
    55  		wantPB: &spb.Struct{Fields: map[string]*spb.Value{
    56  			"nil":     spb.NewNullValue(),
    57  			"bool":    spb.NewBoolValue(false),
    58  			"int":     spb.NewNumberValue(float64(-123)),
    59  			"int32":   spb.NewNumberValue(float64(math.MinInt32)),
    60  			"int64":   spb.NewNumberValue(float64(math.MinInt64)),
    61  			"uint":    spb.NewNumberValue(float64(123)),
    62  			"uint32":  spb.NewNumberValue(float64(math.MaxInt32)),
    63  			"uint64":  spb.NewNumberValue(float64(math.MaxInt64)),
    64  			"float32": spb.NewNumberValue(float64(float32(123.456))),
    65  			"float64": spb.NewNumberValue(float64(float64(123.456))),
    66  			"string":  spb.NewStringValue("hello, world!"),
    67  			"bytes":   spb.NewStringValue("3q2+7w=="),
    68  			"map": spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
    69  				"k1": spb.NewStringValue("v1"),
    70  				"k2": spb.NewStringValue("v2"),
    71  			}}),
    72  			"slice": spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
    73  				spb.NewStringValue("one"),
    74  				spb.NewStringValue("two"),
    75  				spb.NewStringValue("three"),
    76  			}}),
    77  		}},
    78  	}, {
    79  		in:      map[string]interface{}{"\xde\xad\xbe\xef": "<invalid UTF-8>"},
    80  		wantErr: cmpopts.AnyError,
    81  	}, {
    82  		in:      map[string]interface{}{"<invalid UTF-8>": "\xde\xad\xbe\xef"},
    83  		wantErr: cmpopts.AnyError,
    84  	}, {
    85  		in:      map[string]interface{}{"key": protoreflect.Name("named string")},
    86  		wantErr: cmpopts.AnyError,
    87  	}}
    88  
    89  	for _, tt := range tests {
    90  		gotPB, gotErr := spb.NewStruct(tt.in)
    91  		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
    92  			t.Errorf("NewStruct(%v) output mismatch (-want +got):\n%s", tt.in, diff)
    93  		}
    94  		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
    95  			t.Errorf("NewStruct(%v) error mismatch (-want +got):\n%s", tt.in, diff)
    96  		}
    97  	}
    98  }
    99  
   100  func TestFromStruct(t *testing.T) {
   101  	tests := []struct {
   102  		in   *spb.Struct
   103  		want map[string]interface{}
   104  	}{{
   105  		in:   nil,
   106  		want: make(map[string]interface{}),
   107  	}, {
   108  		in:   new(spb.Struct),
   109  		want: make(map[string]interface{}),
   110  	}, {
   111  		in:   &spb.Struct{Fields: make(map[string]*spb.Value)},
   112  		want: make(map[string]interface{}),
   113  	}, {
   114  		in: &spb.Struct{Fields: map[string]*spb.Value{
   115  			"nil":     spb.NewNullValue(),
   116  			"bool":    spb.NewBoolValue(false),
   117  			"int":     spb.NewNumberValue(float64(-123)),
   118  			"int32":   spb.NewNumberValue(float64(math.MinInt32)),
   119  			"int64":   spb.NewNumberValue(float64(math.MinInt64)),
   120  			"uint":    spb.NewNumberValue(float64(123)),
   121  			"uint32":  spb.NewNumberValue(float64(math.MaxInt32)),
   122  			"uint64":  spb.NewNumberValue(float64(math.MaxInt64)),
   123  			"float32": spb.NewNumberValue(float64(float32(123.456))),
   124  			"float64": spb.NewNumberValue(float64(float64(123.456))),
   125  			"string":  spb.NewStringValue("hello, world!"),
   126  			"bytes":   spb.NewStringValue("3q2+7w=="),
   127  			"map": spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
   128  				"k1": spb.NewStringValue("v1"),
   129  				"k2": spb.NewStringValue("v2"),
   130  			}}),
   131  			"slice": spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   132  				spb.NewStringValue("one"),
   133  				spb.NewStringValue("two"),
   134  				spb.NewStringValue("three"),
   135  			}}),
   136  		}},
   137  		want: map[string]interface{}{
   138  			"nil":     nil,
   139  			"bool":    bool(false),
   140  			"int":     float64(-123),
   141  			"int32":   float64(math.MinInt32),
   142  			"int64":   float64(math.MinInt64),
   143  			"uint":    float64(123),
   144  			"uint32":  float64(math.MaxInt32),
   145  			"uint64":  float64(math.MaxInt64),
   146  			"float32": float64(float32(123.456)),
   147  			"float64": float64(float64(123.456)),
   148  			"string":  string("hello, world!"),
   149  			"bytes":   string("3q2+7w=="),
   150  			"map":     map[string]interface{}{"k1": "v1", "k2": "v2"},
   151  			"slice":   []interface{}{"one", "two", "three"},
   152  		},
   153  	}}
   154  
   155  	for _, tt := range tests {
   156  		got := tt.in.AsMap()
   157  		if diff := cmp.Diff(tt.want, got); diff != "" {
   158  			t.Errorf("AsMap(%v) mismatch (-want +got):\n%s", tt.in, diff)
   159  		}
   160  		gotJSON, err := json.Marshal(got)
   161  		if err != nil {
   162  			t.Errorf("Marshal error: %v", err)
   163  		}
   164  		wantJSON, err := tt.in.MarshalJSON()
   165  		if err != nil {
   166  			t.Errorf("Marshal error: %v", err)
   167  		}
   168  		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" {
   169  			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
   170  		}
   171  	}
   172  }
   173  
   174  func TestToListValue(t *testing.T) {
   175  	tests := []struct {
   176  		in      []interface{}
   177  		wantPB  *spb.ListValue
   178  		wantErr error
   179  	}{{
   180  		in:     nil,
   181  		wantPB: new(spb.ListValue),
   182  	}, {
   183  		in:     make([]interface{}, 0),
   184  		wantPB: new(spb.ListValue),
   185  	}, {
   186  		in: []interface{}{
   187  			nil,
   188  			bool(false),
   189  			int(-123),
   190  			int32(math.MinInt32),
   191  			int64(math.MinInt64),
   192  			uint(123),
   193  			uint32(math.MaxInt32),
   194  			uint64(math.MaxInt64),
   195  			float32(123.456),
   196  			float64(123.456),
   197  			string("hello, world!"),
   198  			[]byte("\xde\xad\xbe\xef"),
   199  			map[string]interface{}{"k1": "v1", "k2": "v2"},
   200  			[]interface{}{"one", "two", "three"},
   201  		},
   202  		wantPB: &spb.ListValue{Values: []*spb.Value{
   203  			spb.NewNullValue(),
   204  			spb.NewBoolValue(false),
   205  			spb.NewNumberValue(float64(-123)),
   206  			spb.NewNumberValue(float64(math.MinInt32)),
   207  			spb.NewNumberValue(float64(math.MinInt64)),
   208  			spb.NewNumberValue(float64(123)),
   209  			spb.NewNumberValue(float64(math.MaxInt32)),
   210  			spb.NewNumberValue(float64(math.MaxInt64)),
   211  			spb.NewNumberValue(float64(float32(123.456))),
   212  			spb.NewNumberValue(float64(float64(123.456))),
   213  			spb.NewStringValue("hello, world!"),
   214  			spb.NewStringValue("3q2+7w=="),
   215  			spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
   216  				"k1": spb.NewStringValue("v1"),
   217  				"k2": spb.NewStringValue("v2"),
   218  			}}),
   219  			spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   220  				spb.NewStringValue("one"),
   221  				spb.NewStringValue("two"),
   222  				spb.NewStringValue("three"),
   223  			}}),
   224  		}},
   225  	}, {
   226  		in:      []interface{}{"\xde\xad\xbe\xef"},
   227  		wantErr: cmpopts.AnyError,
   228  	}, {
   229  		in:      []interface{}{protoreflect.Name("named string")},
   230  		wantErr: cmpopts.AnyError,
   231  	}}
   232  
   233  	for _, tt := range tests {
   234  		gotPB, gotErr := spb.NewList(tt.in)
   235  		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
   236  			t.Errorf("NewListValue(%v) output mismatch (-want +got):\n%s", tt.in, diff)
   237  		}
   238  		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
   239  			t.Errorf("NewListValue(%v) error mismatch (-want +got):\n%s", tt.in, diff)
   240  		}
   241  	}
   242  }
   243  
   244  func TestFromListValue(t *testing.T) {
   245  	tests := []struct {
   246  		in   *spb.ListValue
   247  		want []interface{}
   248  	}{{
   249  		in:   nil,
   250  		want: make([]interface{}, 0),
   251  	}, {
   252  		in:   new(spb.ListValue),
   253  		want: make([]interface{}, 0),
   254  	}, {
   255  		in:   &spb.ListValue{Values: make([]*spb.Value, 0)},
   256  		want: make([]interface{}, 0),
   257  	}, {
   258  		in: &spb.ListValue{Values: []*spb.Value{
   259  			spb.NewNullValue(),
   260  			spb.NewBoolValue(false),
   261  			spb.NewNumberValue(float64(-123)),
   262  			spb.NewNumberValue(float64(math.MinInt32)),
   263  			spb.NewNumberValue(float64(math.MinInt64)),
   264  			spb.NewNumberValue(float64(123)),
   265  			spb.NewNumberValue(float64(math.MaxInt32)),
   266  			spb.NewNumberValue(float64(math.MaxInt64)),
   267  			spb.NewNumberValue(float64(float32(123.456))),
   268  			spb.NewNumberValue(float64(float64(123.456))),
   269  			spb.NewStringValue("hello, world!"),
   270  			spb.NewStringValue("3q2+7w=="),
   271  			spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
   272  				"k1": spb.NewStringValue("v1"),
   273  				"k2": spb.NewStringValue("v2"),
   274  			}}),
   275  			spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   276  				spb.NewStringValue("one"),
   277  				spb.NewStringValue("two"),
   278  				spb.NewStringValue("three"),
   279  			}}),
   280  		}},
   281  		want: []interface{}{
   282  			nil,
   283  			bool(false),
   284  			float64(-123),
   285  			float64(math.MinInt32),
   286  			float64(math.MinInt64),
   287  			float64(123),
   288  			float64(math.MaxInt32),
   289  			float64(math.MaxInt64),
   290  			float64(float32(123.456)),
   291  			float64(float64(123.456)),
   292  			string("hello, world!"),
   293  			string("3q2+7w=="),
   294  			map[string]interface{}{"k1": "v1", "k2": "v2"},
   295  			[]interface{}{"one", "two", "three"},
   296  		},
   297  	}}
   298  
   299  	for _, tt := range tests {
   300  		got := tt.in.AsSlice()
   301  		if diff := cmp.Diff(tt.want, got); diff != "" {
   302  			t.Errorf("AsSlice(%v) mismatch (-want +got):\n%s", tt.in, diff)
   303  		}
   304  		gotJSON, err := json.Marshal(got)
   305  		if err != nil {
   306  			t.Errorf("Marshal error: %v", err)
   307  		}
   308  		wantJSON, err := tt.in.MarshalJSON()
   309  		if err != nil {
   310  			t.Errorf("Marshal error: %v", err)
   311  		}
   312  		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" {
   313  			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
   314  		}
   315  	}
   316  }
   317  
   318  func TestToValue(t *testing.T) {
   319  	tests := []struct {
   320  		in      interface{}
   321  		wantPB  *spb.Value
   322  		wantErr error
   323  	}{{
   324  		in:     nil,
   325  		wantPB: spb.NewNullValue(),
   326  	}, {
   327  		in:     bool(false),
   328  		wantPB: spb.NewBoolValue(false),
   329  	}, {
   330  		in:     int(-123),
   331  		wantPB: spb.NewNumberValue(float64(-123)),
   332  	}, {
   333  		in:     int32(math.MinInt32),
   334  		wantPB: spb.NewNumberValue(float64(math.MinInt32)),
   335  	}, {
   336  		in:     int64(math.MinInt64),
   337  		wantPB: spb.NewNumberValue(float64(math.MinInt64)),
   338  	}, {
   339  		in:     uint(123),
   340  		wantPB: spb.NewNumberValue(float64(123)),
   341  	}, {
   342  		in:     uint32(math.MaxInt32),
   343  		wantPB: spb.NewNumberValue(float64(math.MaxInt32)),
   344  	}, {
   345  		in:     uint64(math.MaxInt64),
   346  		wantPB: spb.NewNumberValue(float64(math.MaxInt64)),
   347  	}, {
   348  		in:     float32(123.456),
   349  		wantPB: spb.NewNumberValue(float64(float32(123.456))),
   350  	}, {
   351  		in:     float64(123.456),
   352  		wantPB: spb.NewNumberValue(float64(float64(123.456))),
   353  	}, {
   354  		in:     string("hello, world!"),
   355  		wantPB: spb.NewStringValue("hello, world!"),
   356  	}, {
   357  		in:     []byte("\xde\xad\xbe\xef"),
   358  		wantPB: spb.NewStringValue("3q2+7w=="),
   359  	}, {
   360  		in:     map[string]interface{}(nil),
   361  		wantPB: spb.NewStructValue(nil),
   362  	}, {
   363  		in:     make(map[string]interface{}),
   364  		wantPB: spb.NewStructValue(nil),
   365  	}, {
   366  		in: map[string]interface{}{"k1": "v1", "k2": "v2"},
   367  		wantPB: spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
   368  			"k1": spb.NewStringValue("v1"),
   369  			"k2": spb.NewStringValue("v2"),
   370  		}}),
   371  	}, {
   372  		in:     []interface{}(nil),
   373  		wantPB: spb.NewListValue(nil),
   374  	}, {
   375  		in:     make([]interface{}, 0),
   376  		wantPB: spb.NewListValue(nil),
   377  	}, {
   378  		in: []interface{}{"one", "two", "three"},
   379  		wantPB: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   380  			spb.NewStringValue("one"),
   381  			spb.NewStringValue("two"),
   382  			spb.NewStringValue("three"),
   383  		}}),
   384  	}, {
   385  		in:      "\xde\xad\xbe\xef",
   386  		wantErr: cmpopts.AnyError,
   387  	}, {
   388  		in:      protoreflect.Name("named string"),
   389  		wantErr: cmpopts.AnyError,
   390  	}}
   391  
   392  	for _, tt := range tests {
   393  		gotPB, gotErr := spb.NewValue(tt.in)
   394  		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
   395  			t.Errorf("NewValue(%v) output mismatch (-want +got):\n%s", tt.in, diff)
   396  		}
   397  		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
   398  			t.Errorf("NewValue(%v) error mismatch (-want +got):\n%s", tt.in, diff)
   399  		}
   400  	}
   401  }
   402  
   403  func TestFromValue(t *testing.T) {
   404  	tests := []struct {
   405  		in   *spb.Value
   406  		want interface{}
   407  	}{{
   408  		in:   nil,
   409  		want: nil,
   410  	}, {
   411  		in:   new(spb.Value),
   412  		want: nil,
   413  	}, {
   414  		in:   &spb.Value{Kind: (*spb.Value_NullValue)(nil)},
   415  		want: nil,
   416  	}, {
   417  		in:   spb.NewNullValue(),
   418  		want: nil,
   419  	}, {
   420  		in:   &spb.Value{Kind: &spb.Value_NullValue{NullValue: math.MinInt32}},
   421  		want: nil,
   422  	}, {
   423  		in:   &spb.Value{Kind: (*spb.Value_BoolValue)(nil)},
   424  		want: nil,
   425  	}, {
   426  		in:   spb.NewBoolValue(false),
   427  		want: bool(false),
   428  	}, {
   429  		in:   &spb.Value{Kind: (*spb.Value_NumberValue)(nil)},
   430  		want: nil,
   431  	}, {
   432  		in:   spb.NewNumberValue(float64(math.MinInt32)),
   433  		want: float64(math.MinInt32),
   434  	}, {
   435  		in:   spb.NewNumberValue(float64(math.MinInt64)),
   436  		want: float64(math.MinInt64),
   437  	}, {
   438  		in:   spb.NewNumberValue(float64(123)),
   439  		want: float64(123),
   440  	}, {
   441  		in:   spb.NewNumberValue(float64(math.MaxInt32)),
   442  		want: float64(math.MaxInt32),
   443  	}, {
   444  		in:   spb.NewNumberValue(float64(math.MaxInt64)),
   445  		want: float64(math.MaxInt64),
   446  	}, {
   447  		in:   spb.NewNumberValue(float64(float32(123.456))),
   448  		want: float64(float32(123.456)),
   449  	}, {
   450  		in:   spb.NewNumberValue(float64(float64(123.456))),
   451  		want: float64(float64(123.456)),
   452  	}, {
   453  		in:   spb.NewNumberValue(math.NaN()),
   454  		want: string("NaN"),
   455  	}, {
   456  		in:   spb.NewNumberValue(math.Inf(-1)),
   457  		want: string("-Infinity"),
   458  	}, {
   459  		in:   spb.NewNumberValue(math.Inf(+1)),
   460  		want: string("Infinity"),
   461  	}, {
   462  		in:   &spb.Value{Kind: (*spb.Value_StringValue)(nil)},
   463  		want: nil,
   464  	}, {
   465  		in:   spb.NewStringValue("hello, world!"),
   466  		want: string("hello, world!"),
   467  	}, {
   468  		in:   spb.NewStringValue("3q2+7w=="),
   469  		want: string("3q2+7w=="),
   470  	}, {
   471  		in:   &spb.Value{Kind: (*spb.Value_StructValue)(nil)},
   472  		want: nil,
   473  	}, {
   474  		in:   &spb.Value{Kind: &spb.Value_StructValue{}},
   475  		want: make(map[string]interface{}),
   476  	}, {
   477  		in: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   478  			spb.NewStringValue("one"),
   479  			spb.NewStringValue("two"),
   480  			spb.NewStringValue("three"),
   481  		}}),
   482  		want: []interface{}{"one", "two", "three"},
   483  	}, {
   484  		in:   &spb.Value{Kind: (*spb.Value_ListValue)(nil)},
   485  		want: nil,
   486  	}, {
   487  		in:   &spb.Value{Kind: &spb.Value_ListValue{}},
   488  		want: make([]interface{}, 0),
   489  	}, {
   490  		in: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
   491  			spb.NewStringValue("one"),
   492  			spb.NewStringValue("two"),
   493  			spb.NewStringValue("three"),
   494  		}}),
   495  		want: []interface{}{"one", "two", "three"},
   496  	}}
   497  
   498  	for _, tt := range tests {
   499  		got := tt.in.AsInterface()
   500  		if diff := cmp.Diff(tt.want, got); diff != "" {
   501  			t.Errorf("AsInterface(%v) mismatch (-want +got):\n%s", tt.in, diff)
   502  		}
   503  		gotJSON, gotErr := json.Marshal(got)
   504  		if gotErr != nil {
   505  			t.Errorf("Marshal error: %v", gotErr)
   506  		}
   507  		wantJSON, wantErr := tt.in.MarshalJSON()
   508  		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" && wantErr == nil {
   509  			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
   510  		}
   511  	}
   512  }