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.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) } } } }
// 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 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) } }
// 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 fuzzInternalObject(t *testing.T, forVersion string, 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 TestInternalRoundTrip(t *testing.T) { latest := "v1beta2" seed := rand.Int63() apiObjectFuzzer := apitesting.FuzzerFor(t, "", rand.NewSource(seed)) for k := range internal.Scheme.KnownTypes("") { obj, err := internal.Scheme.New("", k) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } apiObjectFuzzer.Fuzz(obj) newer, err := internal.Scheme.New(latest, k) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if err := internal.Scheme.Convert(obj, newer); err != nil { t.Errorf("unable to convert %#v to %#v: %v", obj, newer, err) continue } actual, err := internal.Scheme.New("", k) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if err := internal.Scheme.Convert(newer, actual); err != nil { t.Errorf("unable to convert %#v to %#v: %v", newer, actual, err) continue } if !internal.Semantic.DeepEqual(obj, actual) { t.Errorf("%s: diff %s", k, util.ObjectDiff(obj, actual)) } } }
func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { for _, version := range []string{"", testapi.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("expected %#v\ngot %#v", item, itemCopy) } } } } }
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 *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 *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 }