Commit 6b6b6c74 authored by Dr. Stefan Schimanski's avatar Dr. Stefan Schimanski Committed by Dr. Stefan Schimanski

pkg/api/testing: split fuzzer between apimachinery and kube

parent a12c6617
......@@ -21,15 +21,16 @@ import (
"math/rand"
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
"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) {
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
items := make([]api.Pod, 4)
for i := range items {
apiObjectFuzzer.Fuzz(&items[i])
......
......@@ -22,11 +22,12 @@ import (
"reflect"
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
"github.com/google/gofuzz"
)
......@@ -34,7 +35,7 @@ import (
func TestDeepCopyApiObjects(t *testing.T) {
for i := 0; i < *fuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63()))
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(rand.Int63()))
for kind := range api.Scheme.KnownTypes(version) {
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) {
for i := 0; i < *fuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63()))
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(rand.Int63()))
doDeepCopyTest(t, version.WithKind("Pod"), f)
}
}
......
......@@ -23,6 +23,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
apitesting "k8s.io/apimachinery/pkg/api/testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
......@@ -31,7 +32,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/api"
"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/apis/extensions"
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
......@@ -75,7 +76,7 @@ func TestUniversalDeserializer(t *testing.T) {
func TestProtobufRoundTrip(t *testing.T) {
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.
obj.Spec.InitContainers = 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
// reflection (to clear APIVersion and Kind)
func BenchmarkEncodeCodecProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type")
b.ResetTimer()
......@@ -111,7 +112,7 @@ func BenchmarkEncodeCodecProtobuf(b *testing.B) {
// BenchmarkEncodeCodecFromInternalProtobuf measures the cost of performing a codec encode,
// including conversions and any type setting. This is a "full" encode.
func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encodable := make([]api.Pod, width)
for i := range items {
......@@ -131,7 +132,7 @@ func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
}
func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
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,
// including conversions and any type setting. This is a "full" decode.
func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
s := protobuf.NewSerializer(api.Scheme, api.Scheme, "application/arbitrary.content.type")
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
func BenchmarkDecodeIntoProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......
......@@ -33,6 +33,7 @@ import (
"github.com/ugorji/go/codec"
"k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
......@@ -43,7 +44,7 @@ import (
"k8s.io/apimachinery/pkg/watch"
"k8s.io/kubernetes/pkg/api"
"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/apis/extensions"
"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
// fuzzer registered with the apitesting package.
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)
if err != nil {
......@@ -440,7 +441,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(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
f := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t), rand.NewSource(benchmarkSeed))
secret := &api.Secret{}
f.Fuzz(secret)
secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00}
......@@ -521,8 +522,8 @@ func TestObjectWatchFraming(t *testing.T) {
const benchmarkSeed = 100
func benchmarkItems() []v1.Pod {
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
func benchmarkItems(b *testing.B) []v1.Pod {
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
items := make([]v1.Pod, 10)
for i := range items {
var pod api.Pod
......@@ -540,7 +541,7 @@ func benchmarkItems() []v1.Pod {
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
// reflection (to clear APIVersion and Kind)
func BenchmarkEncodeCodec(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
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,
// including conversions.
func BenchmarkEncodeCodecFromInternal(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encodable := make([]api.Pod, width)
for i := range items {
......@@ -573,7 +574,7 @@ func BenchmarkEncodeCodecFromInternal(b *testing.B) {
// BenchmarkEncodeJSONMarshal provides a baseline for regular JSON encode performance
func BenchmarkEncodeJSONMarshal(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
......@@ -586,7 +587,7 @@ func BenchmarkEncodeJSONMarshal(b *testing.B) {
func BenchmarkDecodeCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......@@ -608,7 +609,7 @@ func BenchmarkDecodeCodec(b *testing.B) {
func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......@@ -631,7 +632,7 @@ func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......@@ -655,7 +656,7 @@ func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
func BenchmarkDecodeIntoJSON(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......@@ -679,7 +680,7 @@ func BenchmarkDecodeIntoJSON(b *testing.B) {
// BenchmarkDecodeJSON provides a baseline for codecgen JSON decode performance
func BenchmarkDecodeIntoJSONCodecGen(b *testing.B) {
kcodec := testapi.Default.Codec()
items := benchmarkItems()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
......
......@@ -21,9 +21,10 @@ import (
"reflect"
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/kubernetes/pkg/api"
"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/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)
}
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
// that InitContainers and their statuses are not generated. This is
// 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) {
items := benchmarkItems()
items := benchmarkItems(b)
size := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
......
......@@ -24,11 +24,12 @@ import (
"strings"
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/runtime"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/kubernetes/pkg/api"
"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/apis/extensions/v1beta1"
......@@ -148,7 +149,7 @@ func TestValidateOk(t *testing.T) {
}
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 _, test := range tests {
testObj := test.obj
......
......@@ -36,6 +36,7 @@ import (
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
......@@ -48,7 +49,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/endpoints/request"
"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"
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
"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
func BenchmarkUpdateProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
simpleStorage := &SimpleRESTStorage{}
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
......@@ -3394,8 +3395,8 @@ func newTestRequestInfoResolver() *request.RequestInfoFactory {
const benchmarkSeed = 100
func benchmarkItems() []api.Pod {
apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed))
func benchmarkItems(b *testing.B) []api.Pod {
apiObjectFuzzer := apitesting.FuzzerFor(kapitesting.FuzzerFuncs(b), rand.NewSource(benchmarkSeed))
items := make([]api.Pod, 3)
for i := range items {
apiObjectFuzzer.Fuzz(&items[i])
......
......@@ -631,7 +631,7 @@ func TestWatchHTTPTimeout(t *testing.T) {
// BenchmarkWatchHTTP measures the cost of serving a watch.
func BenchmarkWatchHTTP(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
simpleStorage := &SimpleRESTStorage{}
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.
func BenchmarkWatchWebsocket(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
simpleStorage := &SimpleRESTStorage{}
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.
func BenchmarkWatchProtobuf(b *testing.B) {
items := benchmarkItems()
items := benchmarkItems(b)
simpleStorage := &SimpleRESTStorage{}
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
......
/*
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
}
/*
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))
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment