func BenchmarkPodConversion(b *testing.B) { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]api.Pod, 4) for i := range items { apiObjectFuzzer.Fuzz(&items[i]) items[i].Spec.InitContainers = nil items[i].Status.InitContainerStatuses = nil } // add a fixed item items = append(items, benchmarkPod) width := len(items) scheme := api.Scheme for i := 0; i < b.N; i++ { pod := &items[i%width] versionedObj, err := scheme.UnsafeConvertToVersion(pod, api.Registry.GroupOrDie(api.GroupName).GroupVersion) if err != nil { b.Fatalf("Conversion error: %v", err) } if _, err = scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()); err != nil { b.Fatalf("Conversion error: %v", err) } } }
func BenchmarkPodConversion(b *testing.B) { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]api.Pod, 4) for i := range items { apiObjectFuzzer.Fuzz(&items[i]) items[i].Spec.InitContainers = nil items[i].Status.InitContainerStatuses = nil } // add a fixed item data, err := ioutil.ReadFile("pod_example.json") if err != nil { b.Fatalf("Unexpected error while reading file: %v", err) } var pod api.Pod if err := runtime.DecodeInto(testapi.Default.Codec(), data, &pod); err != nil { b.Fatalf("Unexpected error decoding pod: %v", err) } items = append(items, pod) width := len(items) scheme := api.Scheme for i := 0; i < b.N; i++ { pod := &items[i%width] versionedObj, err := scheme.UnsafeConvertToVersion(pod, *testapi.Default.GroupVersion()) if err != nil { b.Fatalf("Conversion error: %v", err) } if _, err = scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()); err != nil { b.Fatalf("Conversion error: %v", err) } } }
func TestValidateOk(t *testing.T) { schema, err := loadSchemaForTest() if err != nil { t.Errorf("Failed to load: %v", err) } tests := []struct { obj runtime.Object typeName string }{ {obj: &api.Pod{}}, {obj: &api.Service{}}, {obj: &api.ReplicationController{}}, } seed := rand.Int63() apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(seed)) for i := 0; i < 5; i++ { for _, test := range tests { testObj := test.obj apiObjectFuzzer.Fuzz(testObj) data, err := testapi.Default.Codec().Encode(testObj) if err != nil { t.Errorf("unexpected error: %v", err) } err = schema.ValidateBytes(data) if err != nil { t.Errorf("unexpected error: %v", err) } } } }
func BenchmarkEncode(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) for i := 0; i < b.N; i++ { latest.Codec.Encode(&pod) } }
func TestDeepCopySingleType(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) doDeepCopyTest(t, version.WithKind("Pod"), f) } } }
func benchmarkItems() []v1.Pod { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]v1.Pod, 2) for i := range items { apiObjectFuzzer.Fuzz(&items[i]) } return items }
func TestDeepCopySingleType(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) doDeepCopyTest(t, version.WithKind("Pod"), f) } } }
func TestDeepCopySingleType(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []string{"", testapi.Default.Version()} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) doDeepCopyTest(t, version, "Pod", f) } } }
// BenchmarkEncodeJSON provides a baseline for regular JSON encode performance func BenchmarkEncodeJSON(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) for i := 0; i < b.N; i++ { json.Marshal(&pod) } }
func BenchmarkDecode(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) data, _ := testapi.Default.Codec().Encode(&pod) for i := 0; i < b.N; i++ { testapi.Default.Codec().Decode(data) } }
func benchmarkItems() []api.Pod { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]api.Pod, 3) for i := range items { apiObjectFuzzer.Fuzz(&items[i]) items[i].Spec.InitContainers, items[i].Status.InitContainerStatuses = nil, nil } return items }
func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) for kind := range api.Scheme.KnownTypes(version) { doDeepCopyTest(t, version.WithKind(kind), f) } } } }
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance func BenchmarkDecodeJSON(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) data, _ := latest.Codec.Encode(&pod) for i := 0; i < b.N; i++ { obj := api.Pod{} json.Unmarshal(data, &obj) } }
func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []string{"", testapi.Default.Version()} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) for kind := range api.Scheme.KnownTypes(version) { doDeepCopyTest(t, version, kind, f) } } } }
func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func benchmarkItems() []v1.Pod { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]v1.Pod, 2) for i := range items { var pod api.Pod apiObjectFuzzer.Fuzz(&pod) out, err := api.Scheme.ConvertToVersion(&pod, "v1") if err != nil { panic(err) } items[i] = *out.(*v1.Pod) } return items }
func benchmarkItems() []v1.Pod { apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) items := make([]v1.Pod, 10) for i := range items { var pod api.Pod apiObjectFuzzer.Fuzz(&pod) pod.Spec.InitContainers, pod.Status.InitContainerStatuses = nil, nil out, err := api.Scheme.ConvertToVersion(&pod, v1.SchemeGroupVersion) if err != nil { panic(err) } items[i] = *out.(*v1.Pod) } return items }
func TestProtobufRoundTrip(t *testing.T) { obj := &v1.Pod{} apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(benchmarkSeed)).Fuzz(obj) data, err := obj.Marshal() if err != nil { t.Fatal(err) } out := &v1.Pod{} if err := out.Unmarshal(data); err != nil { t.Fatal(err) } if !api.Semantic.Equalities.DeepEqual(out, obj) { t.Logf("marshal\n%s", hex.Dump(data)) t.Fatalf("Unmarshal is unequal\n%s", diff.ObjectGoPrintSideBySide(out, obj)) } }
func TestProtobufRoundTrip(t *testing.T) { obj := &v1.Pod{} apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(benchmarkSeed)).Fuzz(obj) // InitContainers are turned into annotations by conversion. obj.Spec.InitContainers = nil obj.Status.InitContainerStatuses = nil data, err := obj.Marshal() if err != nil { t.Fatal(err) } out := &v1.Pod{} if err := out.Unmarshal(data); err != nil { t.Fatal(err) } if !api.Semantic.Equalities.DeepEqual(out, obj) { t.Logf("marshal\n%s", hex.Dump(data)) t.Fatalf("Unmarshal is unequal\n%s", diff.ObjectGoPrintDiff(out, obj)) } }
func fuzzImage(t *testing.T, image *api.Image, seed int64) *api.Image { f := apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(seed)) f.Funcs( func(j *api.Image, c fuzz.Continue) { c.FuzzNoCustom(j) j.Annotations = make(map[string]string) j.Labels = make(map[string]string) j.Signatures = make([]api.ImageSignature, c.Rand.Intn(3)+2) for i := range j.Signatures { sign := &j.Signatures[i] c.Fuzz(sign) sign.Conditions = make([]api.SignatureCondition, c.Rand.Intn(3)+2) for ci := range sign.Conditions { cond := &sign.Conditions[ci] c.Fuzz(cond) } } for i := 0; i < c.Rand.Intn(3)+2; i++ { j.Labels[c.RandString()] = c.RandString() j.Annotations[c.RandString()] = c.RandString() } }, ) updated := api.Image{} f.Fuzz(&updated) updated.Namespace = image.Namespace updated.Name = image.Name j, err := meta.TypeAccessor(image) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, image) } j.SetKind("") j.SetAPIVersion("") return &updated }
func fuzzImageSignature(t *testing.T, signature *api.ImageSignature, seed int64) *api.ImageSignature { f := apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(seed)) f.Funcs( func(j *api.ImageSignature, c fuzz.Continue) { c.FuzzNoCustom(j) j.Annotations = make(map[string]string) j.Labels = make(map[string]string) j.Conditions = []api.SignatureCondition{} j.SignedClaims = make(map[string]string) j.Content = []byte(c.RandString()) for i := 0; i < c.Rand.Intn(3)+2; i++ { j.Labels[c.RandString()] = c.RandString() j.Annotations[c.RandString()] = c.RandString() j.SignedClaims[c.RandString()] = c.RandString() } for i := 0; i < c.Rand.Intn(3)+2; i++ { cond := api.SignatureCondition{} c.Fuzz(&cond) j.Conditions = append(j.Conditions, cond) } }, ) updated := api.ImageSignature{} f.Fuzz(&updated) updated.Namespace = signature.Namespace updated.Name = signature.Name j, err := meta.TypeAccessor(signature) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, signature) } j.SetKind("") j.SetAPIVersion("") return &updated }
func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []string{"", testapi.Default.Version()} { f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) for kind := range api.Scheme.KnownTypes(version) { item, err := api.Scheme.New(version, kind) if err != nil { t.Fatalf("Could not create a %s: %s", kind, err) } f.Fuzz(item) itemCopy, err := api.Scheme.DeepCopy(item) if err != nil { t.Errorf("Could not deep copy a %s: %s", kind, err) continue } if !reflect.DeepEqual(item, itemCopy) { t.Errorf("\nexpected %#v\ngot %#v", item, itemCopy) } } } } }
func TestProtobufRoundTrip(t *testing.T) { obj := &v1.Pod{} apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(benchmarkSeed)).Fuzz(obj) // InitContainers are turned into annotations by conversion. obj.Spec.InitContainers = nil obj.Status.InitContainerStatuses = nil // We don't round trip VolumeSource.Metadata (it's a deprecated OpenShift // carry) for protobuf, so we need to nil it out here to make the test pass. for i := range obj.Spec.Volumes { obj.Spec.Volumes[i].VolumeSource.Metadata = nil } data, err := obj.Marshal() if err != nil { t.Fatal(err) } out := &v1.Pod{} if err := out.Unmarshal(data); err != nil { t.Fatal(err) } if !api.Semantic.Equalities.DeepEqual(out, obj) { t.Logf("marshal\n%s", hex.Dump(data)) t.Fatalf("Unmarshal is unequal\n%s", diff.ObjectGoPrintDiff(out, obj)) } }
// TestObjectWatchFraming establishes that a watch event can be encoded and // decoded correctly through each of the supported RFC2046 media types. func TestObjectWatchFraming(t *testing.T) { f := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) secret := &api.Secret{} f.Fuzz(secret) secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00} secret.Data["utf8"] = []byte("a string with \u0345 characters") secret.Data["long"] = bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x00}, 1000) converted, _ := api.Scheme.ConvertToVersion(secret, v1.SchemeGroupVersion) v1secret := converted.(*v1.Secret) for _, info := range api.Codecs.SupportedMediaTypes() { if info.StreamSerializer == nil { continue } s := info.StreamSerializer framer := s.Framer embedded := info.Serializer if embedded == nil { t.Errorf("no embedded serializer for %s", info.MediaType) continue } innerDecode := api.Codecs.DecoderToVersion(embedded, api.SchemeGroupVersion) // write a single object through the framer and back out obj := &bytes.Buffer{} if err := s.Encode(v1secret, obj); err != nil { t.Fatal(err) } out := &bytes.Buffer{} w := framer.NewFrameWriter(out) if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { t.Fatal(err) } sr := streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) resultSecret := &v1.Secret{} res, _, err := sr.Decode(nil, resultSecret) if err != nil { t.Fatalf("%v:\n%s", err, hex.Dump(obj.Bytes())) } resultSecret.Kind = "Secret" resultSecret.APIVersion = "v1" if !api.Semantic.DeepEqual(v1secret, res) { t.Fatalf("objects did not match: %s", diff.ObjectGoPrintDiff(v1secret, res)) } // write a watch event through the frame writer and read it back in // via the frame reader for this media type obj = &bytes.Buffer{} if err := embedded.Encode(v1secret, obj); err != nil { t.Fatal(err) } event := &metav1.WatchEvent{Type: string(watch.Added)} event.Object.Raw = obj.Bytes() obj = &bytes.Buffer{} if err := s.Encode(event, obj); err != nil { t.Fatal(err) } out = &bytes.Buffer{} w = framer.NewFrameWriter(out) if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { t.Fatal(err) } sr = streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) outEvent := &metav1.WatchEvent{} res, _, err = sr.Decode(nil, outEvent) if err != nil || outEvent.Type != string(watch.Added) { t.Fatalf("%v: %#v", err, outEvent) } if outEvent.Object.Object == nil && outEvent.Object.Raw != nil { outEvent.Object.Object, err = runtime.Decode(innerDecode, outEvent.Object.Raw) if err != nil { t.Fatalf("%v:\n%s", err, hex.Dump(outEvent.Object.Raw)) } } if !api.Semantic.DeepEqual(secret, outEvent.Object.Object) { t.Fatalf("%s: did not match after frame decoding: %s", info.MediaType, diff.ObjectGoPrintDiff(secret, outEvent.Object.Object)) } } }
func TestObjectWatchFraming(t *testing.T) { f := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) secret := &api.Secret{} f.Fuzz(secret) secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00} secret.Data["utf8"] = []byte("a string with \u0345 characters") secret.Data["long"] = bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x00}, 1000) converted, _ := api.Scheme.ConvertToVersion(secret, "v1") v1secret := converted.(*v1.Secret) for _, streamingMediaType := range api.Codecs.SupportedStreamingMediaTypes() { s, framer, mediaType, _ := api.Codecs.StreamingSerializerForMediaType(streamingMediaType, nil) // TODO: remove this when the runtime.SerializerInfo PR lands if mediaType == "application/vnd.kubernetes.protobuf;stream=watch" { mediaType = "application/vnd.kubernetes.protobuf" } embedded, ok := api.Codecs.SerializerForMediaType(mediaType, nil) if !ok { t.Logf("no embedded serializer for %s", mediaType) embedded = s } innerDecode := api.Codecs.DecoderToVersion(embedded, api.SchemeGroupVersion) //innerEncode := api.Codecs.EncoderForVersion(embedded, api.SchemeGroupVersion) // write a single object through the framer and back out obj := &bytes.Buffer{} if err := s.EncodeToStream(v1secret, obj); err != nil { t.Fatal(err) } out := &bytes.Buffer{} w := framer.NewFrameWriter(out) if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { t.Fatal(err) } sr := streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) resultSecret := &v1.Secret{} res, _, err := sr.Decode(nil, resultSecret) if err != nil { t.Fatalf("%v:\n%s", err, hex.Dump(obj.Bytes())) } resultSecret.Kind = "Secret" resultSecret.APIVersion = "v1" if !api.Semantic.DeepEqual(v1secret, res) { t.Fatalf("objects did not match: %s", diff.ObjectGoPrintDiff(v1secret, res)) } // write a watch event through and back out obj = &bytes.Buffer{} if err := embedded.EncodeToStream(v1secret, obj); err != nil { t.Fatal(err) } event := &versioned.Event{Type: string(watch.Added)} event.Object.Raw = obj.Bytes() obj = &bytes.Buffer{} if err := s.EncodeToStream(event, obj); err != nil { t.Fatal(err) } out = &bytes.Buffer{} w = framer.NewFrameWriter(out) if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { t.Fatal(err) } sr = streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) outEvent := &versioned.Event{} res, _, err = sr.Decode(nil, outEvent) if err != nil || outEvent.Type != string(watch.Added) { t.Fatalf("%v: %#v", err, outEvent) } if outEvent.Object.Object == nil && outEvent.Object.Raw != nil { outEvent.Object.Object, err = runtime.Decode(innerDecode, outEvent.Object.Raw) if err != nil { t.Fatalf("%v:\n%s", err, hex.Dump(outEvent.Object.Raw)) } } if !api.Semantic.DeepEqual(secret, outEvent.Object.Object) { t.Fatalf("%s: did not match after frame decoding: %s", streamingMediaType, diff.ObjectGoPrintDiff(secret, outEvent.Object.Object)) } } }
func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.Role) }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.ClusterRole) }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageImportSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To == nil { // To is defaulted to be not nil j.To = &api.LocalObjectReference{} } }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } if j.Tags == nil { j.Tags = make(map[string]image.TagReference) } }, func(j *image.ImageStreamStatus, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.To = api.ObjectReference{ Kind: "Service", Name: j.To.Name, } }, func(j *route.TLSConfig, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Termination) == 0 && len(j.DestinationCACertificate) == 0 { j.Termination = route.TLSTerminationEdge } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} if forVersion == "v1beta3" { // v1beta3 does not contain the PodSecurityContext type. For this API version, only fuzz // the host namespace fields. The fields set to nil here are the other fields of the // PodSecurityContext that will not roundtrip correctly from internal->v1beta3->internal. j.Spec.Template.Spec.SecurityContext.SELinuxOptions = nil j.Spec.Template.Spec.SecurityContext.RunAsUser = nil j.Spec.Template.Spec.SecurityContext.RunAsNonRoot = nil j.Spec.Template.Spec.SecurityContext.SupplementalGroups = nil j.Spec.Template.Spec.SecurityContext.FSGroup = nil } }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) strategyTypes := []deploy.DeploymentStrategyType{deploy.DeploymentStrategyTypeRecreate, deploy.DeploymentStrategyTypeRolling, deploy.DeploymentStrategyTypeCustom} j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] switch j.Type { case deploy.DeploymentStrategyTypeRolling: params := &deploy.RollingDeploymentStrategyParams{} randInt64 := func() *int64 { p := int64(c.RandUint64()) return &p } params.TimeoutSeconds = randInt64() params.IntervalSeconds = randInt64() params.UpdatePeriodSeconds = randInt64() policyTypes := []deploy.LifecycleHookFailurePolicy{ deploy.LifecycleHookFailurePolicyRetry, deploy.LifecycleHookFailurePolicyAbort, deploy.LifecycleHookFailurePolicyIgnore, } if c.RandBool() { params.Pre = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.Post = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.MaxUnavailable = util.NewIntOrStringFromInt(int(c.RandUint64())) params.MaxSurge = util.NewIntOrStringFromInt(int(c.RandUint64())) } else { params.MaxSurge = util.NewIntOrStringFromString(fmt.Sprintf("%d%%", c.RandUint64())) params.MaxUnavailable = util.NewIntOrStringFromString(fmt.Sprintf("%d%%", c.RandUint64())) } j.RollingParams = params default: j.RollingParams = nil } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"stuff", "other"} j.From.Name = specs[c.Intn(len(specs))] if len(j.From.Name) > 0 { j.From.Name = image.JoinImageStreamTag(j.From.Name, tags[c.Intn(len(tags))]) } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] }, func(j *runtime.EmbeddedObject, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.Role) }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { j.Roles = make(map[string]*authorizationapi.ClusterRole) }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateUserName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if valid, _ := uservalidation.ValidateGroupName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if valid, _ := validation.ValidateNamespaceName(j.Subjects[i].Namespace, false); !valid { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if valid, _ := validation.ValidateServiceAccountName(j.Subjects[i].Name, false); !valid { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.To = api.ObjectReference{ Kind: "Service", Name: j.To.Name, } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) mkintp := func(i int) *int64 { v := int64(i) return &v } switch c.Intn(3) { case 0: // TODO: we should not have to set defaults, instead we should be able // to detect defaults were applied. j.Type = deploy.DeploymentStrategyTypeRolling j.RollingParams = &deploy.RollingDeploymentStrategyParams{ IntervalSeconds: mkintp(1), UpdatePeriodSeconds: mkintp(1), TimeoutSeconds: mkintp(120), } case 1: j.Type = deploy.DeploymentStrategyTypeRecreate j.RollingParams = nil case 2: j.Type = deploy.DeploymentStrategyTypeCustom j.RollingParams = nil } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"", "stuff", "other"} j.RepositoryName = specs[c.Intn(len(specs))] if len(j.RepositoryName) > 0 { j.Tag = tags[c.Intn(len(tags))] } else { j.Tag = "" } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] if ref, err := image.ParseDockerImageReference(j.From.Name); err == nil { j.Tag = ref.Tag ref.Tag, ref.ID = "", "" j.RepositoryName = ref.String() } }, func(j *runtime.EmbeddedObject, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { f := apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)) f.Funcs( // Roles and RoleBindings maps are never nil func(j *authorizationapi.Policy, c fuzz.Continue) { c.FuzzNoCustom(j) if j.Roles != nil { j.Roles = make(map[string]*authorizationapi.Role) } for k, v := range j.Roles { if v == nil { delete(j.Roles, k) } } }, func(j *authorizationapi.PolicyBinding, c fuzz.Continue) { c.FuzzNoCustom(j) if j.RoleBindings == nil { j.RoleBindings = make(map[string]*authorizationapi.RoleBinding) } for k, v := range j.RoleBindings { if v == nil { delete(j.RoleBindings, k) } } }, func(j *authorizationapi.ClusterPolicy, c fuzz.Continue) { c.FuzzNoCustom(j) if j.Roles == nil { j.Roles = make(map[string]*authorizationapi.ClusterRole) } for k, v := range j.Roles { if v == nil { delete(j.Roles, k) } } }, func(j *authorizationapi.ClusterPolicyBinding, c fuzz.Continue) { j.RoleBindings = make(map[string]*authorizationapi.ClusterRoleBinding) }, func(j *authorizationapi.RoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateUserName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateGroupName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if len(validation.ValidateNamespaceName(j.Subjects[i].Namespace, false)) != 0 { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if len(validation.ValidateServiceAccountName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *authorizationapi.PolicyRule, c fuzz.Continue) { c.FuzzNoCustom(j) // if no groups are found, then we assume "". This matches defaulting if len(j.APIGroups) == 0 { j.APIGroups = []string{""} } switch c.Intn(3) { case 0: j.AttributeRestrictions = &authorizationapi.IsPersonalSubjectAccessReview{} case 1: j.AttributeRestrictions = &runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "Type", APIVersion: "other"}, ContentType: "application/json", Raw: []byte(`{"apiVersion":"other","kind":"Type"}`)} default: j.AttributeRestrictions = nil } }, func(j *authorizationapi.ClusterRoleBinding, c fuzz.Continue) { c.FuzzNoCustom(j) for i := range j.Subjects { kinds := []string{authorizationapi.UserKind, authorizationapi.SystemUserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.ServiceAccountKind} j.Subjects[i].Kind = kinds[c.Intn(len(kinds))] switch j.Subjects[i].Kind { case authorizationapi.UserKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateUserName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validusername%d", i) } case authorizationapi.GroupKind: j.Subjects[i].Namespace = "" if len(uservalidation.ValidateGroupName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("validgroupname%d", i) } case authorizationapi.ServiceAccountKind: if len(validation.ValidateNamespaceName(j.Subjects[i].Namespace, false)) != 0 { j.Subjects[i].Namespace = fmt.Sprintf("sanamespacehere%d", i) } if len(validation.ValidateServiceAccountName(j.Subjects[i].Name, false)) != 0 { j.Subjects[i].Name = fmt.Sprintf("sanamehere%d", i) } case authorizationapi.SystemUserKind, authorizationapi.SystemGroupKind: j.Subjects[i].Namespace = "" j.Subjects[i].Name = ":" + j.Subjects[i].Name } j.Subjects[i].UID = types.UID("") j.Subjects[i].APIVersion = "" j.Subjects[i].ResourceVersion = "" j.Subjects[i].FieldPath = "" } }, func(j *template.Template, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.Parameters) // TODO: replace with structured type definition j.Objects = []runtime.Object{} }, func(j *image.Image, c fuzz.Continue) { c.Fuzz(&j.ObjectMeta) c.Fuzz(&j.DockerImageMetadata) c.Fuzz(&j.Signatures) j.DockerImageMetadata.APIVersion = "" j.DockerImageMetadata.Kind = "" j.DockerImageMetadataVersion = []string{"pre012", "1.0"}[c.Rand.Intn(2)] j.DockerImageReference = c.RandString() }, func(j *image.ImageSignature, c fuzz.Continue) { c.FuzzNoCustom(j) j.Conditions = nil j.ImageIdentity = "" j.SignedClaims = nil j.Created = nil j.IssuedBy = nil j.IssuedTo = nil }, func(j *image.ImageStreamMapping, c fuzz.Continue) { c.FuzzNoCustom(j) j.DockerImageRepository = "" }, func(j *image.ImageImportSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To == nil { // To is defaulted to be not nil j.To = &kapi.LocalObjectReference{} } }, func(j *image.ImageStreamImage, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamImage, in order to round trip // successfully, the ImageStreamImage's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.ImageStreamSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } if j.Tags == nil { j.Tags = make(map[string]image.TagReference) } for k, v := range j.Tags { v.Name = k j.Tags[k] = v } }, func(j *image.ImageStreamStatus, c fuzz.Continue) { c.FuzzNoCustom(j) // if the generated fuzz value has a tag or image id, strip it if strings.ContainsAny(j.DockerImageRepository, ":@") { j.DockerImageRepository = "" } }, func(j *image.ImageStreamTag, c fuzz.Continue) { c.Fuzz(&j.Image) // because we de-embedded Image from ImageStreamTag, in order to round trip // successfully, the ImageStreamTag's ObjectMeta must match the Image's. j.ObjectMeta = j.Image.ObjectMeta }, func(j *image.TagReference, c fuzz.Continue) { c.FuzzNoCustom(j) if j.From != nil { specs := []string{"", "ImageStreamTag", "ImageStreamImage"} j.From.Kind = specs[c.Intn(len(specs))] } }, func(j *build.BuildConfigSpec, c fuzz.Continue) { c.FuzzNoCustom(j) j.RunPolicy = build.BuildRunPolicySerial }, func(j *build.SourceBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.CustomBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.DockerBuildStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.From.Kind = "ImageStreamTag" j.From.Name = "image:tag" j.From.APIVersion = "" j.From.ResourceVersion = "" j.From.FieldPath = "" }, func(j *build.BuildOutput, c fuzz.Continue) { c.FuzzNoCustom(j) if j.To != nil && (len(j.To.Kind) == 0 || j.To.Kind == "ImageStream") { j.To.Kind = "ImageStreamTag" } if j.To != nil && strings.Contains(j.To.Name, ":") { j.To.Name = strings.Replace(j.To.Name, ":", "-", -1) } }, func(j *route.RouteTargetReference, c fuzz.Continue) { c.FuzzNoCustom(j) j.Kind = "Service" j.Weight = new(int32) *j.Weight = 100 }, func(j *route.TLSConfig, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Termination) == 0 && len(j.DestinationCACertificate) == 0 { j.Termination = route.TLSTerminationEdge } }, func(j *deploy.DeploymentConfig, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Triggers = []deploy.DeploymentTriggerPolicy{{Type: deploy.DeploymentTriggerOnConfigChange}} if j.Spec.Template != nil && len(j.Spec.Template.Spec.Containers) == 1 { containerName := j.Spec.Template.Spec.Containers[0].Name if p := j.Spec.Strategy.RecreateParams; p != nil { defaultHookContainerName(p.Pre, containerName) defaultHookContainerName(p.Mid, containerName) defaultHookContainerName(p.Post, containerName) } if p := j.Spec.Strategy.RollingParams; p != nil { defaultHookContainerName(p.Pre, containerName) defaultHookContainerName(p.Post, containerName) } } }, func(j *deploy.DeploymentStrategy, c fuzz.Continue) { c.FuzzNoCustom(j) j.RecreateParams, j.RollingParams, j.CustomParams = nil, nil, nil strategyTypes := []deploy.DeploymentStrategyType{deploy.DeploymentStrategyTypeRecreate, deploy.DeploymentStrategyTypeRolling, deploy.DeploymentStrategyTypeCustom} j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] switch j.Type { case deploy.DeploymentStrategyTypeRecreate: params := &deploy.RecreateDeploymentStrategyParams{} c.Fuzz(params) if params.TimeoutSeconds == nil { s := int64(120) params.TimeoutSeconds = &s } j.RecreateParams = params case deploy.DeploymentStrategyTypeRolling: params := &deploy.RollingDeploymentStrategyParams{} randInt64 := func() *int64 { p := int64(c.RandUint64()) return &p } params.TimeoutSeconds = randInt64() params.IntervalSeconds = randInt64() params.UpdatePeriodSeconds = randInt64() policyTypes := []deploy.LifecycleHookFailurePolicy{ deploy.LifecycleHookFailurePolicyRetry, deploy.LifecycleHookFailurePolicyAbort, deploy.LifecycleHookFailurePolicyIgnore, } if c.RandBool() { params.Pre = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.Post = &deploy.LifecycleHook{ FailurePolicy: policyTypes[c.Rand.Intn(len(policyTypes))], ExecNewPod: &deploy.ExecNewPodHook{ ContainerName: c.RandString(), }, } } if c.RandBool() { params.MaxUnavailable = intstr.FromInt(int(c.RandUint64())) params.MaxSurge = intstr.FromInt(int(c.RandUint64())) } else { params.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64())) params.MaxUnavailable = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64())) } j.RollingParams = params } }, func(j *deploy.DeploymentCauseImageTrigger, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"", "a/b", "a/b/c", "a:5000/b/c", "a/b", "a/b"} tags := []string{"stuff", "other"} j.From.Name = specs[c.Intn(len(specs))] if len(j.From.Name) > 0 { j.From.Name = image.JoinImageStreamTag(j.From.Name, tags[c.Intn(len(tags))]) } }, func(j *deploy.DeploymentTriggerImageChangeParams, c fuzz.Continue) { c.FuzzNoCustom(j) specs := []string{"a/b", "a/b/c", "a:5000/b/c", "a/b:latest", "a/b@test"} j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] }, // TODO: uncomment when round tripping for init containers is available (the annotation is // not supported on security context review for now) func(j *securityapi.PodSecurityPolicyReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil for i := range j.Status.AllowedServiceAccounts { j.Status.AllowedServiceAccounts[i].Template.Spec.InitContainers = nil } }, func(j *securityapi.PodSecurityPolicySelfSubjectReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil j.Status.Template.Spec.InitContainers = nil }, func(j *securityapi.PodSecurityPolicySubjectReview, c fuzz.Continue) { c.FuzzNoCustom(j) j.Spec.Template.Spec.InitContainers = nil j.Status.Template.Spec.InitContainers = nil }, func(j *oauthapi.OAuthAuthorizeToken, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.CodeChallenge) > 0 && len(j.CodeChallengeMethod) == 0 { j.CodeChallengeMethod = "plain" } }, func(j *oauthapi.OAuthClientAuthorization, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.Scopes) == 0 { j.Scopes = append(j.Scopes, "user:full") } }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.WildcardPolicy) == 0 { j.WildcardPolicy = route.WildcardPolicyNone } }, func(j *route.RouteIngress, c fuzz.Continue) { c.FuzzNoCustom(j) if len(j.WildcardPolicy) == 0 { j.WildcardPolicy = route.WildcardPolicyNone } }, func(j *runtime.Object, c fuzz.Continue) { // runtime.EmbeddedObject causes a panic inside of fuzz because runtime.Object isn't handled. }, func(t *time.Time, c fuzz.Continue) { // This is necessary because the standard fuzzed time.Time object is // completely nil, but when JSON unmarshals dates it fills in the // unexported loc field with the time.UTC object, resulting in // reflect.DeepEqual returning false in the round trip tests. We solve it // by using a date that will be identical to the one JSON unmarshals. *t = time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC) }, func(u64 *uint64, c fuzz.Continue) { // TODO: uint64's are NOT handled right. *u64 = c.RandUint64() >> 8 }, ) f.Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { // We do fuzzing on the internal version of the object, and only then // convert to the external version. This is because custom fuzzing // function are only supported for internal objects. internalObj, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't create internal object %v: %v", kind, err) } seed := rand.Int63() apitesting.FuzzerFor(t, group.InternalGroupVersion(), rand.NewSource(seed)). // We are explicitly overwriting custom fuzzing functions, to ensure // that InitContainers and their statuses are not generated. This is // because in thise test we are simply doing json operations, in which // those disappear. Funcs( func(s *api.PodSpec, c fuzz.Continue) { c.FuzzNoCustom(s) s.InitContainers = nil }, func(s *api.PodStatus, c fuzz.Continue) { c.FuzzNoCustom(s) s.InitContainerStatuses = nil }, ).Fuzz(internalObj) item, err := api.Scheme.New(group.GroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't create external object %v: %v", kind, err) } if err := api.Scheme.Convert(internalObj, item, nil); err != nil { t.Fatalf("Conversion for %v failed: %v", kind, err) } data, err := json.Marshal(item) if err != nil { t.Errorf("Error when marshaling object: %v", err) return } unstr := make(map[string]interface{}) err = json.Unmarshal(data, &unstr) if err != nil { t.Errorf("Error when unmarshaling to unstructured: %v", err) return } data, err = json.Marshal(unstr) if err != nil { t.Errorf("Error when marshaling unstructured: %v", err) return } unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface() err = json.Unmarshal(data, &unmarshalledObj) if err != nil { t.Errorf("Error when unmarshaling to object: %v", err) return } if !api.Semantic.DeepEqual(item, unmarshalledObj) { t.Errorf("Object changed during JSON operations, diff: %v", diff.ObjectReflectDiff(item, unmarshalledObj)) return } // TODO; Enable the following part of test once to/from unstructured // format conversions are implemented. /* newUnstr := make(map[string]interface{}) err = unstructured.NewConverter().ToUnstructured(item, &newUnstr) if err != nil { t.Errorf("ToUnstructured failed: %v", err) return } newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) err = unstructured.NewConverter().FromUnstructured(newUnstr, newObj) if err != nil { t.Errorf("FromUnstructured failed: %v", err) return } if !api.Semantic.DeepEqual(item, newObj) { t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(item, newObj)) } */ }