Shuffle the test cases in the steady state controller test.
In steady state, the controller's mutations should be equivalent to
a pure function of the input Service. So, we verify this by shuffling
the test cases to check that the controller's internal state does
not affect the correctness of the outcome.
@@ -2,11 +2,11 @@ package main
import (
"fmt"
+ "math/rand"
"net"
"testing"
"github.com/google/go-cmp/cmp"
- "github.com/kr/pretty"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -96,7 +96,7 @@ func TestControllerMutation(t *testing.T) {
// In steady state, every input below should be equivalent to a
// pure function that reliably produces the same end state
// regardless of past controller state.
- tests := []struct {
+ tests := []*struct {
desc string
in *v1.Service
want *v1.Service
@@ -149,6 +149,17 @@ func TestControllerMutation(t *testing.T) {
},
},
+ {
+ desc: "request invalid IP",
+ in: &v1.Service{
+ Spec: v1.ServiceSpec{
+ Type: "LoadBalancer",
+ LoadBalancerIP: "please sir may I have an IP address thank you",
+ },
+ },
+ wantErr: true,
+ },
+
{
desc: "request infeasible IP",
in: &v1.Service{
@@ -251,6 +262,7 @@ func TestControllerMutation(t *testing.T) {
},
}
+ for i := 0; i < 100; i++ {
for _, test := range tests {
t.Logf("Running case %q", test.desc)
k.reset()
@@ -272,8 +284,7 @@ func TestControllerMutation(t *testing.T) {
}
gotSvc.Status = *k.updateServiceStatus
}
- pretty.Print(test.in)
- pretty.Print(gotSvc)
+
// v5 of the k8s client does not correctly compare nil
// *metav1.Time objects, which svc.ObjectMeta contains. Add
// some dummy non-nil values to all of in, want, got to work
@@ -298,5 +309,23 @@ func TestControllerMutation(t *testing.T) {
t.Errorf("%q: wrong service mutation (-want +got)\n%s", test.desc, diff)
}
}
+
+ if test.want != nil && len(test.want.Status.LoadBalancer.Ingress) > 0 && test.want.Status.LoadBalancer.Ingress[0].IP != "" {
+ ip := net.ParseIP(test.want.Status.LoadBalancer.Ingress[0].IP)
+ if ip == nil {
+ panic("bad wanted IP in loadbalancer status")
+ }
+ if !ip.Equal(c.ips.GetIP("test")) {
+ t.Errorf("%q: controller internal state does not match IP that controller claimed to allocate: want %q, got %q", test.desc, ip, c.ips.GetIP("test"))
+ }
+ }
+ }
+
+ // Shuffle the input vector, and run again.
+ for x := range tests {
+ nx := rand.Intn(len(tests) - x)
+ tests[x], tests[nx] = tests[nx], tests[x]
+ }
+ t.Logf("Shuffled test cases")
}
}
