Skip to content

Commit

Permalink
add a test; coverage up to 84.7%
Browse files Browse the repository at this point in the history
  • Loading branch information
lavalamp committed Apr 8, 2015
1 parent add5284 commit 13a030d
Showing 1 changed file with 101 additions and 1 deletion.
102 changes: 101 additions & 1 deletion pkg/controller/framework/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ package framework_test

import (
"fmt"
"math/rand"
"sync"
"testing"
"time"
// "testing"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller/framework"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"

"github.com/google/gofuzz"
)

func Example() {
Expand Down Expand Up @@ -170,3 +173,100 @@ func ExampleInformer() {
// b-controller
// c-framework
}

func TestHammerController(t *testing.T) {
// This test executes a bunch of requests through the fake source and
// controller framework to make sure there's no locking/threading
// errors.

// source simulates an apiserver object endpoint.
source := framework.NewFakeControllerSource()

// Let's do threadsafe output to get predictable test results.
outputSetLock := sync.Mutex{}
// map of key to operations done on the key
outputSet := map[string][]string{}

recordFunc := func(eventType string, obj interface{}) {
key, err := framework.DeletionHandlingMetaNamespaceKeyFunc(obj)
if err != nil {
t.Errorf("something wrong with key: %v", err)
key = "oops something went wrong with the key"
}

// Record some output when items are deleted.
outputSetLock.Lock()
defer outputSetLock.Unlock()
outputSet[key] = append(outputSet[key], eventType)
}

// Make a controller that immediately deletes anything added to it, and
// logs anything deleted.
_, controller := framework.NewInformer(
source,
&api.Pod{},
time.Millisecond*100,
framework.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) { recordFunc("add", obj) },
UpdateFunc: func(obj interface{}) { recordFunc("update", obj) },
DeleteFunc: func(obj interface{}) { recordFunc("delete", obj) },
},
)

// Run the controller and run it until we close stop.
stop := make(chan struct{})
go controller.Run(stop)

wg := sync.WaitGroup{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// Let's add a few objects to the source.
currentNames := util.StringSet{}
rs := rand.NewSource(rand.Int63())
f := fuzz.New().NilChance(.5).NumElements(0, 2).RandSource(rs)
r := rand.New(rs) // Mustn't use r and f concurrently!
for i := 0; i < 750; i++ {
var name string
var isNew bool
if currentNames.Len() == 0 || r.Intn(3) == 1 {
f.Fuzz(&name)
isNew = true
} else {
l := currentNames.List()
name = l[r.Intn(len(l))]
}

pod := &api.Pod{}
f.Fuzz(pod)
pod.ObjectMeta.Name = name
pod.ObjectMeta.Namespace = "default"
// Add, update, or delete randomly.
// Note that these pods are not valid-- the fake source doesn't
// call validation or anything.
if isNew {
currentNames.Insert(name)
source.Add(pod)
continue
}
switch r.Intn(2) {
case 0:
currentNames.Insert(name)
source.Modify(pod)
case 1:
currentNames.Delete(name)
source.Delete(pod)
}
}
}()
}
wg.Wait()

// Let's wait for the controller to finish processing the things we just added.
time.Sleep(100 * time.Millisecond)
close(stop)

outputSetLock.Lock()
t.Logf("got: %#v", outputSet)
}

0 comments on commit 13a030d

Please sign in to comment.