func TestRESTUpdate(t *testing.T) { _, rest := NewTestREST() eventA := testEvent("foo") _, err := rest.Create(api.NewDefaultContext(), eventA) if err != nil { t.Fatalf("Unexpected error %v", err) } got, err := rest.Get(api.NewDefaultContext(), eventA.Name) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := eventA, got; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } eventB := testEvent("bar") _, _, err = rest.Update(api.NewDefaultContext(), eventB) if err != nil { t.Fatalf("Unexpected error %v", err) } got2, err := rest.Get(api.NewDefaultContext(), eventB.Name) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := eventB, got2; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } }
func TestGet(t *testing.T) { expect := validNewNamespace() expect.Status.Phase = api.NamespaceActive storage, fakeEtcdClient, _ := newStorage(t) ctx := api.NewContext() key, err := storage.Etcd.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) if err != nil { t.Fatalf("unexpected key error: %v", err) } fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, expect), }, }, } obj, err := storage.Get(api.NewContext(), "foo") namespace := obj.(*api.Namespace) if err != nil { t.Fatalf("unexpected error: %v", err) } expect.Status.Phase = api.NamespaceActive if e, a := expect, namespace; !api.Semantic.DeepEqual(e, a) { t.Errorf("Unexpected namespace: %s", util.ObjectDiff(e, a)) } }
func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) { printer := spew.ConfigState{DisableMethods: true} name := reflect.TypeOf(item).Elem().Name() data, err := codec.Encode(item) if err != nil { t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", item)) return } obj2, err := codec.Decode(data) if err != nil { t.Errorf("0: %v: %v\nCodec: %v\nData: %s\nSource: %#v", name, err, codec, string(data), printer.Sprintf("%#v", item)) return } if !api.Semantic.DeepEqual(item, obj2) { t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %#v\nFinal: %#v", name, util.ObjectGoPrintDiff(item, obj2), codec, string(data), printer.Sprintf("%#v", item), printer.Sprintf("%#v", obj2)) return } obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) err = codec.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } if !api.Semantic.DeepEqual(item, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(item, obj3), codec) return } }
func TestGet(t *testing.T) { expect := validNewPod() expect.Status.Phase = api.PodRunning expect.Spec.NodeName = "machine" fakeEtcdClient, helper := newHelper(t) key := etcdtest.AddPrefix("/pods/test/foo") fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, expect), }, }, } storage := NewStorage(helper, nil).Pod obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo") pod := obj.(*api.Pod) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := expect, pod; !api.Semantic.DeepEqual(e, a) { t.Errorf("Unexpected pod: %s", util.ObjectDiff(e, a)) } }
func TestRESTWatch(t *testing.T) { eventA := &api.Event{ InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "foo", UID: "long uid string", APIVersion: testapi.Version(), ResourceVersion: "0", FieldPath: "", }, Reason: "ForTesting", } reg, rest := NewTestREST() wi, err := rest.Watch(api.NewContext(), labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Unexpected error %v", err) } go func() { reg.Broadcaster.Action(watch.Added, eventA) }() got := <-wi.ResultChan() if e, a := eventA, got.Object; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } }
func TestEtcdDelete(t *testing.T) { podA := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.PodSpec{NodeName: "machine"}, } nodeWithPodA := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, }, E: nil, } emptyNode := tools.EtcdResponseWithError{ R: &etcd.Response{}, E: tools.EtcdErrorNotFound, } key := "foo" table := map[string]struct { existing tools.EtcdResponseWithError expect tools.EtcdResponseWithError errOK func(error) bool }{ "normal": { existing: nodeWithPodA, expect: emptyNode, errOK: func(err error) bool { return err == nil }, }, "notExisting": { existing: emptyNode, expect: emptyNode, errOK: func(err error) bool { return errors.IsNotFound(err) }, }, } for name, item := range table { fakeClient, registry := NewTestGenericEtcdRegistry(t) path := etcdtest.AddPrefix("pods/foo") fakeClient.Data[path] = item.existing obj, err := registry.Delete(api.NewContext(), key, nil) if !item.errOK(err) { t.Errorf("%v: unexpected error: %v (%#v)", name, err, obj) } if item.expect.E != nil { item.expect.E.(*etcd.EtcdError).Index = fakeClient.ChangeIndex } if e, a := item.expect, fakeClient.Data[path]; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v:\n%s", name, util.ObjectDiff(e, a)) } } }
func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) { buf := bytes.NewBuffer([]byte{}) err := printer.PrintObj(&testData, buf) if err != nil { t.Fatal(err) } var poutput testStruct // Verify that given function runs without error. err = unmarshalFunc(buf.Bytes(), &poutput) if err != nil { t.Fatal(err) } // Use real decode function to undo the versioning process. poutput = testStruct{} err = runtime.YAMLDecoder(testapi.Codec()).DecodeInto(buf.Bytes(), &poutput) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(testData, poutput) { t.Errorf("Test data and unmarshaled data are not equal: %v", util.ObjectDiff(poutput, testData)) } obj := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, } buf.Reset() printer.PrintObj(obj, buf) var objOut api.Pod // Verify that given function runs without error. err = unmarshalFunc(buf.Bytes(), &objOut) if err != nil { t.Fatalf("unexpected error: %#v", err) } // Use real decode function to undo the versioning process. objOut = api.Pod{} err = runtime.YAMLDecoder(testapi.Codec()).DecodeInto(buf.Bytes(), &objOut) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(obj, &objOut) { t.Errorf("Unexpected inequality:\n%v", util.ObjectDiff(obj, &objOut)) } }
func TestEtcdUpdateStatus(t *testing.T) { registry, status, fakeClient, helper := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := registry.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) resourcequotaStart := validNewResourceQuota() fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, resourcequotaStart), 1) resourcequotaIn := &api.ResourceQuota{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Status: api.ResourceQuotaStatus{ Used: api.ResourceList{ api.ResourceCPU: resource.MustParse("1"), api.ResourceMemory: resource.MustParse("1Gi"), api.ResourcePods: resource.MustParse("1"), api.ResourceServices: resource.MustParse("1"), api.ResourceReplicationControllers: resource.MustParse("1"), api.ResourceQuotas: resource.MustParse("1"), }, Hard: api.ResourceList{ api.ResourceCPU: resource.MustParse("100"), api.ResourceMemory: resource.MustParse("4Gi"), api.ResourcePods: resource.MustParse("10"), api.ResourceServices: resource.MustParse("10"), api.ResourceReplicationControllers: resource.MustParse("10"), api.ResourceQuotas: resource.MustParse("1"), }, }, } expected := *resourcequotaStart expected.ResourceVersion = "2" expected.Labels = resourcequotaIn.Labels expected.Status = resourcequotaIn.Status _, _, err := status.Update(ctx, resourcequotaIn) if err != nil { t.Fatalf("Unexpected error: %v", err) } var resourcequotaOut api.ResourceQuota key, _ = registry.KeyFunc(ctx, "foo") if err := helper.ExtractObj(key, &resourcequotaOut, false); err != nil { t.Fatalf("Unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, resourcequotaOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(expected, resourcequotaOut)) } }
func TestGet_NoError(t *testing.T) { r := NewTestREST(testResponse{code: 200, data: "ok"}) got, err := r.Get(api.NewContext(), "test1") if err != nil { t.Fatalf("Unexpected error: %v", err) } expect := createTestStatus("test1", api.ConditionTrue, "ok", "nil") if e, a := expect, got; !reflect.DeepEqual(e, a) { t.Errorf("Got unexpected object. Diff: %s", util.ObjectDiff(e, a)) } }
func TestRESTList(t *testing.T) { reg, rest := NewTestREST() eventA := &api.Event{ InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "foo", UID: "long uid string", APIVersion: testapi.Version(), ResourceVersion: "0", FieldPath: "", }, Reason: "ForTesting", Source: api.EventSource{Component: "GoodSource"}, } eventB := &api.Event{ InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "bar", UID: "other long uid string", APIVersion: testapi.Version(), ResourceVersion: "0", FieldPath: "", }, Reason: "ForTesting", Source: api.EventSource{Component: "GoodSource"}, } eventC := &api.Event{ InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "baz", UID: "yet another long uid string", APIVersion: testapi.Version(), ResourceVersion: "0", FieldPath: "", }, Reason: "ForTesting", Source: api.EventSource{Component: "OtherSource"}, } reg.ObjectList = &api.EventList{ Items: []api.Event{*eventA, *eventB, *eventC}, } got, err := rest.List(api.NewContext(), labels.Everything(), fields.Set{"source": "GoodSource"}.AsSelector()) if err != nil { t.Fatalf("Unexpected error %v", err) } expect := &api.EventList{ Items: []api.Event{*eventA, *eventB}, } if e, a := expect, got; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } }
func TestList_NoError(t *testing.T) { r := NewTestREST(testResponse{code: 200, data: "ok"}) got, err := r.List(api.NewContext(), labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("Unexpected error: %v", err) } expect := &api.ComponentStatusList{ Items: []api.ComponentStatus{*(createTestStatus("test1", api.ConditionTrue, "ok", "nil"))}, } if e, a := expect, got; !reflect.DeepEqual(e, a) { t.Errorf("Got unexpected object. Diff: %s", util.ObjectDiff(e, a)) } }
func TestRESTgetAttrs(t *testing.T) { _, rest := NewTestREST() eventA := &api.Event{ ObjectMeta: api.ObjectMeta{Name: "f0118"}, InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "long uid string", APIVersion: testapi.Version(), ResourceVersion: "0", FieldPath: "", }, Reason: "ForTesting", Source: api.EventSource{Component: "test"}, } label, field, err := rest.getAttrs(eventA) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := label, (labels.Set{}); !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } expect := fields.Set{ "metadata.name": "f0118", "involvedObject.kind": "Pod", "involvedObject.name": "foo", "involvedObject.namespace": "baz", "involvedObject.uid": "long uid string", "involvedObject.apiVersion": testapi.Version(), "involvedObject.resourceVersion": "0", "involvedObject.fieldPath": "", "reason": "ForTesting", "source": "test", } if e, a := expect, field; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } }
func TestList_UnknownError(t *testing.T) { r := NewTestREST(testResponse{code: 500, data: "", err: fmt.Errorf("fizzbuzz error")}) got, err := r.List(api.NewContext(), labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("Unexpected error: %v", err) } expect := &api.ComponentStatusList{ Items: []api.ComponentStatus{ *(createTestStatus("test1", api.ConditionUnknown, "", "Get http://testserver1:8000/healthz: fizzbuzz error"))}, } if e, a := expect, got; !reflect.DeepEqual(e, a) { t.Errorf("Got unexpected object. Diff: %s", util.ObjectDiff(e, a)) } }
func TestEtcdWatch(t *testing.T) { table := map[string]generic.Matcher{ "single": setMatcher{util.NewStringSet("foo")}, "multi": setMatcher{util.NewStringSet("foo", "bar")}, } for name, m := range table { podA := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Spec: api.PodSpec{NodeName: "machine"}, } respWithPodA := &etcd.Response{ Node: &etcd.Node{ Key: "/registry/pods/default/foo", Value: runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, Action: "create", } fakeClient, registry := NewTestGenericEtcdRegistry(t) wi, err := registry.WatchPredicate(api.NewContext(), m, "1") if err != nil { t.Errorf("%v: unexpected error: %v", name, err) continue } fakeClient.WaitForWatchCompletion() go func() { fakeClient.WatchResponse <- respWithPodA }() got, open := <-wi.ResultChan() if !open { t.Errorf("%v: unexpected channel close", name) continue } if e, a := podA, got.Object; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v: difference: %s", name, util.ObjectDiff(e, a)) } } }
func TestEtcdUpdateStatus(t *testing.T) { storage, statusStorage, fakeClient, helper := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) pvcStart := validNewPersistentVolumeClaim("foo", api.NamespaceDefault) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvcStart), 1) pvc := &api.PersistentVolumeClaim{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Spec: api.PersistentVolumeClaimSpec{ AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, Resources: api.ResourceRequirements{ Requests: api.ResourceList{ api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), }, }, }, Status: api.PersistentVolumeClaimStatus{ Phase: api.ClaimBound, }, } expected := *pvcStart expected.ResourceVersion = "2" expected.Labels = pvc.Labels expected.Status = pvc.Status _, _, err := statusStorage.Update(ctx, pvc) if err != nil { t.Fatalf("Unexpected error: %v", err) } var pvcOut api.PersistentVolumeClaim key, _ = storage.KeyFunc(ctx, "foo") if err := helper.ExtractObj(key, &pvcOut, false); err != nil { t.Fatalf("Unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, pvcOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(expected, pvcOut)) } }
func TestPersistentVolumesDecode(t *testing.T) { storage, _, _, _ := newStorage(t) expected := validNewPersistentVolume("foo") body, err := latest.Codec.Encode(expected) if err != nil { t.Fatalf("unexpected error: %v", err) } actual := storage.New() if err := latest.Codec.DecodeInto(body, actual); err != nil { t.Fatalf("unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, actual) { t.Errorf("mismatch: %s", util.ObjectDiff(expected, actual)) } }
func TestPodDecode(t *testing.T) { storage := NewStorage(tools.EtcdHelper{}, nil).Pod expected := validNewPod() body, err := latest.Codec.Encode(expected) if err != nil { t.Fatalf("unexpected error: %v", err) } actual := storage.New() if err := latest.Codec.DecodeInto(body, actual); err != nil { t.Fatalf("unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, actual) { t.Errorf("mismatch: %s", util.ObjectDiff(expected, actual)) } }
func TestRESTCreate(t *testing.T) { table := []struct { ctx api.Context event *api.Event valid bool }{ { ctx: api.NewDefaultContext(), event: testEvent("foo"), valid: true, }, { ctx: api.NewContext(), event: testEvent("bar"), valid: true, }, { ctx: api.WithNamespace(api.NewContext(), "nondefault"), event: testEvent("bazzzz"), valid: false, }, } for _, item := range table { _, storage := NewTestREST() c, err := storage.Create(item.ctx, item.event) if !item.valid { if err == nil { ctxNS := api.NamespaceValue(item.ctx) t.Errorf("unexpected non-error for %v (%v, %v)", item.event.Name, ctxNS, item.event.Namespace) } continue } if err != nil { t.Errorf("%v: Unexpected error %v", item.event.Name, err) continue } if !api.HasObjectMetaSystemFieldValues(&item.event.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } if e, a := item.event, c; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } // Ensure we implement the interface _ = rest.Watcher(storage) } }
func (test configCommandTest) run(t *testing.T) string { out, actualConfig := testConfigCommand(test.args, test.startingConfig) testSetNilMapsToEmpties(reflect.ValueOf(&test.expectedConfig)) testSetNilMapsToEmpties(reflect.ValueOf(&actualConfig)) testClearLocationOfOrigin(&actualConfig) if !api.Semantic.DeepEqual(test.expectedConfig, actualConfig) { t.Errorf("diff: %v", util.ObjectDiff(test.expectedConfig, actualConfig)) t.Errorf("expected: %#v\n actual: %#v", test.expectedConfig, actualConfig) } for _, expectedOutput := range test.expectedOutputs { if !strings.Contains(out, expectedOutput) { t.Errorf("expected '%s' in output, got '%s'", expectedOutput, out) } } return out }
func TestNamespaceDecode(t *testing.T) { _, helper := newHelper(t) storage, _, _ := NewStorage(helper) expected := validNewNamespace() expected.Status.Phase = api.NamespaceActive expected.Spec.Finalizers = []api.FinalizerName{api.FinalizerQingYuan} body, err := latest.Codec.Encode(expected) if err != nil { t.Fatalf("unexpected error: %v", err) } actual := storage.New() if err := latest.Codec.DecodeInto(body, actual); err != nil { t.Fatalf("unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, actual) { t.Errorf("mismatch: %s", util.ObjectDiff(expected, actual)) } }
func TestSetListToRuntimeObjectArray(t *testing.T) { pl := &api.List{} list := []runtime.Object{ &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}}, } err := runtime.SetList(pl, list) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := len(list), len(pl.Items); e != a { t.Fatalf("Expected %v, got %v", e, a) } for i := range list { if e, a := list[i], pl.Items[i]; e != a { t.Fatalf("%d: unmatched: %s", i, util.ObjectDiff(e, a)) } } }
func (test stepParserTest) run(t *testing.T) { actualSteps, err := newNavigationSteps(test.path) if len(test.expectedError) != 0 { if err == nil { t.Errorf("Did not get %v", test.expectedError) } else { if !strings.Contains(err.Error(), test.expectedError) { t.Errorf("Expected %v, but got %v", test.expectedError, err) } } return } if err != nil { t.Errorf("Unexpected error: %v", err) } if !reflect.DeepEqual(test.expectedNavigationSteps, *actualSteps) { t.Errorf("diff: %v", util.ObjectDiff(test.expectedNavigationSteps, *actualSteps)) } }
func TestEtcdUpdateStatus(t *testing.T) { storage, statusStorage, fakeClient, helper := newStorage(t) ctx := api.NewContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) pvStart := validNewPersistentVolume("foo") fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvStart), 1) pvIn := &api.PersistentVolume{ ObjectMeta: api.ObjectMeta{ Name: "foo", ResourceVersion: "1", }, Status: api.PersistentVolumeStatus{ Phase: api.VolumeBound, }, } expected := *pvStart expected.ResourceVersion = "2" expected.Labels = pvIn.Labels expected.Status = pvIn.Status _, _, err := statusStorage.Update(ctx, pvIn) if err != nil { t.Fatalf("Unexpected error: %v", err) } var pvOut api.PersistentVolume key, _ = storage.KeyFunc(ctx, "foo") if err := helper.ExtractObj(key, &pvOut, false); err != nil { t.Fatalf("Unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, pvOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(expected, pvOut)) } }
func TestGet(t *testing.T) { expect := validNewResourceQuota() fakeEtcdClient, helper := newHelper(t) storage, _ := NewStorage(helper) key := "/resourcequotas/test/foo" key = etcdtest.AddPrefix(key) fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, expect), }, }, } obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo") resourcequota := obj.(*api.ResourceQuota) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := expect, resourcequota; !api.Semantic.DeepEqual(e, a) { t.Errorf("Unexpected resourcequota: %s", util.ObjectDiff(e, a)) } }
func TestDoRequestFailed(t *testing.T) { status := &api.Status{ Code: http.StatusNotFound, Status: api.StatusFailure, Reason: api.StatusReasonNotFound, Message: " \"\" not found", Details: &api.StatusDetails{}, } expectedBody, _ := latest.Codec.Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 404, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() c, err := RESTClientFor(&Config{ Host: testServer.URL, Version: testapi.Version(), Codec: testapi.Codec(), }) if err != nil { t.Fatalf("unexpected error: %v", err) } body, err := c.Get().Do().Raw() if err == nil || body != nil { t.Errorf("unexpected non-error: %#v", body) } ss, ok := err.(APIStatus) if !ok { t.Errorf("unexpected error type %v", err) } actual := ss.Status() if !reflect.DeepEqual(status, &actual) { t.Errorf("Unexpected mis-match: %s", util.ObjectDiff(status, &actual)) } }
func TestEtcdUpdateNotScheduled(t *testing.T) { registry, _, _, fakeClient, _ := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := registry.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPod()), 1) podIn := validChangedPod() _, _, err := registry.Update(ctx, podIn) if err != nil { t.Errorf("Unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error: %v", err) } podOut := &api.Pod{} latest.Codec.DecodeInto([]byte(response.Node.Value), podOut) if !api.Semantic.DeepEqual(podOut, podIn) { t.Errorf("objects differ: %v", util.ObjectDiff(podOut, podIn)) } }
func TestArrayOfRuntimeObject(t *testing.T) { s := runtime.NewScheme() s.AddKnownTypes("", &EmbeddedTest{}) s.AddKnownTypeWithName("v1test", "EmbeddedTest", &EmbeddedTestExternal{}) s.AddKnownTypes("", &ObjectTest{}) s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{}) internal := &ObjectTest{ Items: []runtime.Object{ &EmbeddedTest{ID: "foo"}, &EmbeddedTest{ID: "bar"}, // TODO: until YAML is removed, this JSON must be in ascending key order to ensure consistent roundtrip serialization &runtime.Unknown{RawJSON: []byte(`{"apiVersion":"unknown","foo":"bar","kind":"OtherTest"}`)}, &ObjectTest{ Items: []runtime.Object{ &EmbeddedTest{ID: "baz"}, }, }, }, } wire, err := s.EncodeToVersion(internal, "v1test") if err != nil { t.Fatalf("unexpected error: %v", err) } t.Logf("Wire format is:\n%s\n", string(wire)) obj := &ObjectTestExternal{} if err := json.Unmarshal(wire, obj); err != nil { t.Fatalf("unexpected error: %v", err) } t.Logf("exact wire is: %s", string(obj.Items[0].RawJSON)) decoded, err := s.Decode(wire) if err != nil { t.Fatalf("unexpected error: %v", err) } list, err := runtime.ExtractList(decoded) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list, s); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } list2, err := runtime.ExtractList(list[3]) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list2, s); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } if err := runtime.SetList(list[3], list2); err != nil { t.Fatalf("unexpected error: %v", err) } internal.Items[2].(*runtime.Unknown).Kind = "OtherTest" internal.Items[2].(*runtime.Unknown).APIVersion = "unknown" if e, a := internal.Items, list; !reflect.DeepEqual(e, a) { t.Errorf("mismatched decoded: %s", util.ObjectDiff(e, a)) } }
func TestEventCreate(t *testing.T) { eventA := &api.Event{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Reason: "forTesting", } eventB := &api.Event{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Reason: "forTesting", } nodeWithEventA := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), eventA), ModifiedIndex: 1, CreatedIndex: 1, TTL: int64(testTTL), }, }, E: nil, } emptyNode := tools.EtcdResponseWithError{ R: &etcd.Response{}, E: tools.EtcdErrorNotFound, } ctx := api.NewDefaultContext() key := "foo" path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/events", key) path = etcdtest.AddPrefix(path) if err != nil { t.Errorf("Unexpected error: %v", err) } table := map[string]struct { existing tools.EtcdResponseWithError expect tools.EtcdResponseWithError toCreate runtime.Object errOK func(error) bool }{ "normal": { existing: emptyNode, expect: nodeWithEventA, toCreate: eventA, errOK: func(err error) bool { return err == nil }, }, "preExisting": { existing: nodeWithEventA, expect: nodeWithEventA, toCreate: eventB, errOK: errors.IsAlreadyExists, }, } for name, item := range table { fakeClient, registry := NewTestEventEtcdRegistry(t) fakeClient.Data[path] = item.existing err := registry.CreateWithName(ctx, key, item.toCreate) if !item.errOK(err) { t.Errorf("%v: unexpected error: %v", name, err) } if e, a := item.expect, fakeClient.Data[path]; !reflect.DeepEqual(e, a) { t.Errorf("%v:\n%s", name, util.ObjectDiff(e, a)) } } }
func TestScheduler(t *testing.T) { eventBroadcaster := record.NewBroadcaster() defer eventBroadcaster.StartLogging(t.Logf).Stop() errS := errors.New("scheduler") errB := errors.New("binder") table := []struct { injectBindError error sendPod *api.Pod algo algorithm.ScheduleAlgorithm expectErrorPod *api.Pod expectAssumedPod *api.Pod expectError error expectBind *api.Binding eventReason string }{ { sendPod: podWithID("foo", ""), algo: mockScheduler{"machine1", nil}, expectBind: &api.Binding{ObjectMeta: api.ObjectMeta{Name: "foo"}, Target: api.ObjectReference{Kind: "Node", Name: "machine1"}}, expectAssumedPod: podWithID("foo", "machine1"), eventReason: "scheduled", }, { sendPod: podWithID("foo", ""), algo: mockScheduler{"machine1", errS}, expectError: errS, expectErrorPod: podWithID("foo", ""), eventReason: "failedScheduling", }, { sendPod: podWithID("foo", ""), algo: mockScheduler{"machine1", nil}, expectBind: &api.Binding{ObjectMeta: api.ObjectMeta{Name: "foo"}, Target: api.ObjectReference{Kind: "Node", Name: "machine1"}}, injectBindError: errB, expectError: errB, expectErrorPod: podWithID("foo", ""), eventReason: "failedScheduling", }, } for i, item := range table { var gotError error var gotPod *api.Pod var gotAssumedPod *api.Pod var gotBinding *api.Binding c := &Config{ Modeler: &FakeModeler{ AssumePodFunc: func(pod *api.Pod) { gotAssumedPod = pod }, }, MinionLister: algorithm.FakeMinionLister( api.NodeList{Items: []api.Node{{ObjectMeta: api.ObjectMeta{Name: "machine1"}}}}, ), Algorithm: item.algo, Binder: fakeBinder{func(b *api.Binding) error { gotBinding = b return item.injectBindError }}, Error: func(p *api.Pod, err error) { gotPod = p gotError = err }, NextPod: func() *api.Pod { return item.sendPod }, Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "scheduler"}), } s := New(c) called := make(chan struct{}) events := eventBroadcaster.StartEventWatcher(func(e *api.Event) { if e, a := item.eventReason, e.Reason; e != a { t.Errorf("%v: expected %v, got %v", i, e, a) } close(called) }) s.scheduleOne() if e, a := item.expectAssumedPod, gotAssumedPod; !reflect.DeepEqual(e, a) { t.Errorf("%v: assumed pod: wanted %v, got %v", i, e, a) } if e, a := item.expectErrorPod, gotPod; !reflect.DeepEqual(e, a) { t.Errorf("%v: error pod: wanted %v, got %v", i, e, a) } if e, a := item.expectError, gotError; !reflect.DeepEqual(e, a) { t.Errorf("%v: error: wanted %v, got %v", i, e, a) } if e, a := item.expectBind, gotBinding; !reflect.DeepEqual(e, a) { t.Errorf("%v: error: %s", i, util.ObjectDiff(e, a)) } <-called events.Stop() } }
func TestSchedulerForgetAssumedPodAfterDelete(t *testing.T) { eventBroadcaster := record.NewBroadcaster() defer eventBroadcaster.StartLogging(t.Logf).Stop() // Setup modeler so we control the contents of all 3 stores: assumed, // scheduled and queued scheduledPodStore := cache.NewStore(cache.MetaNamespaceKeyFunc) scheduledPodLister := &cache.StoreToPodLister{scheduledPodStore} queuedPodStore := cache.NewFIFO(cache.MetaNamespaceKeyFunc) queuedPodLister := &cache.StoreToPodLister{queuedPodStore} modeler := NewSimpleModeler(queuedPodLister, scheduledPodLister) // Create a fake clock used to timestamp entries and calculate ttl. Nothing // will expire till we flip to something older than the ttl, at which point // all entries inserted with fakeTime will expire. ttl := 30 * time.Second fakeTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) fakeClock := &util.FakeClock{fakeTime} ttlPolicy := &cache.TTLPolicy{ttl, fakeClock} assumedPodsStore := cache.NewFakeExpirationStore( cache.MetaNamespaceKeyFunc, nil, ttlPolicy, fakeClock) modeler.assumedPods = &cache.StoreToPodLister{assumedPodsStore} // Port is the easiest way to cause a fit predicate failure podPort := 8080 firstPod := podWithPort("foo", "", podPort) // Create the scheduler config algo := NewGenericScheduler( map[string]algorithm.FitPredicate{"PodFitsPorts": predicates.PodFitsPorts}, []algorithm.PriorityConfig{}, modeler.PodLister(), rand.New(rand.NewSource(time.Now().UnixNano()))) var gotBinding *api.Binding c := &Config{ Modeler: modeler, MinionLister: algorithm.FakeMinionLister( api.NodeList{Items: []api.Node{{ObjectMeta: api.ObjectMeta{Name: "machine1"}}}}, ), Algorithm: algo, Binder: fakeBinder{func(b *api.Binding) error { scheduledPodStore.Add(podWithPort(b.Name, b.Target.Name, podPort)) gotBinding = b return nil }}, NextPod: func() *api.Pod { return queuedPodStore.Pop().(*api.Pod) }, Error: func(p *api.Pod, err error) { t.Errorf("Unexpected error when scheduling pod %+v: %v", p, err) }, Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "scheduler"}), } // First scheduling pass should schedule the pod s := New(c) called := make(chan struct{}) events := eventBroadcaster.StartEventWatcher(func(e *api.Event) { if e, a := "scheduled", e.Reason; e != a { t.Errorf("expected %v, got %v", e, a) } close(called) }) queuedPodStore.Add(firstPod) // queuedPodStore: [foo:8080] // scheduledPodStore: [] // assumedPods: [] s.scheduleOne() // queuedPodStore: [] // scheduledPodStore: [foo:8080] // assumedPods: [foo:8080] pod, exists, _ := scheduledPodStore.GetByKey("foo") if !exists { t.Errorf("Expected scheduled pod store to contain pod") } pod, exists, _ = queuedPodStore.GetByKey("foo") if exists { t.Errorf("Did not expect a queued pod, found %+v", pod) } pod, exists, _ = assumedPodsStore.GetByKey("foo") if !exists { t.Errorf("Assumed pod store should contain stale pod") } expectBind := &api.Binding{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Target: api.ObjectReference{Kind: "Node", Name: "machine1"}, } if ex, ac := expectBind, gotBinding; !reflect.DeepEqual(ex, ac) { t.Errorf("Expected exact match on binding: %s", util.ObjectDiff(ex, ac)) } <-called events.Stop() scheduledPodStore.Delete(pod) _, exists, _ = assumedPodsStore.Get(pod) if !exists { t.Errorf("Expected pod %#v in assumed pod store", pod) } secondPod := podWithPort("bar", "", podPort) queuedPodStore.Add(secondPod) // queuedPodStore: [bar:8080] // scheduledPodStore: [] // assumedPods: [foo:8080] // Second scheduling pass will fail to schedule if the store hasn't expired // the deleted pod. This would normally happen with a timeout. //expirationPolicy.NeverExpire = util.NewStringSet() fakeClock.Time = fakeClock.Time.Add(ttl + 1) called = make(chan struct{}) events = eventBroadcaster.StartEventWatcher(func(e *api.Event) { if e, a := "scheduled", e.Reason; e != a { t.Errorf("expected %v, got %v", e, a) } close(called) }) s.scheduleOne() expectBind = &api.Binding{ ObjectMeta: api.ObjectMeta{Name: "bar"}, Target: api.ObjectReference{Kind: "Node", Name: "machine1"}, } if ex, ac := expectBind, gotBinding; !reflect.DeepEqual(ex, ac) { t.Errorf("Expected exact match on binding: %s", util.ObjectDiff(ex, ac)) } <-called events.Stop() }