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 }