...

Source file src/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache_test.go

Documentation: sigs.k8s.io/structured-merge-diff/v4/value

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package value
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  type CustomValue struct {
    25  	data []byte
    26  }
    27  
    28  // MarshalJSON has a value receiver on this type.
    29  func (c CustomValue) MarshalJSON() ([]byte, error) {
    30  	return c.data, nil
    31  }
    32  
    33  type CustomPointer struct {
    34  	data []byte
    35  }
    36  
    37  // MarshalJSON has a pointer receiver on this type.
    38  func (c *CustomPointer) MarshalJSON() ([]byte, error) {
    39  	return c.data, nil
    40  }
    41  
    42  func TestToUnstructured(t *testing.T) {
    43  	testcases := []struct {
    44  		Data     string
    45  		Expected interface{}
    46  	}{
    47  		{Data: `null`, Expected: nil},
    48  		{Data: `true`, Expected: true},
    49  		{Data: `false`, Expected: false},
    50  		{Data: `[]`, Expected: []interface{}{}},
    51  		{Data: `[1]`, Expected: []interface{}{int64(1)}},
    52  		{Data: `{}`, Expected: map[string]interface{}{}},
    53  		{Data: `{"a":1}`, Expected: map[string]interface{}{"a": int64(1)}},
    54  		{Data: `0`, Expected: int64(0)},
    55  		{Data: `0.0`, Expected: float64(0)},
    56  	}
    57  
    58  	for _, tc := range testcases {
    59  		tc := tc
    60  		t.Run(tc.Data, func(t *testing.T) {
    61  			t.Parallel()
    62  			custom := []interface{}{
    63  				CustomValue{data: []byte(tc.Data)},
    64  				&CustomValue{data: []byte(tc.Data)},
    65  				&CustomPointer{data: []byte(tc.Data)},
    66  			}
    67  			for _, custom := range custom {
    68  				rv := reflect.ValueOf(custom)
    69  				result, err := TypeReflectEntryOf(rv.Type()).ToUnstructured(rv)
    70  				if err != nil {
    71  					t.Fatal(err)
    72  				}
    73  				if !reflect.DeepEqual(result, tc.Expected) {
    74  					t.Errorf("expected %#v but got %#v", tc.Expected, result)
    75  				}
    76  			}
    77  		})
    78  	}
    79  }
    80  
    81  func TestTypeReflectEntryOf(t *testing.T) {
    82  	testString := ""
    83  	tests := map[string]struct {
    84  		arg  interface{}
    85  		want *TypeReflectCacheEntry
    86  	}{
    87  		"StructWithStringField": {
    88  			arg: struct {
    89  				F1 string `json:"f1"`
    90  			}{},
    91  			want: &TypeReflectCacheEntry{
    92  				structFields: map[string]*FieldCacheEntry{
    93  					"f1": {
    94  						JsonName:  "f1",
    95  						fieldPath: [][]int{{0}},
    96  						fieldType: reflect.TypeOf(testString),
    97  						TypeEntry: &TypeReflectCacheEntry{},
    98  					},
    99  				},
   100  				orderedStructFields: []*FieldCacheEntry{
   101  					{
   102  						JsonName:  "f1",
   103  						fieldPath: [][]int{{0}},
   104  						fieldType: reflect.TypeOf(testString),
   105  						TypeEntry: &TypeReflectCacheEntry{},
   106  					},
   107  				},
   108  			},
   109  		},
   110  		"StructWith*StringFieldOmitempty": {
   111  			arg: struct {
   112  				F1 *string `json:"f1,omitempty"`
   113  			}{},
   114  			want: &TypeReflectCacheEntry{
   115  				structFields: map[string]*FieldCacheEntry{
   116  					"f1": {
   117  						JsonName:    "f1",
   118  						isOmitEmpty: true,
   119  						fieldPath:   [][]int{{0}},
   120  						fieldType:   reflect.TypeOf(&testString),
   121  						TypeEntry:   &TypeReflectCacheEntry{},
   122  					},
   123  				},
   124  				orderedStructFields: []*FieldCacheEntry{
   125  					{
   126  						JsonName:    "f1",
   127  						isOmitEmpty: true,
   128  						fieldPath:   [][]int{{0}},
   129  						fieldType:   reflect.TypeOf(&testString),
   130  						TypeEntry:   &TypeReflectCacheEntry{},
   131  					},
   132  				},
   133  			},
   134  		},
   135  		"StructWithInlinedField": {
   136  			arg: struct {
   137  				F1 string `json:",inline"`
   138  			}{},
   139  			want: &TypeReflectCacheEntry{
   140  				structFields:        map[string]*FieldCacheEntry{},
   141  				orderedStructFields: []*FieldCacheEntry{},
   142  			},
   143  		},
   144  	}
   145  	for name, tt := range tests {
   146  		t.Run(name, func(t *testing.T) {
   147  			if got := TypeReflectEntryOf(reflect.TypeOf(tt.arg)); !reflect.DeepEqual(got, tt.want) {
   148  				t.Errorf("TypeReflectEntryOf() = %v, want %v", got, tt.want)
   149  			}
   150  		})
   151  	}
   152  }
   153  

View as plain text