@@ -18,21 +18,26 @@ package v1_test
18
18
19
19
import (
20
20
"encoding/json"
21
+ "math/rand"
21
22
"net/url"
22
23
"reflect"
23
24
"testing"
24
25
"time"
25
26
26
27
"k8s.io/api/core/v1"
28
+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
27
29
apiequality "k8s.io/apimachinery/pkg/api/equality"
28
30
"k8s.io/apimachinery/pkg/api/resource"
31
+ "k8s.io/apimachinery/pkg/api/testing/fuzzer"
29
32
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
33
"k8s.io/apimachinery/pkg/runtime"
31
34
"k8s.io/apimachinery/pkg/util/diff"
32
35
"k8s.io/kubernetes/pkg/api"
33
36
"k8s.io/kubernetes/pkg/api/legacyscheme"
37
+ kapitesting "k8s.io/kubernetes/pkg/api/testing"
34
38
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
35
39
"k8s.io/kubernetes/pkg/apis/extensions"
40
+ utilpointer "k8s.io/kubernetes/pkg/util/pointer"
36
41
37
42
// enforce that all types are installed
38
43
_ "k8s.io/kubernetes/pkg/api/testapi"
@@ -231,59 +236,112 @@ func TestResourceListConversion(t *testing.T) {
231
236
232
237
func TestReplicationControllerConversion (t * testing.T ) {
233
238
// If we start with a RC, we should always have round-trip fidelity.
234
- replicas := int32 (1 )
235
- in := & v1.ReplicationController {
236
- ObjectMeta : metav1.ObjectMeta {
237
- Name : "name" ,
238
- Namespace : "namespace" ,
239
- },
240
- Spec : v1.ReplicationControllerSpec {
241
- Replicas : & replicas ,
242
- MinReadySeconds : 32 ,
243
- Selector : map [string ]string {"foo" : "bar" , "bar" : "foo" },
244
- Template : & v1.PodTemplateSpec {
245
- ObjectMeta : metav1.ObjectMeta {
246
- Labels : map [string ]string {"foo" : "bar" , "bar" : "foo" },
247
- },
248
- Spec : v1.PodSpec {
249
- Containers : []v1.Container {
250
- {
251
- Name : "container" ,
252
- Image : "image" ,
239
+ inputs := []* v1.ReplicationController {
240
+ {
241
+ ObjectMeta : metav1.ObjectMeta {
242
+ Name : "name" ,
243
+ Namespace : "namespace" ,
244
+ },
245
+ Spec : v1.ReplicationControllerSpec {
246
+ Replicas : utilpointer .Int32Ptr (1 ),
247
+ MinReadySeconds : 32 ,
248
+ Selector : map [string ]string {"foo" : "bar" , "bar" : "foo" },
249
+ Template : & v1.PodTemplateSpec {
250
+ ObjectMeta : metav1.ObjectMeta {
251
+ Labels : map [string ]string {"foo" : "bar" , "bar" : "foo" },
252
+ },
253
+ Spec : v1.PodSpec {
254
+ Containers : []v1.Container {
255
+ {
256
+ Name : "container" ,
257
+ Image : "image" ,
258
+ },
253
259
},
254
260
},
255
261
},
256
262
},
257
- },
258
- Status : v1. ReplicationControllerStatus {
259
- Replicas : 1 ,
260
- FullyLabeledReplicas : 2 ,
261
- ReadyReplicas : 3 ,
262
- AvailableReplicas : 4 ,
263
- ObservedGeneration : 5 ,
264
- Conditions : []v1. ReplicationControllerCondition {
265
- {
266
- Type : v1 .ReplicationControllerReplicaFailure ,
267
- Status : v1 . ConditionTrue ,
268
- LastTransitionTime : metav1 . NewTime ( time . Unix ( 123456789 , 0 )) ,
269
- Reason : "Reason " ,
270
- Message : "Message" ,
263
+ Status : v1. ReplicationControllerStatus {
264
+ Replicas : 1 ,
265
+ FullyLabeledReplicas : 2 ,
266
+ ReadyReplicas : 3 ,
267
+ AvailableReplicas : 4 ,
268
+ ObservedGeneration : 5 ,
269
+ Conditions : []v1. ReplicationControllerCondition {
270
+ {
271
+ Type : v1 . ReplicationControllerReplicaFailure ,
272
+ Status : v1 .ConditionTrue ,
273
+ LastTransitionTime : metav1 . NewTime ( time . Unix ( 123456789 , 0 )) ,
274
+ Reason : "Reason" ,
275
+ Message : "Message " ,
276
+ } ,
271
277
},
272
278
},
273
279
},
274
280
}
275
- in = roundTrip (t , in ).(* v1.ReplicationController )
276
- rs := & extensions.ReplicaSet {}
277
- if err := k8s_api_v1 .Convert_v1_ReplicationController_to_extensions_ReplicaSet (in , rs , nil ); err != nil {
278
- t .Fatalf ("can't convert RC to RS: %v" , err )
281
+
282
+ // Add some fuzzed RCs.
283
+ apiObjectFuzzer := fuzzer .FuzzerFor (kapitesting .FuzzerFuncs , rand .NewSource (152 ), legacyscheme .Codecs )
284
+ for i := 0 ; i < 100 ; i ++ {
285
+ rc := & v1.ReplicationController {}
286
+ apiObjectFuzzer .Fuzz (rc )
287
+ // Sometimes the fuzzer decides to leave Spec.Template nil.
288
+ // We can't support that because Spec.Template is not a pointer in RS,
289
+ // so it will round-trip as non-nil but empty.
290
+ if rc .Spec .Template == nil {
291
+ rc .Spec .Template = & v1.PodTemplateSpec {}
292
+ }
293
+ // Sometimes the fuzzer decides to insert an empty label key.
294
+ // This doesn't round-trip properly because it's invalid.
295
+ if rc .Spec .Selector != nil {
296
+ delete (rc .Spec .Selector , "" )
297
+ }
298
+ inputs = append (inputs , rc )
299
+ }
300
+
301
+ // Round-trip the input RCs before converting to RS.
302
+ for i := range inputs {
303
+ inputs [i ] = roundTrip (t , inputs [i ]).(* v1.ReplicationController )
304
+ }
305
+
306
+ for _ , in := range inputs {
307
+ rs := & extensions.ReplicaSet {}
308
+ // Use in.DeepCopy() to avoid sharing pointers with `in`.
309
+ if err := k8s_api_v1 .Convert_v1_ReplicationController_to_extensions_ReplicaSet (in .DeepCopy (), rs , nil ); err != nil {
310
+ t .Errorf ("can't convert RC to RS: %v" , err )
311
+ continue
312
+ }
313
+ // Round-trip RS before converting back to RC.
314
+ rs = roundTripRS (t , rs )
315
+ out := & v1.ReplicationController {}
316
+ if err := k8s_api_v1 .Convert_extensions_ReplicaSet_to_v1_ReplicationController (rs , out , nil ); err != nil {
317
+ t .Errorf ("can't convert RS to RC: %v" , err )
318
+ continue
319
+ }
320
+ if ! apiequality .Semantic .DeepEqual (in , out ) {
321
+ instr , _ := json .MarshalIndent (in , "" , " " )
322
+ outstr , _ := json .MarshalIndent (out , "" , " " )
323
+ t .Errorf ("RC-RS conversion round-trip failed:\n in:\n %s\n out:\n %s" , instr , outstr )
324
+ }
325
+ }
326
+ }
327
+
328
+ func roundTripRS (t * testing.T , rs * extensions.ReplicaSet ) * extensions.ReplicaSet {
329
+ codec := legacyscheme .Codecs .LegacyCodec (extensionsv1beta1 .SchemeGroupVersion )
330
+ data , err := runtime .Encode (codec , rs )
331
+ if err != nil {
332
+ t .Errorf ("%v\n %#v" , err , rs )
333
+ return nil
279
334
}
280
- out := & v1.ReplicationController {}
281
- if err := k8s_api_v1 .Convert_extensions_ReplicaSet_to_v1_ReplicationController (rs , out , nil ); err != nil {
282
- t .Fatalf ("can't convert RS to RC: %v" , err )
335
+ obj2 , err := runtime .Decode (codec , data )
336
+ if err != nil {
337
+ t .Errorf ("%v\n Data: %s\n Source: %#v" , err , string (data ), rs )
338
+ return nil
283
339
}
284
- if ! apiequality .Semantic .DeepEqual (in , out ) {
285
- instr , _ := json .MarshalIndent (in , "" , " " )
286
- outstr , _ := json .MarshalIndent (out , "" , " " )
287
- t .Errorf ("RC-RS conversion round-trip failed:\n in:\n %s\n out:\n %s" , instr , outstr )
340
+ obj3 := & extensions.ReplicaSet {}
341
+ err = legacyscheme .Scheme .Convert (obj2 , obj3 , nil )
342
+ if err != nil {
343
+ t .Errorf ("%v\n Source: %#v" , err , obj2 )
344
+ return nil
288
345
}
346
+ return obj3
289
347
}
0 commit comments