mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
pkg/api/testing: split fuzzer between apimachinery and kube
This commit is contained in:
parent
a12c661773
commit
6b6b6c747e
@ -21,15 +21,16 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkPodConversion(b *testing.B) {
|
func BenchmarkPodConversion(b *testing.B) {
|
||||||
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
|
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
|
||||||
items := make([]api.Pod, 4)
|
items := make([]api.Pod, 4)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
apiObjectFuzzer.Fuzz(&items[i])
|
apiObjectFuzzer.Fuzz(&items[i])
|
||||||
|
@ -22,11 +22,12 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
|
|
||||||
"github.com/google/gofuzz"
|
"github.com/google/gofuzz"
|
||||||
)
|
)
|
||||||
@ -34,7 +35,7 @@ import (
|
|||||||
func TestDeepCopyApiObjects(t *testing.T) {
|
func TestDeepCopyApiObjects(t *testing.T) {
|
||||||
for i := 0; i < *fuzzIters; i++ {
|
for i := 0; i < *fuzzIters; i++ {
|
||||||
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
|
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
|
||||||
f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63()))
|
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(rand.Int63()))
|
||||||
for kind := range api.Scheme.KnownTypes(version) {
|
for kind := range api.Scheme.KnownTypes(version) {
|
||||||
doDeepCopyTest(t, version.WithKind(kind), f)
|
doDeepCopyTest(t, version.WithKind(kind), f)
|
||||||
}
|
}
|
||||||
@ -83,7 +84,7 @@ func doDeepCopyTest(t *testing.T, kind schema.GroupVersionKind, f *fuzz.Fuzzer)
|
|||||||
func TestDeepCopySingleType(t *testing.T) {
|
func TestDeepCopySingleType(t *testing.T) {
|
||||||
for i := 0; i < *fuzzIters; i++ {
|
for i := 0; i < *fuzzIters; i++ {
|
||||||
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
|
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
|
||||||
f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63()))
|
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(rand.Int63()))
|
||||||
doDeepCopyTest(t, version.WithKind("Pod"), f)
|
doDeepCopyTest(t, version.WithKind("Pod"), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -31,7 +32,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
_ "k8s.io/kubernetes/pkg/apis/extensions"
|
_ "k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
@ -75,7 +76,7 @@ func TestUniversalDeserializer(t *testing.T) {
|
|||||||
|
|
||||||
func TestProtobufRoundTrip(t *testing.T) {
|
func TestProtobufRoundTrip(t *testing.T) {
|
||||||
obj := &v1.Pod{}
|
obj := &v1.Pod{}
|
||||||
apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(benchmarkSeed)).Fuzz(obj)
|
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(benchmarkSeed)).Fuzz(obj)
|
||||||
// InitContainers are turned into annotations by conversion.
|
// InitContainers are turned into annotations by conversion.
|
||||||
obj.Spec.InitContainers = nil
|
obj.Spec.InitContainers = nil
|
||||||
obj.Status.InitContainerStatuses = nil
|
obj.Status.InitContainerStatuses = nil
|
||||||
@ -96,7 +97,7 @@ func TestProtobufRoundTrip(t *testing.T) {
|
|||||||
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
|
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
|
||||||
// reflection (to clear APIVersion and Kind)
|
// reflection (to clear APIVersion and Kind)
|
||||||
func BenchmarkEncodeCodecProtobuf(b *testing.B) {
|
func BenchmarkEncodeCodecProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type")
|
s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type")
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
@ -111,7 +112,7 @@ func BenchmarkEncodeCodecProtobuf(b *testing.B) {
|
|||||||
// BenchmarkEncodeCodecFromInternalProtobuf measures the cost of performing a codec encode,
|
// BenchmarkEncodeCodecFromInternalProtobuf measures the cost of performing a codec encode,
|
||||||
// including conversions and any type setting. This is a "full" encode.
|
// including conversions and any type setting. This is a "full" encode.
|
||||||
func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
|
func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encodable := make([]api.Pod, width)
|
encodable := make([]api.Pod, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -131,7 +132,7 @@ func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) {
|
func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
@ -145,7 +146,7 @@ func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) {
|
|||||||
// BenchmarkDecodeCodecToInternalProtobuf measures the cost of performing a codec decode,
|
// BenchmarkDecodeCodecToInternalProtobuf measures the cost of performing a codec decode,
|
||||||
// including conversions and any type setting. This is a "full" decode.
|
// including conversions and any type setting. This is a "full" decode.
|
||||||
func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) {
|
func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
s := protobuf.NewSerializer(api.Scheme, api.Scheme, "application/arbitrary.content.type")
|
s := protobuf.NewSerializer(api.Scheme, api.Scheme, "application/arbitrary.content.type")
|
||||||
encoder := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion)
|
encoder := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion)
|
||||||
@ -170,7 +171,7 @@ func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) {
|
|||||||
|
|
||||||
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
|
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
|
||||||
func BenchmarkDecodeIntoProtobuf(b *testing.B) {
|
func BenchmarkDecodeIntoProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/conversion"
|
"k8s.io/apimachinery/pkg/conversion"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -43,7 +44,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
@ -63,7 +64,7 @@ var codecsToTest = []func(version schema.GroupVersion, item runtime.Object) (run
|
|||||||
// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate
|
// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate
|
||||||
// fuzzer registered with the apitesting package.
|
// fuzzer registered with the apitesting package.
|
||||||
func fuzzInternalObject(t *testing.T, forVersion schema.GroupVersion, item runtime.Object, seed int64) runtime.Object {
|
func fuzzInternalObject(t *testing.T, forVersion schema.GroupVersion, item runtime.Object, seed int64) runtime.Object {
|
||||||
apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item)
|
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(seed)).Fuzz(item)
|
||||||
|
|
||||||
j, err := meta.TypeAccessor(item)
|
j, err := meta.TypeAccessor(item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -440,7 +441,7 @@ func TestUnversionedTypes(t *testing.T) {
|
|||||||
// TestObjectWatchFraming establishes that a watch event can be encoded and
|
// TestObjectWatchFraming establishes that a watch event can be encoded and
|
||||||
// decoded correctly through each of the supported RFC2046 media types.
|
// decoded correctly through each of the supported RFC2046 media types.
|
||||||
func TestObjectWatchFraming(t *testing.T) {
|
func TestObjectWatchFraming(t *testing.T) {
|
||||||
f := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
|
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(benchmarkSeed))
|
||||||
secret := &api.Secret{}
|
secret := &api.Secret{}
|
||||||
f.Fuzz(secret)
|
f.Fuzz(secret)
|
||||||
secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00}
|
secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00}
|
||||||
@ -521,8 +522,8 @@ func TestObjectWatchFraming(t *testing.T) {
|
|||||||
|
|
||||||
const benchmarkSeed = 100
|
const benchmarkSeed = 100
|
||||||
|
|
||||||
func benchmarkItems() []v1.Pod {
|
func benchmarkItems(b *testing.B) []v1.Pod {
|
||||||
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
|
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
|
||||||
items := make([]v1.Pod, 10)
|
items := make([]v1.Pod, 10)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
var pod api.Pod
|
var pod api.Pod
|
||||||
@ -540,7 +541,7 @@ func benchmarkItems() []v1.Pod {
|
|||||||
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
|
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
|
||||||
// reflection (to clear APIVersion and Kind)
|
// reflection (to clear APIVersion and Kind)
|
||||||
func BenchmarkEncodeCodec(b *testing.B) {
|
func BenchmarkEncodeCodec(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
@ -554,7 +555,7 @@ func BenchmarkEncodeCodec(b *testing.B) {
|
|||||||
// BenchmarkEncodeCodecFromInternal measures the cost of performing a codec encode,
|
// BenchmarkEncodeCodecFromInternal measures the cost of performing a codec encode,
|
||||||
// including conversions.
|
// including conversions.
|
||||||
func BenchmarkEncodeCodecFromInternal(b *testing.B) {
|
func BenchmarkEncodeCodecFromInternal(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encodable := make([]api.Pod, width)
|
encodable := make([]api.Pod, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -573,7 +574,7 @@ func BenchmarkEncodeCodecFromInternal(b *testing.B) {
|
|||||||
|
|
||||||
// BenchmarkEncodeJSONMarshal provides a baseline for regular JSON encode performance
|
// BenchmarkEncodeJSONMarshal provides a baseline for regular JSON encode performance
|
||||||
func BenchmarkEncodeJSONMarshal(b *testing.B) {
|
func BenchmarkEncodeJSONMarshal(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
@ -586,7 +587,7 @@ func BenchmarkEncodeJSONMarshal(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkDecodeCodec(b *testing.B) {
|
func BenchmarkDecodeCodec(b *testing.B) {
|
||||||
codec := testapi.Default.Codec()
|
codec := testapi.Default.Codec()
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -608,7 +609,7 @@ func BenchmarkDecodeCodec(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
|
func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
|
||||||
codec := testapi.Default.Codec()
|
codec := testapi.Default.Codec()
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -631,7 +632,7 @@ func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
|
func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
|
||||||
codec := testapi.Default.Codec()
|
codec := testapi.Default.Codec()
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -655,7 +656,7 @@ func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
|
|||||||
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
|
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
|
||||||
func BenchmarkDecodeIntoJSON(b *testing.B) {
|
func BenchmarkDecodeIntoJSON(b *testing.B) {
|
||||||
codec := testapi.Default.Codec()
|
codec := testapi.Default.Codec()
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
@ -679,7 +680,7 @@ func BenchmarkDecodeIntoJSON(b *testing.B) {
|
|||||||
// BenchmarkDecodeJSON provides a baseline for codecgen JSON decode performance
|
// BenchmarkDecodeJSON provides a baseline for codecgen JSON decode performance
|
||||||
func BenchmarkDecodeIntoJSONCodecGen(b *testing.B) {
|
func BenchmarkDecodeIntoJSONCodecGen(b *testing.B) {
|
||||||
kcodec := testapi.Default.Codec()
|
kcodec := testapi.Default.Codec()
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
width := len(items)
|
width := len(items)
|
||||||
encoded := make([][]byte, width)
|
encoded := make([][]byte, width)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
|
@ -18,19 +18,17 @@ package testing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/gofuzz"
|
"github.com/google/gofuzz"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
@ -44,51 +42,65 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FuzzerFor can randomly populate api objects that are destined for version.
|
// overrideGenericFuncs override some generic fuzzer funcs from k8s.io/apiserver in order to have more realistic
|
||||||
func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz.Fuzzer {
|
// values in a Kubernetes context.
|
||||||
f := fuzz.New().NilChance(.5).NumElements(0, 1)
|
func overrideGenericFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
if src != nil {
|
return []interface{}{
|
||||||
f.RandSource(src)
|
func(j *runtime.Object, c fuzz.Continue) {
|
||||||
|
// TODO: uncomment when round trip starts from a versioned object
|
||||||
|
if true { //c.RandBool() {
|
||||||
|
*j = &runtime.Unknown{
|
||||||
|
// We do not set TypeMeta here because it is not carried through a round trip
|
||||||
|
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
|
||||||
|
ContentType: runtime.ContentTypeJSON,
|
||||||
}
|
}
|
||||||
f.Funcs(
|
|
||||||
func(j *int, c fuzz.Continue) {
|
|
||||||
*j = int(c.Int31())
|
|
||||||
},
|
|
||||||
func(j **int, c fuzz.Continue) {
|
|
||||||
if c.RandBool() {
|
|
||||||
i := int(c.Int31())
|
|
||||||
*j = &i
|
|
||||||
} else {
|
} else {
|
||||||
*j = nil
|
types := []runtime.Object{&api.Pod{}, &api.ReplicationController{}}
|
||||||
|
t := types[c.Rand.Intn(len(types))]
|
||||||
|
c.Fuzz(t)
|
||||||
|
*j = t
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
func(r *runtime.RawExtension, c fuzz.Continue) {
|
||||||
|
// Pick an arbitrary type and fuzz it
|
||||||
|
types := []runtime.Object{&api.Pod{}, &extensions.Deployment{}, &api.Service{}}
|
||||||
|
obj := types[c.Rand.Intn(len(types))]
|
||||||
|
c.Fuzz(obj)
|
||||||
|
|
||||||
|
// 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 runtime.Codec
|
||||||
|
switch obj.(type) {
|
||||||
|
case *api.Pod:
|
||||||
|
codec = testapi.Default.Codec()
|
||||||
|
case *extensions.Deployment:
|
||||||
|
codec = testapi.Extensions.Codec()
|
||||||
|
case *api.Service:
|
||||||
|
codec = testapi.Default.Codec()
|
||||||
|
default:
|
||||||
|
|
||||||
|
t.Errorf("Failed to find codec for object type: %T", obj)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the object to raw bytes
|
||||||
|
bytes, err := runtime.Encode(codec, obj)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to encode object: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the bytes field on the RawExtension
|
||||||
|
r.Raw = bytes
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func coreFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
func(q *resource.Quantity, c fuzz.Continue) {
|
func(q *resource.Quantity, c fuzz.Continue) {
|
||||||
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
|
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
|
||||||
},
|
},
|
||||||
func(j *runtime.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.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 *api.ObjectReference, c fuzz.Continue) {
|
func(j *api.ObjectReference, c fuzz.Continue) {
|
||||||
// We have to customize the randomization of TypeMetas because their
|
// We have to customize the randomization of TypeMetas because their
|
||||||
// APIVersion and Kind must remain blank in memory.
|
// APIVersion and Kind must remain blank in memory.
|
||||||
@ -99,10 +111,6 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
|
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
|
||||||
j.FieldPath = c.RandString()
|
j.FieldPath = c.RandString()
|
||||||
},
|
},
|
||||||
func(j *metav1.ListMeta, c fuzz.Continue) {
|
|
||||||
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
|
|
||||||
j.SelfLink = c.RandString()
|
|
||||||
},
|
|
||||||
func(j *api.ListOptions, c fuzz.Continue) {
|
func(j *api.ListOptions, c fuzz.Continue) {
|
||||||
label, _ := labels.Parse("a=b")
|
label, _ := labels.Parse("a=b")
|
||||||
j.LabelSelector = label
|
j.LabelSelector = label
|
||||||
@ -158,48 +166,6 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
//j.TemplateRef = nil // this is required for round trip
|
//j.TemplateRef = nil // this is required for round trip
|
||||||
},
|
},
|
||||||
func(j *extensions.DeploymentStrategy, c fuzz.Continue) {
|
|
||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
|
||||||
// Ensure that strategyType is one of valid values.
|
|
||||||
strategyTypes := []extensions.DeploymentStrategyType{extensions.RecreateDeploymentStrategyType, extensions.RollingUpdateDeploymentStrategyType}
|
|
||||||
j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))]
|
|
||||||
if j.Type != extensions.RollingUpdateDeploymentStrategyType {
|
|
||||||
j.RollingUpdate = nil
|
|
||||||
} else {
|
|
||||||
rollingUpdate := extensions.RollingUpdateDeployment{}
|
|
||||||
if c.RandBool() {
|
|
||||||
rollingUpdate.MaxUnavailable = intstr.FromInt(int(c.Rand.Int31()))
|
|
||||||
rollingUpdate.MaxSurge = intstr.FromInt(int(c.Rand.Int31()))
|
|
||||||
} else {
|
|
||||||
rollingUpdate.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.Rand.Int31()))
|
|
||||||
}
|
|
||||||
j.RollingUpdate = &rollingUpdate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
func(j *batch.JobSpec, c fuzz.Continue) {
|
|
||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
|
||||||
completions := int32(c.Rand.Int31())
|
|
||||||
parallelism := int32(c.Rand.Int31())
|
|
||||||
j.Completions = &completions
|
|
||||||
j.Parallelism = ¶llelism
|
|
||||||
if c.Rand.Int31()%2 == 0 {
|
|
||||||
j.ManualSelector = newBool(true)
|
|
||||||
} else {
|
|
||||||
j.ManualSelector = nil
|
|
||||||
}
|
|
||||||
},
|
|
||||||
func(sj *batch.CronJobSpec, c fuzz.Continue) {
|
|
||||||
c.FuzzNoCustom(sj)
|
|
||||||
suspend := c.RandBool()
|
|
||||||
sj.Suspend = &suspend
|
|
||||||
sds := int64(c.RandUint64())
|
|
||||||
sj.StartingDeadlineSeconds = &sds
|
|
||||||
sj.Schedule = c.RandString()
|
|
||||||
},
|
|
||||||
func(cp *batch.ConcurrencyPolicy, c fuzz.Continue) {
|
|
||||||
policies := []batch.ConcurrencyPolicy{batch.AllowConcurrent, batch.ForbidConcurrent, batch.ReplaceConcurrent}
|
|
||||||
*cp = policies[c.Rand.Intn(len(policies))]
|
|
||||||
},
|
|
||||||
func(j *api.List, c fuzz.Continue) {
|
func(j *api.List, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
// TODO: uncomment when round trip starts from a versioned object
|
// TODO: uncomment when round trip starts from a versioned object
|
||||||
@ -207,21 +173,6 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
j.Items = []runtime.Object{}
|
j.Items = []runtime.Object{}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(j *runtime.Object, c fuzz.Continue) {
|
|
||||||
// TODO: uncomment when round trip starts from a versioned object
|
|
||||||
if true { //c.RandBool() {
|
|
||||||
*j = &runtime.Unknown{
|
|
||||||
// We do not set TypeMeta here because it is not carried through a round trip
|
|
||||||
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
|
|
||||||
ContentType: runtime.ContentTypeJSON,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
types := []runtime.Object{&api.Pod{}, &api.ReplicationController{}}
|
|
||||||
t := types[c.Rand.Intn(len(types))]
|
|
||||||
c.Fuzz(t)
|
|
||||||
*j = t
|
|
||||||
}
|
|
||||||
},
|
|
||||||
func(q *api.ResourceRequirements, c fuzz.Continue) {
|
func(q *api.ResourceRequirements, c fuzz.Continue) {
|
||||||
randomQuantity := func() resource.Quantity {
|
randomQuantity := func() resource.Quantity {
|
||||||
var q resource.Quantity
|
var q resource.Quantity
|
||||||
@ -513,12 +464,28 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
c.FuzzNoCustom(s)
|
c.FuzzNoCustom(s)
|
||||||
s.Allocatable = s.Capacity
|
s.Allocatable = s.Capacity
|
||||||
},
|
},
|
||||||
func(s *autoscaling.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
|
}
|
||||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
}
|
||||||
minReplicas := int32(c.Rand.Int31())
|
|
||||||
s.MinReplicas = &minReplicas
|
func extensionFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
targetCpu := int32(c.RandUint64())
|
return []interface{}{
|
||||||
s.TargetCPUUtilizationPercentage = &targetCpu
|
func(j *extensions.DeploymentStrategy, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
|
// Ensure that strategyType is one of valid values.
|
||||||
|
strategyTypes := []extensions.DeploymentStrategyType{extensions.RecreateDeploymentStrategyType, extensions.RollingUpdateDeploymentStrategyType}
|
||||||
|
j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))]
|
||||||
|
if j.Type != extensions.RollingUpdateDeploymentStrategyType {
|
||||||
|
j.RollingUpdate = nil
|
||||||
|
} else {
|
||||||
|
rollingUpdate := extensions.RollingUpdateDeployment{}
|
||||||
|
if c.RandBool() {
|
||||||
|
rollingUpdate.MaxUnavailable = intstr.FromInt(int(c.Rand.Int31()))
|
||||||
|
rollingUpdate.MaxSurge = intstr.FromInt(int(c.Rand.Int31()))
|
||||||
|
} else {
|
||||||
|
rollingUpdate.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.Rand.Int31()))
|
||||||
|
}
|
||||||
|
j.RollingUpdate = &rollingUpdate
|
||||||
|
}
|
||||||
},
|
},
|
||||||
func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
|
func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(psp) // fuzz self without calling this function again
|
c.FuzzNoCustom(psp) // fuzz self without calling this function again
|
||||||
@ -546,6 +513,52 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func batchFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(j *batch.JobSpec, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
|
completions := int32(c.Rand.Int31())
|
||||||
|
parallelism := int32(c.Rand.Int31())
|
||||||
|
j.Completions = &completions
|
||||||
|
j.Parallelism = ¶llelism
|
||||||
|
if c.Rand.Int31()%2 == 0 {
|
||||||
|
j.ManualSelector = newBool(true)
|
||||||
|
} else {
|
||||||
|
j.ManualSelector = nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(sj *batch.CronJobSpec, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(sj)
|
||||||
|
suspend := c.RandBool()
|
||||||
|
sj.Suspend = &suspend
|
||||||
|
sds := int64(c.RandUint64())
|
||||||
|
sj.StartingDeadlineSeconds = &sds
|
||||||
|
sj.Schedule = c.RandString()
|
||||||
|
},
|
||||||
|
func(cp *batch.ConcurrencyPolicy, c fuzz.Continue) {
|
||||||
|
policies := []batch.ConcurrencyPolicy{batch.AllowConcurrent, batch.ForbidConcurrent, batch.ReplaceConcurrent}
|
||||||
|
*cp = policies[c.Rand.Intn(len(policies))]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoscalingFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(s *autoscaling.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||||
|
minReplicas := int32(c.Rand.Int31())
|
||||||
|
s.MinReplicas = &minReplicas
|
||||||
|
targetCpu := int32(c.RandUint64())
|
||||||
|
s.TargetCPUUtilizationPercentage = &targetCpu
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rbacFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
func(r *rbac.RoleRef, c fuzz.Continue) {
|
func(r *rbac.RoleRef, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(r) // fuzz self without calling this function again
|
c.FuzzNoCustom(r) // fuzz self without calling this function again
|
||||||
|
|
||||||
@ -554,37 +567,11 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
r.APIGroup = rbac.GroupName
|
r.APIGroup = rbac.GroupName
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(r *runtime.RawExtension, c fuzz.Continue) {
|
|
||||||
// Pick an arbitrary type and fuzz it
|
|
||||||
types := []runtime.Object{&api.Pod{}, &extensions.Deployment{}, &api.Service{}}
|
|
||||||
obj := types[c.Rand.Intn(len(types))]
|
|
||||||
c.Fuzz(obj)
|
|
||||||
|
|
||||||
// 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 runtime.Codec
|
|
||||||
switch obj.(type) {
|
|
||||||
case *api.Pod:
|
|
||||||
codec = testapi.Default.Codec()
|
|
||||||
case *extensions.Deployment:
|
|
||||||
codec = testapi.Extensions.Codec()
|
|
||||||
case *api.Service:
|
|
||||||
codec = testapi.Default.Codec()
|
|
||||||
default:
|
|
||||||
t.Errorf("Failed to find codec for object type: %T", obj)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the object to raw bytes
|
func kubeAdmFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
bytes, err := runtime.Encode(codec, obj)
|
return []interface{}{
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to encode object: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the bytes field on the RawExtension
|
|
||||||
r.Raw = bytes
|
|
||||||
},
|
|
||||||
func(obj *kubeadm.MasterConfiguration, c fuzz.Continue) {
|
func(obj *kubeadm.MasterConfiguration, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(obj)
|
c.FuzzNoCustom(obj)
|
||||||
obj.KubernetesVersion = "v10"
|
obj.KubernetesVersion = "v10"
|
||||||
@ -594,16 +581,40 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
|
|||||||
obj.AuthorizationMode = "foo"
|
obj.AuthorizationMode = "foo"
|
||||||
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func policyFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
func(s *policy.PodDisruptionBudgetStatus, c fuzz.Continue) {
|
func(s *policy.PodDisruptionBudgetStatus, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||||
s.PodDisruptionsAllowed = int32(c.Rand.Intn(2))
|
s.PodDisruptionsAllowed = int32(c.Rand.Intn(2))
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func certificateFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
func(obj *certificates.CertificateSigningRequestSpec, c fuzz.Continue) {
|
func(obj *certificates.CertificateSigningRequestSpec, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(obj) // fuzz self without calling this function again
|
c.FuzzNoCustom(obj) // fuzz self without calling this function again
|
||||||
obj.Usages = []certificates.KeyUsage{certificates.UsageKeyEncipherment}
|
obj.Usages = []certificates.KeyUsage{certificates.UsageKeyEncipherment}
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzerFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return mergeFuncLists(t,
|
||||||
|
apitesting.GenericFuzzerFuncs(t),
|
||||||
|
overrideGenericFuncs(t),
|
||||||
|
coreFuncs(t),
|
||||||
|
extensionFuncs(t),
|
||||||
|
batchFuncs(t),
|
||||||
|
autoscalingFuncs(t),
|
||||||
|
rbacFuncs(t),
|
||||||
|
kubeAdmFuncs(t),
|
||||||
|
policyFuncs(t),
|
||||||
|
certificateFuncs(t),
|
||||||
)
|
)
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBool(val bool) *bool {
|
func newBool(val bool) *bool {
|
||||||
@ -611,3 +622,25 @@ func newBool(val bool) *bool {
|
|||||||
*p = val
|
*p = val
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeFuncLists will merge the given funcLists, overriding early funcs with later ones if there first
|
||||||
|
// argument has the same type.
|
||||||
|
func mergeFuncLists(t apitesting.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
|
||||||
|
}
|
||||||
|
funcMap[fT.In(0).String()] = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []interface{}{}
|
||||||
|
for _, f := range funcMap {
|
||||||
|
result = append(result, f)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -21,9 +21,10 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
@ -41,7 +42,7 @@ func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) {
|
|||||||
t.Fatalf("Couldn't create internal object %v: %v", kind, err)
|
t.Fatalf("Couldn't create internal object %v: %v", kind, err)
|
||||||
}
|
}
|
||||||
seed := rand.Int63()
|
seed := rand.Int63()
|
||||||
apitesting.FuzzerFor(t, group.InternalGroupVersion(), rand.NewSource(seed)).
|
apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(seed)).
|
||||||
// We are explicitly overwriting custom fuzzing functions, to ensure
|
// We are explicitly overwriting custom fuzzing functions, to ensure
|
||||||
// that InitContainers and their statuses are not generated. This is
|
// that InitContainers and their statuses are not generated. This is
|
||||||
// because in thise test we are simply doing json operations, in which
|
// because in thise test we are simply doing json operations, in which
|
||||||
@ -155,7 +156,7 @@ func BenchmarkToFromUnstructured(b *testing.B) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func BenchmarkToFromUnstructuredViaJSON(b *testing.B) {
|
func BenchmarkToFromUnstructuredViaJSON(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
size := len(items)
|
size := len(items)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
@ -24,11 +24,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ func TestValidateOk(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
seed := rand.Int63()
|
seed := rand.Int63()
|
||||||
apiObjectFuzzer := apitesting.FuzzerFor(nil, testapi.Default.InternalGroupVersion(), rand.NewSource(seed))
|
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(seed))
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
testObj := test.obj
|
testObj := test.obj
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
|
|
||||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
@ -48,7 +49,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
kapitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
|
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||||
@ -3338,7 +3339,7 @@ func readBodyOrDie(r io.Reader) []byte {
|
|||||||
|
|
||||||
// BenchmarkUpdateProtobuf measures the cost of processing an update on the server in proto
|
// BenchmarkUpdateProtobuf measures the cost of processing an update on the server in proto
|
||||||
func BenchmarkUpdateProtobuf(b *testing.B) {
|
func BenchmarkUpdateProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
simpleStorage := &SimpleRESTStorage{}
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
||||||
@ -3394,8 +3395,8 @@ func newTestRequestInfoResolver() *request.RequestInfoFactory {
|
|||||||
|
|
||||||
const benchmarkSeed = 100
|
const benchmarkSeed = 100
|
||||||
|
|
||||||
func benchmarkItems() []api.Pod {
|
func benchmarkItems(b *testing.B) []api.Pod {
|
||||||
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
|
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
|
||||||
items := make([]api.Pod, 3)
|
items := make([]api.Pod, 3)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
apiObjectFuzzer.Fuzz(&items[i])
|
apiObjectFuzzer.Fuzz(&items[i])
|
||||||
|
@ -631,7 +631,7 @@ func TestWatchHTTPTimeout(t *testing.T) {
|
|||||||
|
|
||||||
// BenchmarkWatchHTTP measures the cost of serving a watch.
|
// BenchmarkWatchHTTP measures the cost of serving a watch.
|
||||||
func BenchmarkWatchHTTP(b *testing.B) {
|
func BenchmarkWatchHTTP(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
simpleStorage := &SimpleRESTStorage{}
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
||||||
@ -678,7 +678,7 @@ func BenchmarkWatchHTTP(b *testing.B) {
|
|||||||
|
|
||||||
// BenchmarkWatchWebsocket measures the cost of serving a watch.
|
// BenchmarkWatchWebsocket measures the cost of serving a watch.
|
||||||
func BenchmarkWatchWebsocket(b *testing.B) {
|
func BenchmarkWatchWebsocket(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
simpleStorage := &SimpleRESTStorage{}
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
||||||
@ -718,7 +718,7 @@ func BenchmarkWatchWebsocket(b *testing.B) {
|
|||||||
|
|
||||||
// BenchmarkWatchProtobuf measures the cost of serving a watch.
|
// BenchmarkWatchProtobuf measures the cost of serving a watch.
|
||||||
func BenchmarkWatchProtobuf(b *testing.B) {
|
func BenchmarkWatchProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems()
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
simpleStorage := &SimpleRESTStorage{}
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
||||||
|
133
staging/src/k8s.io/apimachinery/pkg/api/testing/fuzzer.go
Normal file
133
staging/src/k8s.io/apimachinery/pkg/api/testing/fuzzer.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/gofuzz"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenericFuzzerFuncs(t TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(j *int, c fuzz.Continue) {
|
||||||
|
*j = int(c.Int31())
|
||||||
|
},
|
||||||
|
func(j **int, c fuzz.Continue) {
|
||||||
|
if c.RandBool() {
|
||||||
|
i := int(c.Int31())
|
||||||
|
*j = &i
|
||||||
|
} else {
|
||||||
|
*j = nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(j *runtime.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.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() {
|
||||||
|
*j = &runtime.Unknown{
|
||||||
|
// We do not set TypeMeta here because it is not carried through a round trip
|
||||||
|
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
|
||||||
|
ContentType: runtime.ContentTypeJSON,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
|
||||||
|
t := types[c.Rand.Intn(len(types))]
|
||||||
|
c.Fuzz(t)
|
||||||
|
*j = t
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(r *runtime.RawExtension, c fuzz.Continue) {
|
||||||
|
// Pick an arbitrary type and fuzz it
|
||||||
|
types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
|
||||||
|
obj := types[c.Rand.Intn(len(types))]
|
||||||
|
c.Fuzz(obj)
|
||||||
|
|
||||||
|
// 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 = Codec(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)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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{})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
f.Funcs(funcs...)
|
||||||
|
return f
|
||||||
|
}
|
57
staging/src/k8s.io/apimachinery/pkg/api/testing/register.go
Normal file
57
staging/src/k8s.io/apimachinery/pkg/api/testing/register.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"mime"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
var scheme = runtime.NewScheme()
|
||||||
|
var codecs = runtimeserializer.NewCodecFactory(scheme)
|
||||||
|
var serializer runtime.SerializerInfo
|
||||||
|
|
||||||
|
// Codec returns the codec for the API version to test against, as set by the
|
||||||
|
// KUBE_TEST_API_TYPE env var.
|
||||||
|
func Codec(gvs ...schema.GroupVersion) runtime.Codec {
|
||||||
|
if serializer.Serializer == nil {
|
||||||
|
return codecs.LegacyCodec(gvs...)
|
||||||
|
}
|
||||||
|
return codecs.CodecForVersions(serializer.Serializer, codecs.UniversalDeserializer(), schema.GroupVersions(gvs), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
metav1.AddToGroupVersion(scheme, metav1.SchemeGroupVersion)
|
||||||
|
|
||||||
|
if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 {
|
||||||
|
var ok bool
|
||||||
|
mediaType, _, err := mime.ParseMediaType(apiMediaType)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
serializer, ok = runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("no serializer for %s", apiMediaType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user