Unify fuzzers and roundtrip tests

This commit is contained in:
Dr. Stefan Schimanski 2017-07-12 16:10:48 +02:00
parent ec2fa9d46c
commit ecc811d263
47 changed files with 591 additions and 261 deletions

View File

@ -14,7 +14,7 @@ go_library(
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)

View File

@ -19,11 +19,12 @@ package fuzzer
import (
"github.com/google/gofuzz"
apitesting "k8s.io/apimachinery/pkg/api/testing"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func KubeadmFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
// Funcs returns the fuzzer functions for the kubeadm apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *kubeadm.MasterConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)

View File

@ -45,6 +45,6 @@ go_test(
tags = ["automanaged"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
],
)

View File

@ -19,10 +19,10 @@ package install
import (
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
kubeadmfuzzer "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer"
)
func TestRoundTripTypes(t *testing.T) {
apitesting.RoundTripTestForAPIGroup(t, Install, fuzzer.KubeadmFuzzerFuncs(t))
roundtrip.RoundTripTestForAPIGroup(t, Install, kubeadmfuzzer.Funcs)
}

View File

@ -9,7 +9,6 @@ cmd/kube-controller-manager/app
cmd/kube-proxy/app
cmd/kubeadm/app
cmd/kubeadm/app/apis/kubeadm
cmd/kubeadm/app/apis/kubeadm/fuzzer
cmd/kubeadm/app/apis/kubeadm/v1alpha1
cmd/kubeadm/app/apis/kubeadm/validation
cmd/kubeadm/app/cmd
@ -579,18 +578,19 @@ staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource
staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition
staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver
staging/src/k8s.io/apimachinery/pkg/api/meta
staging/src/k8s.io/apimachinery/pkg/api/testing
staging/src/k8s.io/apimachinery/pkg/api/testing/fuzzer
staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip
staging/src/k8s.io/apimachinery/pkg/api/validation
staging/src/k8s.io/apimachinery/pkg/api/validation/path
staging/src/k8s.io/apimachinery/pkg/apimachinery/announced
staging/src/k8s.io/apimachinery/pkg/apimachinery/registered
staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer
staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion
staging/src/k8s.io/apimachinery/pkg/apis/meta/v1
staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation
staging/src/k8s.io/apimachinery/pkg/apis/meta/v1alpha1
staging/src/k8s.io/apimachinery/pkg/apis/testapigroup
staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer
staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1
staging/src/k8s.io/apimachinery/pkg/conversion
staging/src/k8s.io/apimachinery/pkg/conversion/unstructured
@ -636,7 +636,6 @@ staging/src/k8s.io/apiserver/pkg/apis/audit
staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1
staging/src/k8s.io/apiserver/pkg/apis/audit/validation
staging/src/k8s.io/apiserver/pkg/apis/example
staging/src/k8s.io/apiserver/pkg/apis/example/fuzzer
staging/src/k8s.io/apiserver/pkg/apis/example/v1
staging/src/k8s.io/apiserver/pkg/audit
staging/src/k8s.io/apiserver/pkg/audit/policy

View File

@ -77,7 +77,8 @@ go_test(
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/unstructured:go_default_library",

View File

@ -22,7 +22,7 @@ import (
"testing"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
@ -31,7 +31,7 @@ import (
)
func BenchmarkPodConversion(b *testing.B) {
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b, api.Codecs), rand.NewSource(benchmarkSeed))
apiObjectFuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
items := make([]api.Pod, 4)
for i := range items {
apiObjectFuzzer.Fuzz(&items[i])

View File

@ -22,20 +22,21 @@ import (
"reflect"
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
"github.com/google/gofuzz"
)
func TestDeepCopyApiObjects(t *testing.T) {
for i := 0; i < *apitesting.FuzzIters; i++ {
for i := 0; i < *roundtrip.FuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(rand.Int63()))
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(rand.Int63()), api.Codecs)
for kind := range api.Scheme.KnownTypes(version) {
doDeepCopyTest(t, version.WithKind(kind), f)
}
@ -82,9 +83,9 @@ func doDeepCopyTest(t *testing.T, kind schema.GroupVersionKind, f *fuzz.Fuzzer)
}
func TestDeepCopySingleType(t *testing.T) {
for i := 0; i < *apitesting.FuzzIters; i++ {
for i := 0; i < *roundtrip.FuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(rand.Int63()))
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(rand.Int63()), api.Codecs)
doDeepCopyTest(t, version.WithKind("Pod"), f)
}
}

View File

@ -27,7 +27,7 @@ import (
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
apiv1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
apitesting "k8s.io/apimachinery/pkg/api/testing"
roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -163,7 +163,7 @@ func TestDefaulting(t *testing.T) {
iter := 0
changedOnce := false
for {
if iter > *apitesting.FuzzIters {
if iter > *roundtrip.FuzzIters {
if !expectedChanged || changedOnce {
break
}

View File

@ -27,7 +27,7 @@ import (
"github.com/gogo/protobuf/proto"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -98,7 +98,7 @@ func fieldsHaveProtobufTags(obj reflect.Type) error {
func TestProtobufRoundTrip(t *testing.T) {
obj := &v1.Pod{}
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(benchmarkSeed)).Fuzz(obj)
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs).Fuzz(obj)
// InitContainers are turned into annotations by conversion.
obj.Spec.InitContainers = nil
obj.Status.InitContainerStatuses = nil

View File

@ -33,7 +33,8 @@ import (
"k8s.io/api/extensions/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
@ -53,7 +54,7 @@ import (
// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate
// fuzzer registered with the apitesting package.
func fuzzInternalObject(t *testing.T, forVersion schema.GroupVersion, item runtime.Object, seed int64) runtime.Object {
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(seed)).Fuzz(item)
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs).Fuzz(item)
j, err := meta.TypeAccessor(item)
if err != nil {
@ -143,9 +144,9 @@ func TestSpecificKind(t *testing.T) {
internalGVK := schema.GroupVersionKind{Group: "extensions", Version: runtime.APIVersionInternal, Kind: "DaemonSet"}
seed := rand.Int63()
fuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(seed))
fuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs)
apitesting.RoundTripSpecificKind(t, internalGVK, api.Scheme, api.Codecs, fuzzer, nil)
roundtrip.RoundTripSpecificKind(t, internalGVK, api.Scheme, api.Codecs, fuzzer, nil)
}
var nonRoundTrippableTypes = sets.NewString(
@ -204,7 +205,7 @@ func TestCommonKindsRegistered(t *testing.T) {
// in all of the API groups registered for test in the testapi package.
func TestRoundTripTypes(t *testing.T) {
seed := rand.Int63()
fuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(seed))
fuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs)
nonRoundTrippableTypes := map[schema.GroupVersionKind]bool{
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeletConfiguration"}: true,
@ -212,7 +213,7 @@ func TestRoundTripTypes(t *testing.T) {
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeSchedulerConfiguration"}: true,
}
apitesting.RoundTripTypes(t, api.Scheme, api.Codecs, fuzzer, nonRoundTrippableTypes)
roundtrip.RoundTripTypes(t, api.Scheme, api.Codecs, fuzzer, nonRoundTrippableTypes)
}
// TestEncodePtr tests that a pointer to a golang type can be encoded and
@ -300,7 +301,7 @@ func TestUnversionedTypes(t *testing.T) {
// 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(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(benchmarkSeed))
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
secret := &api.Secret{}
f.Fuzz(secret)
secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00}
@ -382,7 +383,7 @@ func TestObjectWatchFraming(t *testing.T) {
const benchmarkSeed = 100
func benchmarkItems(b *testing.B) []v1.Pod {
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b, api.Codecs), rand.NewSource(benchmarkSeed))
apiObjectFuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
items := make([]v1.Pod, 10)
for i := range items {
var pod api.Pod

View File

@ -32,6 +32,8 @@ go_library(
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",

View File

@ -26,6 +26,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
genericfuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
@ -49,7 +51,7 @@ import (
// overrideGenericFuncs override some generic fuzzer funcs from k8s.io/apiserver in order to have more realistic
// values in a Kubernetes context.
func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
func overrideGenericFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
@ -83,8 +85,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
// Convert the object to raw bytes
bytes, err := runtime.Encode(codec, obj)
if err != nil {
t.Errorf("Failed to encode object: %v", err)
return
panic(fmt.Sprintf("Failed to encode object: %v", err))
}
// Set the bytes field on the RawExtension
@ -93,7 +94,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
}
}
func coreFuncs(t apitesting.TestingCommon) []interface{} {
func coreFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(q *resource.Quantity, c fuzz.Continue) {
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
@ -500,7 +501,7 @@ func coreFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func extensionFuncs(t apitesting.TestingCommon) []interface{} {
func extensionFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *extensions.DeploymentSpec, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again
@ -580,7 +581,7 @@ func extensionFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func batchFuncs(t apitesting.TestingCommon) []interface{} {
func batchFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *batch.JobSpec, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again
@ -617,7 +618,7 @@ func batchFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func autoscalingFuncs(t apitesting.TestingCommon) []interface{} {
func autoscalingFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *autoscaling.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again
@ -680,7 +681,7 @@ func autoscalingFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func rbacFuncs(t apitesting.TestingCommon) []interface{} {
func rbacFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(r *rbac.RoleRef, c fuzz.Continue) {
c.FuzzNoCustom(r) // fuzz self without calling this function again
@ -714,7 +715,7 @@ func rbacFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func appsFuncs(t apitesting.TestingCommon) []interface{} {
func appsFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *apps.StatefulSet, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again
@ -733,7 +734,7 @@ func appsFuncs(t apitesting.TestingCommon) []interface{} {
},
}
}
func policyFuncs(t apitesting.TestingCommon) []interface{} {
func policyFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *policy.PodDisruptionBudgetStatus, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again
@ -742,7 +743,7 @@ func policyFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func certificateFuncs(t apitesting.TestingCommon) []interface{} {
func certificateFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *certificates.CertificateSigningRequestSpec, c fuzz.Continue) {
c.FuzzNoCustom(obj) // fuzz self without calling this function again
@ -751,7 +752,7 @@ func certificateFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func admissionregistrationFuncs(t apitesting.TestingCommon) []interface{} {
func admissionregistrationFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *admissionregistration.ExternalAdmissionHook, c fuzz.Continue) {
c.FuzzNoCustom(obj) // fuzz self without calling this function again
@ -766,22 +767,20 @@ func admissionregistrationFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func FuzzerFuncs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
return apitesting.MergeFuzzerFuncs(t,
apitesting.GenericFuzzerFuncs(t, codecs),
overrideGenericFuncs(t, codecs),
coreFuncs(t),
extensionFuncs(t),
appsFuncs(t),
batchFuncs(t),
autoscalingFuncs(t),
rbacFuncs(t),
kubeadmfuzzer.KubeadmFuzzerFuncs(t),
policyFuncs(t),
certificateFuncs(t),
admissionregistrationFuncs(t),
)
}
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
genericfuzzer.Funcs,
overrideGenericFuncs,
coreFuncs,
extensionFuncs,
appsFuncs,
batchFuncs,
autoscalingFuncs,
rbacFuncs,
kubeadmfuzzer.Funcs,
policyFuncs,
certificateFuncs,
admissionregistrationFuncs,
)
func newBool(val bool) *bool {
p := new(bool)

View File

@ -21,19 +21,18 @@ import (
"reflect"
"testing"
"github.com/google/gofuzz"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/conversion/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/json"
"github.com/google/gofuzz"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
)
func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) {
@ -45,7 +44,7 @@ func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) {
t.Fatalf("Couldn't create internal object %v: %v", kind, err)
}
seed := rand.Int63()
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(seed)).
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs).
// 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

View File

@ -79,7 +79,7 @@ go_test(
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",

View File

@ -24,16 +24,16 @@ import (
"strings"
"testing"
"github.com/ghodss/yaml"
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
"github.com/ghodss/yaml"
)
func readPod(filename string) ([]byte, error) {
@ -146,7 +146,7 @@ func TestValidateOk(t *testing.T) {
}
seed := rand.Int63()
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(seed))
apiObjectFuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs)
for i := 0; i < 5; i++ {
for _, test := range tests {
testObj := test.obj

View File

@ -10,12 +10,14 @@ load(
go_test(
name = "go_default_test",
srcs = ["types_test.go"],
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",

View File

@ -22,10 +22,13 @@ import (
"github.com/google/gofuzz"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip"
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
var _ runtime.Object = &Example{}
@ -34,7 +37,7 @@ var _ metav1.ObjectMetaAccessor = &Example{}
var _ runtime.Object = &ExampleList{}
var _ metav1.ListMetaAccessor = &ExampleList{}
func exampleFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
func exampleFuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *ExampleList, c fuzz.Continue) {
c.FuzzNoCustom(obj)
@ -55,9 +58,9 @@ func TestRoundTrip(t *testing.T) {
AddToScheme(scheme)
seed := rand.Int63()
fuzzerFuncs := apitesting.MergeFuzzerFuncs(t, apitesting.GenericFuzzerFuncs(t, codecs), exampleFuzzerFuncs(t))
fuzzer := apitesting.FuzzerFor(fuzzerFuncs, rand.NewSource(seed))
fuzzerFuncs := fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, exampleFuzzerFuncs)
fuzzer := fuzzer.FuzzerFor(fuzzerFuncs, rand.NewSource(seed), codecs)
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("Example"), scheme, codecs, fuzzer, nil)
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("ExampleList"), scheme, codecs, fuzzer, nil)
roundtrip.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("Example"), scheme, codecs, fuzzer, nil)
roundtrip.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("ExampleList"), scheme, codecs, fuzzer, nil)
}

View File

@ -0,0 +1,19 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["fuzzer.go"],
tags = ["automanaged"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)

View File

@ -14,25 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package install
package fuzzer
import (
"strings"
"testing"
"github.com/google/gofuzz"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
apitesting "k8s.io/apimachinery/pkg/api/testing"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
func TestRoundTripTypes(t *testing.T) {
apitesting.RoundTripTestForAPIGroup(t, Install, apitesting.MergeFuzzerFuncs(t,
fuzzerFuncs(),
))
}
func fuzzerFuncs() []interface{} {
// Funcs returns the fuzzer functions for the apiextensions apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *apiextensions.CustomResourceDefinitionSpec, c fuzz.Continue) {
c.FuzzNoCustom(obj)

View File

@ -10,13 +10,12 @@ load(
go_test(
name = "go_default_test",
srcs = ["install_test.go"],
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
],
)

View File

@ -0,0 +1,28 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package install
import (
"testing"
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForAPIGroup(t, Install, apiextensionsfuzzer.Funcs)
}

View File

@ -5,44 +5,16 @@ licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["valuefuzz_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [
"codec.go",
"fuzzer.go",
"roundtrip.go",
"valuefuzz.go",
],
srcs = ["codec.go"],
tags = ["automanaged"],
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)

View File

@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["valuefuzz_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [
"fuzzer.go",
"valuefuzz.go",
],
tags = ["automanaged"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)

View File

@ -0,0 +1,52 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import (
"math/rand"
"github.com/google/gofuzz"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
// FuzzerFuncs returns a list of func(*SomeType, c fuzz.Continue) functions.
type FuzzerFuncs func(codecs runtimeserializer.CodecFactory) []interface{}
// FuzzerFor can randomly populate api objects that are destined for version.
func FuzzerFor(funcs FuzzerFuncs, src rand.Source, codecs runtimeserializer.CodecFactory) *fuzz.Fuzzer {
f := fuzz.New().NilChance(.5).NumElements(0, 1)
if src != nil {
f.RandSource(src)
}
f.Funcs(funcs(codecs)...)
return f
}
// MergeFuzzerFuncs will merge the given funcLists, overriding early funcs with later ones if there first
// argument has the same type.
func MergeFuzzerFuncs(funcs ...FuzzerFuncs) FuzzerFuncs {
return FuzzerFuncs(func(codecs runtimeserializer.CodecFactory) []interface{} {
result := []interface{}{}
for _, f := range funcs {
if f != nil {
result = append(result, f(codecs)...)
}
}
return result
})
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
package fuzzer
import (
"reflect"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
package fuzzer
import "testing"

View File

@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["roundtrip.go"],
tags = ["automanaged"],
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)

View File

@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
package roundtrip
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"reflect"
"strings"
"testing"
@ -28,16 +29,19 @@ import (
"github.com/golang/protobuf/proto"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
apimeta "k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/sets"
)
@ -46,7 +50,7 @@ type InstallFunc func(groupFactoryRegistry announced.APIGroupFactoryRegistry, re
// RoundTripTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides
// enough information to round trip
func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs []interface{}) {
func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) {
groupFactoryRegistry := make(announced.APIGroupFactoryRegistry)
registry := registered.NewOrDie("")
scheme := runtime.NewScheme()
@ -56,15 +60,19 @@ func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs
}
// RoundTripTestForScheme is convenient to call if you already have a scheme and want to make sure that its well-formed
func RoundTripTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs []interface{}) {
func RoundTripTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs fuzzer.FuzzerFuncs) {
codecFactory := runtimeserializer.NewCodecFactory(scheme)
fuzzer := DefaultFuzzers(t, codecFactory, fuzzingFuncs)
RoundTripTypesWithoutProtobuf(t, scheme, codecFactory, fuzzer, nil)
f := fuzzer.FuzzerFor(
fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, fuzzingFuncs),
rand.NewSource(rand.Int63()),
codecFactory,
)
RoundTripTypesWithoutProtobuf(t, scheme, codecFactory, f, nil)
}
// RoundTripProtobufTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides
// enough information to round trip
func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs []interface{}) {
func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) {
groupFactoryRegistry := make(announced.APIGroupFactoryRegistry)
registry := registered.NewOrDie("")
scheme := runtime.NewScheme()
@ -74,9 +82,13 @@ func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzi
}
// RoundTripProtobufTestForScheme is convenient to call if you already have a scheme and want to make sure that its well-formed
func RoundTripProtobufTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs []interface{}) {
func RoundTripProtobufTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs fuzzer.FuzzerFuncs) {
codecFactory := runtimeserializer.NewCodecFactory(scheme)
fuzzer := DefaultFuzzers(t, codecFactory, fuzzingFuncs)
fuzzer := fuzzer.FuzzerFor(
fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, fuzzingFuncs),
rand.NewSource(rand.Int63()),
codecFactory,
)
RoundTripTypes(t, scheme, codecFactory, fuzzer, nil)
}
@ -160,7 +172,7 @@ func roundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *ru
func fuzzInternalObject(t *testing.T, fuzzer *fuzz.Fuzzer, object runtime.Object) runtime.Object {
fuzzer.Fuzz(object)
j, err := meta.TypeAccessor(object)
j, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("Unexpected error %v for %#v", err, object)
}
@ -183,7 +195,7 @@ func roundTripToAllExternalVersions(t *testing.T, scheme *runtime.Scheme, codecF
if err != nil {
t.Fatalf("Couldn't make a %v? %v", internalGVK, err)
}
if _, err := meta.TypeAccessor(object); err != nil {
if _, err := apimeta.TypeAccessor(object); err != nil {
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", internalGVK, err)
}
@ -204,7 +216,7 @@ func roundTripToAllExternalVersions(t *testing.T, scheme *runtime.Scheme, codecF
}
t.Logf("\tround tripping to %v %v", externalGVK, externalGoType)
roundTrip(t, scheme, TestCodec(codecFactory, externalGVK.GroupVersion()), object)
roundTrip(t, scheme, apitesting.TestCodec(codecFactory, externalGVK.GroupVersion()), object)
// TODO remove this hack after we're past the intermediate steps
if !skipProtobuf && externalGVK.Group != "kubeadm.k8s.io" {
@ -220,7 +232,7 @@ func roundTripOfExternalType(t *testing.T, scheme *runtime.Scheme, codecFactory
if err != nil {
t.Fatalf("Couldn't make a %v? %v", externalGVK, err)
}
typeAcc, err := meta.TypeAccessor(object)
typeAcc, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", externalGVK, err)
}
@ -279,7 +291,7 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
// copy or conversion should alter the object
// TODO eliminate this global
if !apiequality.Semantic.DeepEqual(original, object) {
t.Errorf("0: %v: encode altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object))
t.Errorf("%v: encode altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object))
return
}
@ -303,14 +315,14 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
// decode (deserialize) the encoded data back into an object
obj2, err := runtime.Decode(codec, data)
if err != nil {
t.Errorf("0: %v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", object))
t.Errorf("%v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", object))
panic("failed")
}
// ensure that the object produced from decoding the encoded data is equal
// to the original object
if !apiequality.Semantic.DeepEqual(original, obj2) {
t.Errorf("1: %v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(object, obj2), codec, printer.Sprintf("%#v", object), dataAsString(data), printer.Sprintf("%#v", obj2))
t.Errorf("%v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(object, obj2), codec, printer.Sprintf("%#v", object), dataAsString(data), printer.Sprintf("%#v", obj2))
return
}
@ -318,27 +330,66 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
// create a new object)
obj3 := reflect.New(reflect.TypeOf(object).Elem()).Interface().(runtime.Object)
if err := runtime.DecodeInto(codec, data, obj3); err != nil {
t.Errorf("2: %v: %v", name, err)
t.Errorf("%v: %v", name, err)
return
}
// special case for kinds which are internal and external at the same time (many in meta.k8s.io are). For those
// runtime.DecodeInto above will return the external variant and set the APIVersion and kind, while the input
// object might be internal. Hence, we clear those values for obj3 for that case to correctly compare.
intAndExt, err := internalAndExternalKind(scheme, object)
if err != nil {
t.Errorf("%v: %v", name, err)
return
}
if intAndExt {
typeAcc, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("%v: error accessing TypeMeta: %v", name, err)
}
if len(typeAcc.GetAPIVersion()) == 0 {
typeAcc, err := apimeta.TypeAccessor(obj3)
if err != nil {
t.Fatalf("%v: error accessing TypeMeta: %v", name, err)
}
typeAcc.SetAPIVersion("")
typeAcc.SetKind("")
}
}
// ensure that the new runtime object is equal to the original after being
// decoded into
if !apiequality.Semantic.DeepEqual(object, obj3) {
t.Errorf("3: %v: diff: %v\nCodec: %#v", name, diff.ObjectReflectDiff(object, obj3), codec)
t.Errorf("%v: diff: %v\nCodec: %#v", name, diff.ObjectReflectDiff(object, obj3), codec)
return
}
// do structure-preserving fuzzing of the deep-copied object. If it shares anything with the original,
// the deep-copy was actually only a shallow copy. Then original and obj3 will be different after fuzzing.
// NOTE: we use the encoding+decoding here as an alternative, guaranteed deep-copy to compare against.
ValueFuzz(object)
fuzzer.ValueFuzz(object)
if !apiequality.Semantic.DeepEqual(original, obj3) {
t.Errorf("0: %v: fuzzing a copy altered the original, diff: %v", name, diff.ObjectReflectDiff(original, object))
t.Errorf("%v: fuzzing a copy altered the original, diff: %v", name, diff.ObjectReflectDiff(original, object))
return
}
}
func internalAndExternalKind(scheme *runtime.Scheme, object runtime.Object) (bool, error) {
kinds, _, err := scheme.ObjectKinds(object)
if err != nil {
return false, err
}
internal, external := false, false
for _, k := range kinds {
if k.Version == runtime.APIVersionInternal {
internal = true
} else {
external = true
}
}
return internal && external, nil
}
// dataAsString returns the given byte array as a string; handles detecting
// protocol buffers.
func dataAsString(data []byte) string {

View File

@ -0,0 +1,25 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["fuzzer.go"],
tags = ["automanaged"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
],
)

View File

@ -14,24 +14,25 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
package fuzzer
import (
"math/rand"
"reflect"
"fmt"
"strconv"
"testing"
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/resource"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1alpha1 "k8s.io/apimachinery/pkg/apis/meta/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/types"
)
func GenericFuzzerFuncs(t TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
func genericFuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(q *resource.Quantity, c fuzz.Continue) {
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
@ -53,28 +54,6 @@ func GenericFuzzerFuncs(t TestingCommon, codecs runtimeserializer.CodecFactory)
j.APIVersion = ""
j.Kind = ""
},
func(j *metav1.TypeMeta, c fuzz.Continue) {
// We have to customize the randomization of TypeMetas because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = ""
j.Kind = ""
},
func(j *metav1.ObjectMeta, c fuzz.Continue) {
j.Name = c.RandString()
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
j.UID = types.UID(c.RandString())
j.GenerateName = c.RandString()
var sec, nsec int64
c.Fuzz(&sec)
c.Fuzz(&nsec)
j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy()
},
func(j *metav1.ListMeta, c fuzz.Continue) {
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
},
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
if true { //c.RandBool() {
@ -98,77 +77,100 @@ func GenericFuzzerFuncs(t TestingCommon, codecs runtimeserializer.CodecFactory)
// Find a codec for converting the object to raw bytes. This is necessary for the
// api version and kind to be correctly set be serialization.
var codec = TestCodec(codecs, metav1.SchemeGroupVersion)
var codec = apitesting.TestCodec(codecs, metav1.SchemeGroupVersion)
// Convert the object to raw bytes
bytes, err := runtime.Encode(codec, obj)
if err != nil {
t.Errorf("Failed to encode object: %v", err)
panic(fmt.Sprintf("Failed to encode object: %v", err))
return
}
// strip trailing newlines which do not survive roundtrips
for len(bytes) >= 1 && bytes[len(bytes)-1] == 10 {
bytes = bytes[:len(bytes)-1]
}
// Set the bytes field on the RawExtension
r.Raw = bytes
},
}
}
// TestingCommon abstracts testing.T and testing.B
type TestingCommon interface {
Log(args ...interface{})
Logf(format string, args ...interface{})
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
}
func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *metav1.TypeMeta, c fuzz.Continue) {
// We have to customize the randomization of TypeMetas because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = ""
j.Kind = ""
},
func(j *metav1.ObjectMeta, c fuzz.Continue) {
j.Name = c.RandString()
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
j.UID = types.UID(c.RandString())
j.GenerateName = c.RandString()
var (
_ TestingCommon = &testing.T{}
_ TestingCommon = &testing.B{}
)
// FuzzerFor can randomly populate api objects that are destined for version.
func FuzzerFor(funcs []interface{}, src rand.Source) *fuzz.Fuzzer {
f := fuzz.New().NilChance(.5).NumElements(0, 1)
if src != nil {
f.RandSource(src)
var sec, nsec int64
c.Fuzz(&sec)
c.Fuzz(&nsec)
j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy()
},
func(j *metav1.ListMeta, c fuzz.Continue) {
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
},
}
f.Funcs(funcs...)
return f
}
// MergeFuzzerFuncs will merge the given funcLists, overriding early funcs with later ones if there first
// argument has the same type.
func MergeFuzzerFuncs(t TestingCommon, funcLists ...[]interface{}) []interface{} {
funcMap := map[string]interface{}{}
for _, list := range funcLists {
for _, f := range list {
fT := reflect.TypeOf(f)
if fT.Kind() != reflect.Func || fT.NumIn() != 2 {
t.Errorf("Fuzzer func with invalid type: %v", fT)
continue
func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(r *metav1alpha1.TableRow, c fuzz.Continue) {
c.Fuzz(&r.Object)
c.Fuzz(&r.Conditions)
if len(r.Conditions) == 0 {
r.Conditions = nil
}
funcMap[fT.In(0).String()] = f
}
n := c.Intn(10)
if n > 0 {
r.Cells = make([]interface{}, n)
}
for i := range r.Cells {
t := c.Intn(6)
switch t {
case 0:
r.Cells[i] = c.RandString()
case 1:
r.Cells[i] = c.Uint64()
case 2:
r.Cells[i] = c.RandBool()
case 3:
// maps roundtrip as map[interface{}]interface{}, but the json codec cannot encode that
// TODO: get maps to roundtrip properly
/*
x := map[string]interface{}{}
for j := c.Intn(10) + 1; j >= 0; j-- {
x[c.RandString()] = c.RandString()
}
r.Cells[i] = x
*/
case 4:
x := make([]interface{}, c.Intn(10))
for i := range x {
x[i] = c.Uint64()
}
r.Cells[i] = x
default:
r.Cells[i] = nil
}
}
},
}
result := []interface{}{}
for _, f := range funcMap {
result = append(result, f)
}
return result
}
func DefaultFuzzers(t TestingCommon, codecFactory runtimeserializer.CodecFactory, fuzzerFuncs []interface{}) *fuzz.Fuzzer {
seed := rand.Int63()
return FuzzerFor(
MergeFuzzerFuncs(t,
GenericFuzzerFuncs(t, codecFactory),
fuzzerFuncs,
),
rand.NewSource(seed),
)
}
var Funcs = fuzzer.MergeFuzzerFuncs(
genericFuzzerFuncs,
v1FuzzerFuncs,
v1alpha1FuzzerFuncs,
)

View File

@ -10,10 +10,15 @@ load(
go_test(
name = "go_default_test",
srcs = ["register_test.go"],
srcs = [
"register_test.go",
"roundtrip_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],

View File

@ -0,0 +1,28 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package internalversion
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/apis/meta/fuzzer"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForScheme(t, scheme, fuzzer.Funcs)
}

View File

@ -14,6 +14,7 @@ go_library(
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -17,18 +17,21 @@ limitations under the License.
package fuzzer
import (
"fmt"
"github.com/google/gofuzz"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
// overrideGenericFuncs override some generic fuzzer funcs from k8s.io/apimachinery in order to have more realistic
// overrideMetaFuncs override some generic fuzzer funcs from k8s.io/apimachinery in order to have more realistic
// values in a Kubernetes context.
func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
@ -54,7 +57,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
// Convert the object to raw bytes
bytes, err := runtime.Encode(apitesting.TestCodec(codecs, v1.SchemeGroupVersion), obj)
if err != nil {
t.Errorf("Failed to encode object: %v", err)
panic(fmt.Sprintf("Failed to encode object: %v", err))
return
}
@ -64,7 +67,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
}
}
func testapigroupFuncs(t apitesting.TestingCommon) []interface{} {
func testapigroupFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *testapigroup.CarpSpec, c fuzz.Continue) {
c.FuzzNoCustom(s)
@ -90,10 +93,8 @@ func testapigroupFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func Funcs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
return apitesting.MergeFuzzerFuncs(t,
apitesting.GenericFuzzerFuncs(t, codecs),
overrideGenericFuncs(t, codecs),
testapigroupFuncs(t),
)
}
// Funcs returns the fuzzer functions for the testapigroup.
var Funcs = fuzzer.MergeFuzzerFuncs(
overrideMetaFuncs,
testapigroupFuncs,
)

View File

@ -5,6 +5,7 @@ licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
@ -19,3 +20,14 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer:go_default_library",
],
)

View File

@ -0,0 +1,28 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package install
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
testapigroupfuzzer "k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForAPIGroup(t, Install, testapigroupfuzzer.Funcs)
}

View File

@ -14,6 +14,7 @@ go_library(
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library",

View File

@ -17,18 +17,21 @@ limitations under the License.
package fuzzer
import (
"fmt"
"github.com/google/gofuzz"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apiserver/pkg/apis/example"
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
)
// overrideGenericFuncs override some generic fuzzer funcs from k8s.io/apiserver in order to have more realistic
// overrideMetaFuncs override some generic fuzzer funcs from k8s.io/apiserver in order to have more realistic
// values in a Kubernetes context.
func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
@ -54,7 +57,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
// Convert the object to raw bytes
bytes, err := runtime.Encode(apitesting.TestCodec(codecs, examplev1.SchemeGroupVersion), obj)
if err != nil {
t.Errorf("Failed to encode object: %v", err)
panic(fmt.Sprintf("Failed to encode object: %v", err))
return
}
@ -64,7 +67,7 @@ func overrideGenericFuncs(t apitesting.TestingCommon, codecs runtimeserializer.C
}
}
func exampleFuncs(t apitesting.TestingCommon) []interface{} {
func exampleFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *example.PodSpec, c fuzz.Continue) {
c.FuzzNoCustom(s)
@ -90,10 +93,8 @@ func exampleFuncs(t apitesting.TestingCommon) []interface{} {
}
}
func Funcs(t apitesting.TestingCommon, codecs runtimeserializer.CodecFactory) []interface{} {
return apitesting.MergeFuzzerFuncs(t,
apitesting.GenericFuzzerFuncs(t, codecs),
overrideGenericFuncs(t, codecs),
exampleFuncs(t),
)
}
// Funcs returns the fuzzer functions for the example api group.
var Funcs = fuzzer.MergeFuzzerFuncs(
overrideMetaFuncs,
exampleFuncs,
)

View File

@ -5,6 +5,7 @@ licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
@ -19,3 +20,14 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/example/fuzzer:go_default_library",
],
)

View File

@ -0,0 +1,28 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package install
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
examplefuzzer "k8s.io/apiserver/pkg/apis/example/fuzzer"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForAPIGroup(t, Install, examplefuzzer.Funcs)
}

View File

@ -25,7 +25,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",

View File

@ -41,7 +41,7 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality"
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
fuzzer "k8s.io/apimachinery/pkg/api/testing/fuzzer"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -4104,7 +4104,7 @@ func newTestRequestInfoResolver() *request.RequestInfoFactory {
const benchmarkSeed = 100
func benchmarkItems(b *testing.B) []example.Pod {
clientapiObjectFuzzer := apitesting.FuzzerFor(examplefuzzer.Funcs(b, codecs), rand.NewSource(benchmarkSeed))
clientapiObjectFuzzer := fuzzer.FuzzerFor(examplefuzzer.Funcs, rand.NewSource(benchmarkSeed), codecs)
items := make([]example.Pod, 3)
for i := range items {
clientapiObjectFuzzer.Fuzz(&items[i])

View File

@ -10,10 +10,10 @@ load(
go_test(
name = "go_default_test",
srcs = ["install_test.go"],
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library"],
)
go_library(

View File

@ -19,9 +19,9 @@ package install
import (
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip"
)
func TestRoundTripTypes(t *testing.T) {
apitesting.RoundTripTestForAPIGroup(t, Install, nil)
roundtrip.RoundTripTestForAPIGroup(t, Install, nil)
}

View File

@ -13,7 +13,7 @@ go_test(
srcs = ["scheme_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library"],
)
go_library(

View File

@ -19,9 +19,9 @@ package apiserver
import (
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
)
func TestRoundTripTypes(t *testing.T) {
apitesting.RoundTripTestForScheme(t, Scheme, nil)
roundtrip.RoundTripTestForScheme(t, Scheme, nil)
}