github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/conversion/queryparams/convert_test.go (about) 1 /* 2 Copyright 2014 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 queryparams_test 18 19 import ( 20 "net/url" 21 "reflect" 22 "testing" 23 "time" 24 25 metav1 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1" 26 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/conversion/queryparams" 27 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/schema" 28 ) 29 30 type namedString string 31 type namedBool bool 32 33 type bar struct { 34 Float1 float32 `json:"float1"` 35 Float2 float64 `json:"float2"` 36 Int1 int64 `json:"int1,omitempty"` 37 Int2 int32 `json:"int2,omitempty"` 38 Int3 int16 `json:"int3,omitempty"` 39 Str1 string `json:"str1,omitempty"` 40 Ignored int 41 Ignored2 string 42 } 43 44 func (obj *bar) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } 45 46 type foo struct { 47 Str string `json:"str"` 48 Integer int `json:"integer,omitempty"` 49 Slice []string `json:"slice,omitempty"` 50 Boolean bool `json:"boolean,omitempty"` 51 NamedStr namedString `json:"namedStr,omitempty"` 52 NamedBool namedBool `json:"namedBool,omitempty"` 53 Foobar bar `json:"foobar,omitempty"` 54 Testmap map[string]string `json:"testmap,omitempty"` 55 } 56 57 func (obj *foo) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } 58 59 type baz struct { 60 Ptr *int `json:"ptr"` 61 Bptr *bool `json:"bptr,omitempty"` 62 } 63 64 func (obj *baz) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } 65 66 // childStructs tests some of the types we serialize to query params for log API calls 67 // notably, the nested time struct 68 type childStructs struct { 69 Container string `json:"container,omitempty"` 70 Follow bool `json:"follow,omitempty"` 71 Previous bool `json:"previous,omitempty"` 72 SinceSeconds *int64 `json:"sinceSeconds,omitempty"` 73 TailLines *int64 `json:"tailLines,omitempty"` 74 SinceTime *metav1.Time `json:"sinceTime,omitempty"` 75 EmptyTime *metav1.Time `json:"emptyTime"` 76 NonPointerTime metav1.Time `json:"nonPointerTime"` 77 } 78 79 func (obj *childStructs) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } 80 81 func validateResult(t *testing.T, input interface{}, actual, expected url.Values) { 82 local := url.Values{} 83 for k, v := range expected { 84 local[k] = v 85 } 86 for k, v := range actual { 87 if ev, ok := local[k]; !ok || !reflect.DeepEqual(ev, v) { 88 if !ok { 89 t.Errorf("%#v: actual value key %s not found in expected map", input, k) 90 } else { 91 t.Errorf("%#v: values don't match: actual: %#v, expected: %#v", input, v, ev) 92 } 93 } 94 delete(local, k) 95 } 96 if len(local) > 0 { 97 t.Errorf("%#v: expected map has keys that were not found in actual map: %#v", input, local) 98 } 99 } 100 101 func TestConvert(t *testing.T) { 102 sinceSeconds := int64(123) 103 tailLines := int64(0) 104 sinceTime := metav1.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC) 105 106 tests := []struct { 107 input interface{} 108 expected url.Values 109 }{ 110 { 111 input: &foo{ 112 Str: "hello", 113 }, 114 expected: url.Values{"str": {"hello"}}, 115 }, 116 { 117 input: &foo{ 118 Str: "test string", 119 Slice: []string{"one", "two", "three"}, 120 Integer: 234, 121 Boolean: true, 122 }, 123 expected: url.Values{"str": {"test string"}, "slice": {"one", "two", "three"}, "integer": {"234"}, "boolean": {"true"}}, 124 }, 125 { 126 input: &foo{ 127 Str: "named types", 128 NamedStr: "value1", 129 NamedBool: true, 130 }, 131 expected: url.Values{"str": {"named types"}, "namedStr": {"value1"}, "namedBool": {"true"}}, 132 }, 133 { 134 input: &foo{ 135 Str: "don't ignore embedded struct", 136 Foobar: bar{ 137 Float1: 5.0, 138 }, 139 }, 140 expected: url.Values{"str": {"don't ignore embedded struct"}, "float1": {"5"}, "float2": {"0"}}, 141 }, 142 { 143 // Ignore untagged fields 144 input: &bar{ 145 Float1: 23.5, 146 Float2: 100.7, 147 Int1: 1, 148 Int2: 2, 149 Int3: 3, 150 Ignored: 1, 151 Ignored2: "ignored", 152 }, 153 expected: url.Values{"float1": {"23.5"}, "float2": {"100.7"}, "int1": {"1"}, "int2": {"2"}, "int3": {"3"}}, 154 }, 155 { 156 // include fields that are not tagged omitempty 157 input: &foo{ 158 NamedStr: "named str", 159 }, 160 expected: url.Values{"str": {""}, "namedStr": {"named str"}}, 161 }, 162 { 163 input: &baz{ 164 Ptr: intp(5), 165 Bptr: boolp(true), 166 }, 167 expected: url.Values{"ptr": {"5"}, "bptr": {"true"}}, 168 }, 169 { 170 input: &baz{ 171 Bptr: boolp(true), 172 }, 173 expected: url.Values{"ptr": {""}, "bptr": {"true"}}, 174 }, 175 { 176 input: &baz{ 177 Ptr: intp(5), 178 }, 179 expected: url.Values{"ptr": {"5"}}, 180 }, 181 { 182 input: &childStructs{ 183 Container: "mycontainer", 184 Follow: true, 185 Previous: true, 186 SinceSeconds: &sinceSeconds, 187 TailLines: nil, 188 SinceTime: &sinceTime, // test a custom marshaller 189 EmptyTime: nil, // test a nil custom marshaller without omitempty 190 NonPointerTime: sinceTime, 191 }, 192 expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "sinceTime": {"2000-01-01T12:34:56Z"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, 193 }, 194 { 195 input: &childStructs{ 196 Container: "mycontainer", 197 Follow: true, 198 Previous: true, 199 SinceSeconds: &sinceSeconds, 200 TailLines: &tailLines, 201 SinceTime: nil, // test a nil custom marshaller with omitempty 202 NonPointerTime: sinceTime, 203 }, 204 expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "tailLines": {"0"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, 205 }, 206 } 207 208 for _, test := range tests { 209 result, err := queryparams.Convert(test.input) 210 if err != nil { 211 t.Errorf("Unexpected error while converting %#v: %v", test.input, err) 212 } 213 validateResult(t, test.input, result, test.expected) 214 } 215 } 216 217 func intp(n int) *int { return &n } 218 219 func boolp(b bool) *bool { return &b }