github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/runtime/serializer/json/json_test.go (about)

     1  /*
     2  Copyright 2015 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 json_test
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	metav1 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1"
    26  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1/unstructured"
    27  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime"
    28  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/schema"
    29  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/serializer/json"
    30  	runtimetesting "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/testing"
    31  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/diff"
    32  )
    33  
    34  type testDecodable struct {
    35  	metav1.TypeMeta `json:",inline"`
    36  
    37  	Other     string
    38  	Value     int           `json:"value"`
    39  	Spec      DecodableSpec `json:"spec"`
    40  	Interface interface{}   `json:"interface"`
    41  }
    42  
    43  // DecodableSpec has 15 fields.
    44  type DecodableSpec struct {
    45  	A int `json:"A"`
    46  	B int `json:"B"`
    47  	C int `json:"C"`
    48  	D int `json:"D"`
    49  	E int `json:"E"`
    50  	F int `json:"F"`
    51  	G int `json:"G"`
    52  	H int `json:"h"`
    53  	I int `json:"i"`
    54  	J int `json:"j"`
    55  	K int `json:"k"`
    56  	L int `json:"l"`
    57  	M int `json:"m"`
    58  	N int `json:"n"`
    59  	O int `json:"o"`
    60  }
    61  
    62  func (d *testDecodable) DeepCopyObject() runtime.Object {
    63  	if d == nil {
    64  		return nil
    65  	}
    66  	out := new(testDecodable)
    67  	d.DeepCopyInto(out)
    68  	return out
    69  }
    70  func (d *testDecodable) DeepCopyInto(out *testDecodable) {
    71  	*out = *d
    72  	out.Other = d.Other
    73  	out.Value = d.Value
    74  	out.Spec = d.Spec
    75  	out.Interface = d.Interface
    76  	return
    77  }
    78  
    79  type testDecodeCoercion struct {
    80  	metav1.TypeMeta `json:",inline"`
    81  
    82  	Bool bool `json:"bool"`
    83  
    84  	Int   int `json:"int"`
    85  	Int32 int `json:"int32"`
    86  	Int64 int `json:"int64"`
    87  
    88  	Float32 float32 `json:"float32"`
    89  	Float64 float64 `json:"float64"`
    90  
    91  	String string `json:"string"`
    92  
    93  	Struct testDecodable `json:"struct"`
    94  
    95  	Array []string          `json:"array"`
    96  	Map   map[string]string `json:"map"`
    97  }
    98  
    99  func (d *testDecodeCoercion) DeepCopyObject() runtime.Object {
   100  	if d == nil {
   101  		return nil
   102  	}
   103  	out := new(testDecodeCoercion)
   104  	d.DeepCopyInto(out)
   105  	return out
   106  }
   107  func (d *testDecodeCoercion) DeepCopyInto(out *testDecodeCoercion) {
   108  	*out = *d
   109  	return
   110  }
   111  
   112  func TestDecode(t *testing.T) {
   113  	type testCase struct {
   114  		creater runtime.ObjectCreater
   115  		typer   runtime.ObjectTyper
   116  		yaml    bool
   117  		pretty  bool
   118  		strict  bool
   119  
   120  		data       []byte
   121  		defaultGVK *schema.GroupVersionKind
   122  		into       runtime.Object
   123  
   124  		errFn          func(error) bool
   125  		expectedObject runtime.Object
   126  		expectedGVK    *schema.GroupVersionKind
   127  	}
   128  
   129  	testCases := []testCase{
   130  		// missing metadata without into, typed creater
   131  		{
   132  			data: []byte("{}"),
   133  
   134  			expectedGVK: &schema.GroupVersionKind{},
   135  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   136  		},
   137  		{
   138  			data: []byte("{}"),
   139  
   140  			expectedGVK: &schema.GroupVersionKind{},
   141  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   142  			strict:      true,
   143  		},
   144  
   145  		{
   146  			data: []byte(`{"kind":"Foo"}`),
   147  
   148  			expectedGVK: &schema.GroupVersionKind{Kind: "Foo"},
   149  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
   150  		},
   151  		{
   152  			data: []byte(`{"kind":"Foo"}`),
   153  
   154  			expectedGVK: &schema.GroupVersionKind{Kind: "Foo"},
   155  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
   156  			strict:      true,
   157  		},
   158  
   159  		{
   160  			data: []byte(`{"apiVersion":"foo/v1"}`),
   161  
   162  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   163  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   164  		},
   165  		{
   166  			data: []byte(`{"apiVersion":"foo/v1"}`),
   167  
   168  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   169  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   170  			strict:      true,
   171  		},
   172  
   173  		{
   174  			data:    []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   175  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   176  			creater: &mockCreater{obj: &testDecodable{}},
   177  
   178  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "/v1", Kind: "Foo"}},
   179  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   180  		},
   181  		{
   182  			data:    []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   183  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   184  			creater: &mockCreater{obj: &testDecodable{}},
   185  
   186  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "/v1", Kind: "Foo"}},
   187  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   188  			strict:         true,
   189  		},
   190  
   191  		// missing metadata with unstructured into
   192  		{
   193  			data:  []byte("{}"),
   194  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   195  			into:  &unstructured.Unstructured{},
   196  
   197  			expectedGVK: &schema.GroupVersionKind{},
   198  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   199  		},
   200  		{
   201  			data:  []byte("{}"),
   202  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   203  			into:  &unstructured.Unstructured{},
   204  
   205  			expectedGVK: &schema.GroupVersionKind{},
   206  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   207  			strict:      true,
   208  		},
   209  
   210  		{
   211  			data:  []byte(`{"kind":"Foo"}`),
   212  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   213  			into:  &unstructured.Unstructured{},
   214  
   215  			expectedGVK:    &schema.GroupVersionKind{Kind: "Foo"},
   216  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"kind": "Foo"}},
   217  			// TODO(109023): expect this to error; unstructured decoding currently only requires kind to be set, not apiVersion
   218  		},
   219  		{
   220  			data:  []byte(`{"kind":"Foo"}`),
   221  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   222  			into:  &unstructured.Unstructured{},
   223  
   224  			expectedGVK:    &schema.GroupVersionKind{Kind: "Foo"},
   225  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"kind": "Foo"}},
   226  			strict:         true,
   227  			// TODO(109023): expect this to error; unstructured decoding currently only requires kind to be set, not apiVersion
   228  		},
   229  
   230  		{
   231  			data:  []byte(`{"apiVersion":"foo/v1"}`),
   232  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   233  			into:  &unstructured.Unstructured{},
   234  
   235  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   236  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   237  		},
   238  		{
   239  			data:  []byte(`{"apiVersion":"foo/v1"}`),
   240  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   241  			into:  &unstructured.Unstructured{},
   242  
   243  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   244  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   245  			strict:      true,
   246  		},
   247  
   248  		{
   249  			data:  []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   250  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   251  			into:  &unstructured.Unstructured{},
   252  
   253  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   254  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   255  		},
   256  		{
   257  			data:  []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   258  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   259  			into:  &unstructured.Unstructured{},
   260  
   261  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   262  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   263  			strict:         true,
   264  		},
   265  
   266  		// missing metadata with unstructured into providing metadata
   267  		{
   268  			data:  []byte("{}"),
   269  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   270  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   271  
   272  			expectedGVK: &schema.GroupVersionKind{},
   273  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   274  		},
   275  		{
   276  			data:  []byte("{}"),
   277  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   278  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   279  
   280  			expectedGVK: &schema.GroupVersionKind{},
   281  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   282  			strict:      true,
   283  		},
   284  
   285  		{
   286  			data:  []byte(`{"kind":"Foo"}`),
   287  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   288  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   289  
   290  			expectedGVK:    &schema.GroupVersionKind{Kind: "Foo"},
   291  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"kind": "Foo"}},
   292  			// TODO(109023): expect this to error; unstructured decoding currently only requires kind to be set, not apiVersion
   293  		},
   294  		{
   295  			data:  []byte(`{"kind":"Foo"}`),
   296  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   297  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   298  
   299  			expectedGVK:    &schema.GroupVersionKind{Kind: "Foo"},
   300  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"kind": "Foo"}},
   301  			strict:         true,
   302  			// TODO(109023): expect this to error; unstructured decoding currently only requires kind to be set, not apiVersion
   303  		},
   304  
   305  		{
   306  			data:  []byte(`{"apiVersion":"foo/v1"}`),
   307  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   308  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   309  
   310  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   311  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   312  		},
   313  		{
   314  			data:  []byte(`{"apiVersion":"foo/v1"}`),
   315  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   316  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   317  
   318  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   319  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   320  			strict:      true,
   321  		},
   322  
   323  		{
   324  			data:  []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   325  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   326  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   327  
   328  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   329  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   330  		},
   331  		{
   332  			data:  []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   333  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   334  			into:  &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "into/v1", "kind": "Into"}},
   335  
   336  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   337  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   338  			strict:         true,
   339  		},
   340  
   341  		// missing metadata without into, unstructured creater
   342  		{
   343  			data:    []byte("{}"),
   344  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   345  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   346  
   347  			expectedGVK: &schema.GroupVersionKind{},
   348  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   349  		},
   350  		{
   351  			data:    []byte("{}"),
   352  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   353  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   354  
   355  			expectedGVK: &schema.GroupVersionKind{},
   356  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   357  			strict:      true,
   358  		},
   359  
   360  		{
   361  			data:    []byte(`{"kind":"Foo"}`),
   362  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   363  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   364  
   365  			expectedGVK: &schema.GroupVersionKind{Kind: "Foo"},
   366  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
   367  		},
   368  		{
   369  			data:    []byte(`{"kind":"Foo"}`),
   370  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   371  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   372  
   373  			expectedGVK: &schema.GroupVersionKind{Kind: "Foo"},
   374  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
   375  			strict:      true,
   376  		},
   377  
   378  		{
   379  			data:    []byte(`{"apiVersion":"foo/v1"}`),
   380  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   381  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   382  
   383  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   384  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   385  		},
   386  		{
   387  			data:    []byte(`{"apiVersion":"foo/v1"}`),
   388  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   389  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   390  
   391  			expectedGVK: &schema.GroupVersionKind{Group: "foo", Version: "v1"},
   392  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
   393  			strict:      true,
   394  		},
   395  
   396  		{
   397  			data:    []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   398  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   399  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   400  
   401  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   402  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   403  		},
   404  		{
   405  			data:    []byte(`{"apiVersion":"/v1","kind":"Foo"}`),
   406  			typer:   &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   407  			creater: &mockCreater{obj: &unstructured.Unstructured{}},
   408  
   409  			expectedGVK:    &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Foo"},
   410  			expectedObject: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "/v1", "kind": "Foo"}},
   411  			strict:         true,
   412  		},
   413  
   414  		// creator errors
   415  		{
   416  			data:       []byte("{}"),
   417  			defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   418  			creater:    &mockCreater{err: fmt.Errorf("fake error")},
   419  
   420  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   421  			errFn:       func(err error) bool { return err.Error() == "fake error" },
   422  		},
   423  		{
   424  			data:       []byte("{}"),
   425  			defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   426  			creater:    &mockCreater{err: fmt.Errorf("fake error")},
   427  
   428  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   429  			errFn:       func(err error) bool { return err.Error() == "fake error" },
   430  		},
   431  		// creator typed
   432  		{
   433  			data:           []byte("{}"),
   434  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   435  			creater:        &mockCreater{obj: &testDecodable{}},
   436  			expectedObject: &testDecodable{},
   437  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   438  		},
   439  		{
   440  			data:           []byte("{}"),
   441  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   442  			creater:        &mockCreater{obj: &testDecodable{}},
   443  			expectedObject: &testDecodable{},
   444  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   445  			strict:         true,
   446  		},
   447  
   448  		// version without group is not defaulted
   449  		{
   450  			data:           []byte(`{"apiVersion":"blah"}`),
   451  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   452  			creater:        &mockCreater{obj: &testDecodable{}},
   453  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "blah"}},
   454  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "", Version: "blah"},
   455  		},
   456  		// group without version is defaulted
   457  		{
   458  			data:           []byte(`{"apiVersion":"other/"}`),
   459  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   460  			creater:        &mockCreater{obj: &testDecodable{}},
   461  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "other/"}},
   462  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   463  		},
   464  		// group version, kind is defaulted
   465  		{
   466  			data:           []byte(`{"apiVersion":"other1/blah1"}`),
   467  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   468  			creater:        &mockCreater{obj: &testDecodable{}},
   469  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "other1/blah1"}},
   470  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other1", Version: "blah1"},
   471  		},
   472  		// gvk all provided then not defaulted at all
   473  		{
   474  			data:           []byte(`{"kind":"Test","apiVersion":"other/blah"}`),
   475  			defaultGVK:     &schema.GroupVersionKind{Kind: "Test1", Group: "other1", Version: "blah1"},
   476  			creater:        &mockCreater{obj: &testDecodable{}},
   477  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"}},
   478  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   479  		},
   480  		//gvk defaulting if kind not provided in data and defaultGVK use into's kind
   481  		{
   482  			data:           []byte(`{"apiVersion":"b1/c1"}`),
   483  			into:           &testDecodable{TypeMeta: metav1.TypeMeta{Kind: "a3", APIVersion: "b1/c1"}},
   484  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"}},
   485  			defaultGVK:     nil,
   486  			creater:        &mockCreater{obj: &testDecodable{}},
   487  			expectedObject: &testDecodable{TypeMeta: metav1.TypeMeta{Kind: "a3", APIVersion: "b1/c1"}},
   488  			expectedGVK:    &schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"},
   489  		},
   490  
   491  		// accept runtime.Unknown as into and bypass creator
   492  		{
   493  			data: []byte(`{}`),
   494  			into: &runtime.Unknown{},
   495  
   496  			expectedGVK: &schema.GroupVersionKind{},
   497  			expectedObject: &runtime.Unknown{
   498  				Raw:         []byte(`{}`),
   499  				ContentType: runtime.ContentTypeJSON,
   500  			},
   501  		},
   502  		{
   503  			data: []byte(`{"test":"object"}`),
   504  			into: &runtime.Unknown{},
   505  
   506  			expectedGVK: &schema.GroupVersionKind{},
   507  			expectedObject: &runtime.Unknown{
   508  				Raw:         []byte(`{"test":"object"}`),
   509  				ContentType: runtime.ContentTypeJSON,
   510  			},
   511  		},
   512  		{
   513  			data:        []byte(`{"test":"object"}`),
   514  			into:        &runtime.Unknown{},
   515  			defaultGVK:  &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   516  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   517  			expectedObject: &runtime.Unknown{
   518  				TypeMeta:    runtime.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   519  				Raw:         []byte(`{"test":"object"}`),
   520  				ContentType: runtime.ContentTypeJSON,
   521  			},
   522  		},
   523  
   524  		// unregistered objects can be decoded into directly
   525  		{
   526  			data:        []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`),
   527  			into:        &testDecodable{},
   528  			typer:       &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
   529  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   530  			expectedObject: &testDecodable{
   531  				TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   532  				Other:    "test",
   533  				Value:    1,
   534  			},
   535  		},
   536  		// registered types get defaulted by the into object kind
   537  		{
   538  			data:        []byte(`{"value":1,"Other":"test"}`),
   539  			into:        &testDecodable{},
   540  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   541  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   542  			expectedObject: &testDecodable{
   543  				Other: "test",
   544  				Value: 1,
   545  			},
   546  		},
   547  		// registered types get defaulted by the into object kind even without version, but return an error
   548  		{
   549  			data:        []byte(`{"value":1,"Other":"test"}`),
   550  			into:        &testDecodable{},
   551  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}},
   552  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: ""},
   553  			errFn:       func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
   554  			expectedObject: &testDecodable{
   555  				Other: "test",
   556  				Value: 1,
   557  			},
   558  		},
   559  		// Error on invalid number
   560  		{
   561  			data:        []byte(`{"kind":"Test","apiVersion":"other/blah","interface":1e1000}`),
   562  			creater:     &mockCreater{obj: &testDecodable{}},
   563  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   564  			errFn: func(err error) bool {
   565  				return strings.Contains(err.Error(), `json: cannot unmarshal number 1e1000 into Go struct field testDecodable.interface of type float64`)
   566  			},
   567  		},
   568  		// Unmarshalling is case-sensitive
   569  		{
   570  			// "VaLue" should have been "value"
   571  			data:        []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
   572  			into:        &testDecodable{},
   573  			typer:       &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
   574  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   575  			expectedObject: &testDecodable{
   576  				TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   577  				Other:    "test",
   578  			},
   579  		},
   580  		// Unmarshalling is case-sensitive for big struct.
   581  		{
   582  			// "b" should have been "B", "I" should have been "i"
   583  			data:        []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`),
   584  			into:        &testDecodable{},
   585  			typer:       &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
   586  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   587  			expectedObject: &testDecodable{
   588  				TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   589  				Spec:     DecodableSpec{A: 1, H: 3},
   590  			},
   591  		},
   592  		// Unknown fields should return an error from the strict JSON deserializer.
   593  		{
   594  			data:        []byte(`{"unknown": 1}`),
   595  			into:        &testDecodable{},
   596  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   597  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   598  			errFn: func(err error) bool {
   599  				return strings.Contains(err.Error(), `unknown field "unknown"`)
   600  			},
   601  			strict: true,
   602  		},
   603  		// Unknown fields should return an error from the strict YAML deserializer.
   604  		{
   605  			data:        []byte("unknown: 1\n"),
   606  			into:        &testDecodable{},
   607  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   608  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   609  			errFn: func(err error) bool {
   610  				return strings.Contains(err.Error(), `unknown field "unknown"`)
   611  			},
   612  			yaml:   true,
   613  			strict: true,
   614  		},
   615  		// Duplicate fields should return an error from the strict JSON deserializer.
   616  		{
   617  			data:        []byte(`{"value":1,"value":1}`),
   618  			into:        &testDecodable{},
   619  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   620  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   621  			errFn: func(err error) bool {
   622  				return strings.Contains(err.Error(), `duplicate field "value"`)
   623  			},
   624  			strict: true,
   625  		},
   626  		// Duplicate fields should return an error from the strict YAML deserializer.
   627  		{
   628  			data: []byte("value: 1\n" +
   629  				"value: 1\n"),
   630  			into:        &testDecodable{},
   631  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   632  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   633  			errFn: func(err error) bool {
   634  				return strings.Contains(err.Error(), `"value" already set in map`)
   635  			},
   636  			yaml:   true,
   637  			strict: true,
   638  		},
   639  		// Duplicate fields should return an error from the strict JSON deserializer for unstructured.
   640  		{
   641  			data:        []byte(`{"kind":"Custom","value":1,"value":1}`),
   642  			into:        &unstructured.Unstructured{},
   643  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   644  			expectedGVK: &schema.GroupVersionKind{Kind: "Custom"},
   645  			errFn: func(err error) bool {
   646  				return strings.Contains(err.Error(), `duplicate field "value"`)
   647  			},
   648  			strict: true,
   649  		},
   650  		// Duplicate fields should return an error from the strict YAML deserializer for unstructured.
   651  		{
   652  			data: []byte("kind: Custom\n" +
   653  				"value: 1\n" +
   654  				"value: 1\n"),
   655  			into:        &unstructured.Unstructured{},
   656  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   657  			expectedGVK: &schema.GroupVersionKind{Kind: "Custom"},
   658  			errFn: func(err error) bool {
   659  				return strings.Contains(err.Error(), `"value" already set in map`)
   660  			},
   661  			yaml:   true,
   662  			strict: true,
   663  		},
   664  		// Strict JSON decode into unregistered objects directly.
   665  		{
   666  			data:        []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`),
   667  			into:        &testDecodable{},
   668  			typer:       &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
   669  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   670  			expectedObject: &testDecodable{
   671  				TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   672  				Other:    "test",
   673  				Value:    1,
   674  			},
   675  			strict: true,
   676  		},
   677  		// Strict YAML decode into unregistered objects directly.
   678  		{
   679  			data: []byte("kind: Test\n" +
   680  				"apiVersion: other/blah\n" +
   681  				"value: 1\n" +
   682  				"Other: test\n"),
   683  			into:        &testDecodable{},
   684  			typer:       &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
   685  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   686  			expectedObject: &testDecodable{
   687  				TypeMeta: metav1.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
   688  				Other:    "test",
   689  				Value:    1,
   690  			},
   691  			yaml:   true,
   692  			strict: true,
   693  		},
   694  		// Valid strict JSON decode without GVK.
   695  		{
   696  			data:        []byte(`{"value":1234}`),
   697  			into:        &testDecodable{},
   698  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   699  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   700  			expectedObject: &testDecodable{
   701  				Value: 1234,
   702  			},
   703  			strict: true,
   704  		},
   705  		// Valid strict YAML decode without GVK.
   706  		{
   707  			data:        []byte("value: 1234\n"),
   708  			into:        &testDecodable{},
   709  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   710  			expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   711  			expectedObject: &testDecodable{
   712  				Value: 1234,
   713  			},
   714  			yaml:   true,
   715  			strict: true,
   716  		},
   717  		// Invalid strict JSON, results in json parse error:
   718  		{
   719  			data:  []byte("foo"),
   720  			into:  &unstructured.Unstructured{},
   721  			typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   722  			errFn: func(err error) bool {
   723  				return strings.Contains(err.Error(), `json parse error: invalid character 'o'`)
   724  			},
   725  			strict: true,
   726  		},
   727  		// empty JSON strict, results in missing kind error
   728  		{
   729  			data:        []byte("{}"),
   730  			into:        &unstructured.Unstructured{},
   731  			typer:       &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   732  			expectedGVK: &schema.GroupVersionKind{},
   733  			errFn: func(err error) bool {
   734  				return strings.Contains(err.Error(), `Object 'Kind' is missing`)
   735  			},
   736  			strict: true,
   737  		},
   738  		// coerce from null
   739  		{
   740  			data:           []byte(`{"bool":null,"int":null,"int32":null,"int64":null,"float32":null,"float64":null,"string":null,"array":null,"map":null,"struct":null}`),
   741  			into:           &testDecodeCoercion{},
   742  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   743  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   744  			expectedObject: &testDecodeCoercion{},
   745  			strict:         true,
   746  		},
   747  		{
   748  			data:           []byte(`{"bool":null,"int":null,"int32":null,"int64":null,"float32":null,"float64":null,"string":null,"array":null,"map":null,"struct":null}`),
   749  			into:           &testDecodeCoercion{},
   750  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   751  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   752  			expectedObject: &testDecodeCoercion{},
   753  			yaml:           true,
   754  			strict:         true,
   755  		},
   756  		// coerce from string
   757  		{
   758  			data:           []byte(`{"string":""}`),
   759  			into:           &testDecodeCoercion{},
   760  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   761  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   762  			expectedObject: &testDecodeCoercion{},
   763  			strict:         true,
   764  		},
   765  		{
   766  			data:           []byte(`{"string":""}`),
   767  			into:           &testDecodeCoercion{},
   768  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   769  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   770  			expectedObject: &testDecodeCoercion{},
   771  			yaml:           true,
   772  			strict:         true,
   773  		},
   774  		// coerce from array
   775  		{
   776  			data:           []byte(`{"array":[]}`),
   777  			into:           &testDecodeCoercion{},
   778  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   779  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   780  			expectedObject: &testDecodeCoercion{Array: []string{}},
   781  			strict:         true,
   782  		},
   783  		{
   784  			data:           []byte(`{"array":[]}`),
   785  			into:           &testDecodeCoercion{},
   786  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   787  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   788  			expectedObject: &testDecodeCoercion{Array: []string{}},
   789  			yaml:           true,
   790  			strict:         true,
   791  		},
   792  		// coerce from map
   793  		{
   794  			data:           []byte(`{"map":{},"struct":{}}`),
   795  			into:           &testDecodeCoercion{},
   796  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   797  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   798  			expectedObject: &testDecodeCoercion{Map: map[string]string{}},
   799  			strict:         true,
   800  		},
   801  		{
   802  			data:           []byte(`{"map":{},"struct":{}}`),
   803  			into:           &testDecodeCoercion{},
   804  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   805  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   806  			expectedObject: &testDecodeCoercion{Map: map[string]string{}},
   807  			yaml:           true,
   808  			strict:         true,
   809  		},
   810  		// coerce from int
   811  		{
   812  			data:           []byte(`{"int":1,"int32":1,"int64":1,"float32":1,"float64":1}`),
   813  			into:           &testDecodeCoercion{},
   814  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   815  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   816  			expectedObject: &testDecodeCoercion{Int: 1, Int32: 1, Int64: 1, Float32: 1, Float64: 1},
   817  			strict:         true,
   818  		},
   819  		{
   820  			data:           []byte(`{"int":1,"int32":1,"int64":1,"float32":1,"float64":1}`),
   821  			into:           &testDecodeCoercion{},
   822  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   823  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   824  			expectedObject: &testDecodeCoercion{Int: 1, Int32: 1, Int64: 1, Float32: 1, Float64: 1},
   825  			yaml:           true,
   826  			strict:         true,
   827  		},
   828  		// coerce from float
   829  		{
   830  			data:           []byte(`{"float32":1.0,"float64":1.0}`),
   831  			into:           &testDecodeCoercion{},
   832  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   833  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   834  			expectedObject: &testDecodeCoercion{Float32: 1, Float64: 1},
   835  			strict:         true,
   836  		},
   837  		{
   838  			data:           []byte(`{"int":1.0,"int32":1.0,"int64":1.0,"float32":1.0,"float64":1.0}`), // floating point gets dropped in yaml -> json step
   839  			into:           &testDecodeCoercion{},
   840  			typer:          &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
   841  			expectedGVK:    &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
   842  			expectedObject: &testDecodeCoercion{Int: 1, Int32: 1, Int64: 1, Float32: 1, Float64: 1},
   843  			yaml:           true,
   844  			strict:         true,
   845  		},
   846  	}
   847  
   848  	logTestCase := func(t *testing.T, tc testCase) {
   849  		t.Logf("data=%s\n\tinto=%T, yaml=%v, strict=%v", string(tc.data), tc.into, tc.yaml, tc.strict)
   850  	}
   851  
   852  	for i, test := range testCases {
   853  		var s runtime.Serializer
   854  		if test.yaml {
   855  			s = json.NewSerializerWithOptions(json.DefaultMetaFactory, test.creater, test.typer, json.SerializerOptions{Yaml: test.yaml, Pretty: false, Strict: test.strict})
   856  		} else {
   857  			s = json.NewSerializerWithOptions(json.DefaultMetaFactory, test.creater, test.typer, json.SerializerOptions{Yaml: test.yaml, Pretty: test.pretty, Strict: test.strict})
   858  		}
   859  		obj, gvk, err := s.Decode([]byte(test.data), test.defaultGVK, test.into)
   860  
   861  		if !reflect.DeepEqual(test.expectedGVK, gvk) {
   862  			logTestCase(t, test)
   863  			t.Errorf("%d: unexpected GVK: %v", i, gvk)
   864  		}
   865  
   866  		switch {
   867  		case err == nil && test.errFn != nil:
   868  			logTestCase(t, test)
   869  			t.Errorf("%d: failed: not getting the expected error", i)
   870  			continue
   871  		case err != nil && test.errFn == nil:
   872  			logTestCase(t, test)
   873  			t.Errorf("%d: failed: %v", i, err)
   874  			continue
   875  		case err != nil:
   876  			if !test.errFn(err) {
   877  				logTestCase(t, test)
   878  				t.Errorf("%d: failed: %v", i, err)
   879  			}
   880  			if !runtime.IsStrictDecodingError(err) && obj != nil {
   881  				logTestCase(t, test)
   882  				t.Errorf("%d: should have returned nil object", i)
   883  			}
   884  			continue
   885  		}
   886  
   887  		if test.into != nil && test.into != obj {
   888  			logTestCase(t, test)
   889  			t.Errorf("%d: expected into to be returned: %v", i, obj)
   890  			continue
   891  		}
   892  
   893  		if !reflect.DeepEqual(test.expectedObject, obj) {
   894  			logTestCase(t, test)
   895  			t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.expectedObject, obj))
   896  		}
   897  	}
   898  }
   899  
   900  func TestCacheableObject(t *testing.T) {
   901  	gvk := schema.GroupVersionKind{Group: "group", Version: "version", Kind: "MockCacheableObject"}
   902  	creater := &mockCreater{obj: &runtimetesting.MockCacheableObject{}}
   903  	typer := &mockTyper{gvk: &gvk}
   904  	serializer := json.NewSerializer(json.DefaultMetaFactory, creater, typer, false)
   905  
   906  	runtimetesting.CacheableObjectTest(t, serializer)
   907  }
   908  
   909  type mockCreater struct {
   910  	apiVersion string
   911  	kind       string
   912  	err        error
   913  	obj        runtime.Object
   914  }
   915  
   916  func (c *mockCreater) New(kind schema.GroupVersionKind) (runtime.Object, error) {
   917  	c.apiVersion, c.kind = kind.GroupVersion().String(), kind.Kind
   918  	return c.obj, c.err
   919  }
   920  
   921  type mockTyper struct {
   922  	gvk *schema.GroupVersionKind
   923  	err error
   924  }
   925  
   926  func (t *mockTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
   927  	if t.gvk == nil {
   928  		return nil, false, t.err
   929  	}
   930  	return []schema.GroupVersionKind{*t.gvk}, false, t.err
   931  }
   932  
   933  func (t *mockTyper) Recognizes(_ schema.GroupVersionKind) bool {
   934  	return false
   935  }