Refactor API object fuzzer

API object fuzzer is used to randomly populate API object for testing. Similar
code of the fuzzer was duplicated in multiple files. This change refactors the
tests and moves the fuzzer to a separate file.
This commit is contained in:
Yu-Ju Hong
2015-01-28 16:57:33 -08:00
parent fcb1cd30ff
commit 4cb730dad5
4 changed files with 177 additions and 333 deletions

View File

@@ -18,128 +18,21 @@ package latest
import (
"encoding/json"
"strconv"
"math/rand"
"testing"
internal "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apitesting "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testing"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
docker "github.com/fsouza/go-dockerclient"
fuzz "github.com/google/gofuzz"
)
// apiObjectFuzzer can randomly populate api objects.
var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
func(j *internal.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 *internal.ObjectMeta, c fuzz.Continue) {
j.Name = c.RandString()
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
var sec, nsec int64
c.Fuzz(&sec)
c.Fuzz(&nsec)
j.CreationTimestamp = util.Unix(sec, nsec).Rfc3339Copy()
},
func(j *internal.ListMeta, c fuzz.Continue) {
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
},
func(j *internal.ObjectReference, c fuzz.Continue) {
// We have to customize the randomization of TypeMetas because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = c.RandString()
j.Kind = c.RandString()
j.Namespace = c.RandString()
j.Name = c.RandString()
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.FieldPath = c.RandString()
},
func(j *internal.PodPhase, c fuzz.Continue) {
statuses := []internal.PodPhase{internal.PodPending, internal.PodRunning, internal.PodFailed, internal.PodUnknown}
*j = statuses[c.Rand.Intn(len(statuses))]
},
func(j *internal.ReplicationControllerSpec, c fuzz.Continue) {
// TemplateRef must be nil for round trip
c.Fuzz(&j.Template)
if j.Template == nil {
// TODO: v1beta1/2 can't round trip a nil template correctly, fix by having v1beta1/2
// conversion compare converted object to nil via DeepEqual
j.Template = &internal.PodTemplateSpec{}
}
j.Template.ObjectMeta = internal.ObjectMeta{Labels: j.Template.ObjectMeta.Labels}
j.Template.Spec.NodeSelector = nil
c.Fuzz(&j.Selector)
j.Replicas = int(c.RandUint64())
},
func(j *internal.ReplicationControllerStatus, c fuzz.Continue) {
// only replicas round trips
j.Replicas = int(c.RandUint64())
},
func(j *internal.List, c fuzz.Continue) {
c.Fuzz(&j.ListMeta)
c.Fuzz(&j.Items)
if j.Items == nil {
j.Items = []runtime.Object{}
}
},
func(j *runtime.Object, c fuzz.Continue) {
if c.RandBool() {
*j = &runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "Something", APIVersion: "unknown"},
RawJSON: []byte(`{"apiVersion":"unknown","kind":"Something","someKey":"someValue"}`),
}
} else {
types := []runtime.Object{&internal.Pod{}, &internal.ReplicationController{}}
t := types[c.Rand.Intn(len(types))]
c.Fuzz(t)
*j = t
}
},
func(intstr *util.IntOrString, c fuzz.Continue) {
// util.IntOrString will panic if its kind is set wrong.
if c.RandBool() {
intstr.Kind = util.IntstrInt
intstr.IntVal = int(c.RandUint64())
intstr.StrVal = ""
} else {
intstr.Kind = util.IntstrString
intstr.IntVal = 0
intstr.StrVal = c.RandString()
}
},
func(pb map[docker.Port][]docker.PortBinding, c fuzz.Continue) {
// This is necessary because keys with nil values get omitted.
// TODO: Is this a bug?
pb[docker.Port(c.RandString())] = []docker.PortBinding{
{c.RandString(), c.RandString()},
{c.RandString(), c.RandString()},
}
},
func(pm map[string]docker.PortMapping, c fuzz.Continue) {
// This is necessary because keys with nil values get omitted.
// TODO: Is this a bug?
pm[c.RandString()] = docker.PortMapping{
c.RandString(): c.RandString(),
}
},
func(p *internal.PullPolicy, c fuzz.Continue) {
policies := []internal.PullPolicy{internal.PullAlways, internal.PullNever, internal.PullIfNotPresent}
*p = policies[c.Rand.Intn(len(policies))]
},
)
func TestInternalRoundTrip(t *testing.T) {
latest := "v1beta2"
seed := rand.Int63()
apiObjectFuzzer := apitesting.FuzzerFor(t, "", rand.NewSource(seed))
for k := range internal.Scheme.KnownTypes("") {
obj, err := internal.Scheme.New("", k)
if err != nil {