// Test public interface func doTestIndex(t *testing.T, indexer Indexer) { mkObj := func(id string, val string) testStoreObject { return testStoreObject{id: id, val: val} } // Test Index expected := map[string]util.StringSet{} expected["b"] = util.NewStringSet("a", "c") expected["f"] = util.NewStringSet("e") expected["h"] = util.NewStringSet("g") indexer.Add(mkObj("a", "b")) indexer.Add(mkObj("c", "b")) indexer.Add(mkObj("e", "f")) indexer.Add(mkObj("g", "h")) { for k, v := range expected { found := util.StringSet{} indexResults, err := indexer.Index("by_val", mkObj("", k)) if err != nil { t.Errorf("Unexpected error %v", err) } for _, item := range indexResults { found.Insert(item.(testStoreObject).id) } items := v.List() if !found.HasAll(items...) { t.Errorf("missing items, index %s, expected %v but found %v", k, items, found.List()) } } } }
func TestFilterQuotaPods(t *testing.T) { pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "pod-running"}, Status: api.PodStatus{Phase: api.PodRunning}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-pending"}, Status: api.PodStatus{Phase: api.PodPending}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-succeeded"}, Status: api.PodStatus{Phase: api.PodSucceeded}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-unknown"}, Status: api.PodStatus{Phase: api.PodUnknown}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-failed"}, Status: api.PodStatus{Phase: api.PodFailed}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-failed-with-restart-always"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, }, Status: api.PodStatus{Phase: api.PodFailed}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-failed-with-restart-on-failure"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyOnFailure, }, Status: api.PodStatus{Phase: api.PodFailed}, }, { ObjectMeta: api.ObjectMeta{Name: "pod-failed-with-restart-never"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyNever, }, Status: api.PodStatus{Phase: api.PodFailed}, }, } expectedResults := util.NewStringSet("pod-running", "pod-pending", "pod-unknown", "pod-failed-with-restart-always", "pod-failed-with-restart-on-failure") actualResults := util.StringSet{} result := FilterQuotaPods(pods) for i := range result { actualResults.Insert(result[i].Name) } if len(expectedResults) != len(actualResults) || !actualResults.HasAll(expectedResults.List()...) { t.Errorf("Expected results %v, Actual results %v", expectedResults, actualResults) } }
func TestOrphanBuildResolver(t *testing.T) { activeBuildConfig := mockBuildConfig("a", "active-build-config") inactiveBuildConfig := mockBuildConfig("a", "inactive-build-config") buildConfigs := []*buildapi.BuildConfig{activeBuildConfig} builds := []*buildapi.Build{} expectedNames := util.StringSet{} BuildPhaseOptions := []buildapi.BuildPhase{ buildapi.BuildPhaseCancelled, buildapi.BuildPhaseComplete, buildapi.BuildPhaseError, buildapi.BuildPhaseFailed, buildapi.BuildPhaseNew, buildapi.BuildPhasePending, buildapi.BuildPhaseRunning, } BuildPhaseFilter := []buildapi.BuildPhase{ buildapi.BuildPhaseCancelled, buildapi.BuildPhaseComplete, buildapi.BuildPhaseError, buildapi.BuildPhaseFailed, } BuildPhaseFilterSet := util.StringSet{} for _, BuildPhase := range BuildPhaseFilter { BuildPhaseFilterSet.Insert(string(BuildPhase)) } for _, BuildPhaseOption := range BuildPhaseOptions { builds = append(builds, withStatus(mockBuild("a", string(BuildPhaseOption)+"-active", activeBuildConfig), BuildPhaseOption)) builds = append(builds, withStatus(mockBuild("a", string(BuildPhaseOption)+"-inactive", inactiveBuildConfig), BuildPhaseOption)) builds = append(builds, withStatus(mockBuild("a", string(BuildPhaseOption)+"-orphan", nil), BuildPhaseOption)) if BuildPhaseFilterSet.Has(string(BuildPhaseOption)) { expectedNames.Insert(string(BuildPhaseOption) + "-inactive") expectedNames.Insert(string(BuildPhaseOption) + "-orphan") } } dataSet := NewDataSet(buildConfigs, builds) resolver := NewOrphanBuildResolver(dataSet, BuildPhaseFilter) results, err := resolver.Resolve() if err != nil { t.Errorf("Unexpected error %v", err) } foundNames := util.StringSet{} for _, result := range results { foundNames.Insert(result.Name) } if len(foundNames) != len(expectedNames) || !expectedNames.HasAll(foundNames.List()...) { t.Errorf("expected %v, actual %v", expectedNames, foundNames) } }
func validateList(t *testing.T, lister Lister, user user.Info, expectedSet util.StringSet) { namespaceList, err := lister.List(user) if err != nil { t.Errorf("Unexpected error %v", err) } results := util.StringSet{} for _, namespace := range namespaceList.Items { results.Insert(namespace.Name) } if results.Len() != expectedSet.Len() || !results.HasAll(expectedSet.List()...) { t.Errorf("User %v, Expected: %v, Actual: %v", user.GetName(), expectedSet, results) } }
func TestOrphanDeploymentResolver(t *testing.T) { activeDeploymentConfig := mockDeploymentConfig("a", "active-deployment-config") inactiveDeploymentConfig := mockDeploymentConfig("a", "inactive-deployment-config") deploymentConfigs := []*deployapi.DeploymentConfig{activeDeploymentConfig} deployments := []*kapi.ReplicationController{} expectedNames := util.StringSet{} deploymentStatusOptions := []deployapi.DeploymentStatus{ deployapi.DeploymentStatusComplete, deployapi.DeploymentStatusFailed, deployapi.DeploymentStatusNew, deployapi.DeploymentStatusPending, deployapi.DeploymentStatusRunning, } deploymentStatusFilter := []deployapi.DeploymentStatus{ deployapi.DeploymentStatusComplete, deployapi.DeploymentStatusFailed, } deploymentStatusFilterSet := util.StringSet{} for _, deploymentStatus := range deploymentStatusFilter { deploymentStatusFilterSet.Insert(string(deploymentStatus)) } for _, deploymentStatusOption := range deploymentStatusOptions { deployments = append(deployments, withStatus(mockDeployment("a", string(deploymentStatusOption)+"-active", activeDeploymentConfig), deploymentStatusOption)) deployments = append(deployments, withStatus(mockDeployment("a", string(deploymentStatusOption)+"-inactive", inactiveDeploymentConfig), deploymentStatusOption)) deployments = append(deployments, withStatus(mockDeployment("a", string(deploymentStatusOption)+"-orphan", nil), deploymentStatusOption)) if deploymentStatusFilterSet.Has(string(deploymentStatusOption)) { expectedNames.Insert(string(deploymentStatusOption) + "-inactive") expectedNames.Insert(string(deploymentStatusOption) + "-orphan") } } dataSet := NewDataSet(deploymentConfigs, deployments) resolver := NewOrphanDeploymentResolver(dataSet, deploymentStatusFilter) results, err := resolver.Resolve() if err != nil { t.Errorf("Unexpected error %v", err) } foundNames := util.StringSet{} for _, result := range results { foundNames.Insert(result.Name) } if len(foundNames) != len(expectedNames) || !expectedNames.HasAll(foundNames.List()...) { t.Errorf("expected %v, actual %v", expectedNames, foundNames) } }
// Test public interface func doTestStore(t *testing.T, store Store) { mkObj := func(id string, val string) testStoreObject { return testStoreObject{id: id, val: val} } store.Add(mkObj("foo", "bar")) if item, ok, _ := store.Get(mkObj("foo", "")); !ok { t.Errorf("didn't find inserted item") } else { if e, a := "bar", item.(testStoreObject).val; e != a { t.Errorf("expected %v, got %v", e, a) } } store.Update(mkObj("foo", "baz")) if item, ok, _ := store.Get(mkObj("foo", "")); !ok { t.Errorf("didn't find inserted item") } else { if e, a := "baz", item.(testStoreObject).val; e != a { t.Errorf("expected %v, got %v", e, a) } } store.Delete(mkObj("foo", "")) if _, ok, _ := store.Get(mkObj("foo", "")); ok { t.Errorf("found deleted item??") } // Test List. store.Add(mkObj("a", "b")) store.Add(mkObj("c", "d")) store.Add(mkObj("e", "e")) { found := util.StringSet{} for _, item := range store.List() { found.Insert(item.(testStoreObject).val) } if !found.HasAll("b", "d", "e") { t.Errorf("missing items, found: %v", found) } if len(found) != 3 { t.Errorf("extra items") } } // Test Replace. store.Replace([]interface{}{ mkObj("foo", "foo"), mkObj("bar", "bar"), }) { found := util.StringSet{} for _, item := range store.List() { found.Insert(item.(testStoreObject).val) } if !found.HasAll("foo", "bar") { t.Errorf("missing items") } if len(found) != 2 { t.Errorf("extra items") } } }
func TestPerBuildConfigResolver(t *testing.T) { BuildPhaseOptions := []buildapi.BuildPhase{ buildapi.BuildPhaseCancelled, buildapi.BuildPhaseComplete, buildapi.BuildPhaseError, buildapi.BuildPhaseFailed, buildapi.BuildPhaseNew, buildapi.BuildPhasePending, buildapi.BuildPhaseRunning, } buildConfigs := []*buildapi.BuildConfig{ mockBuildConfig("a", "build-config-1"), mockBuildConfig("b", "build-config-2"), } buildsPerStatus := 100 builds := []*buildapi.Build{} for _, buildConfig := range buildConfigs { for _, BuildPhaseOption := range BuildPhaseOptions { for i := 0; i < buildsPerStatus; i++ { build := withStatus(mockBuild(buildConfig.Namespace, fmt.Sprintf("%v-%v-%v", buildConfig.Name, BuildPhaseOption, i), buildConfig), BuildPhaseOption) builds = append(builds, build) } } } now := util.Now() for i := range builds { creationTimestamp := util.NewTime(now.Time.Add(-1 * time.Duration(i) * time.Hour)) builds[i].CreationTimestamp = creationTimestamp } // test number to keep at varying ranges for keep := 0; keep < buildsPerStatus*2; keep++ { dataSet := NewDataSet(buildConfigs, builds) expectedNames := util.StringSet{} buildCompleteStatusFilterSet := util.NewStringSet(string(buildapi.BuildPhaseComplete)) buildFailedStatusFilterSet := util.NewStringSet(string(buildapi.BuildPhaseCancelled), string(buildapi.BuildPhaseError), string(buildapi.BuildPhaseFailed)) for _, buildConfig := range buildConfigs { buildItems, err := dataSet.ListBuildsByBuildConfig(buildConfig) if err != nil { t.Errorf("Unexpected err %v", err) } completedBuilds, failedBuilds := []*buildapi.Build{}, []*buildapi.Build{} for _, build := range buildItems { if buildCompleteStatusFilterSet.Has(string(build.Status.Phase)) { completedBuilds = append(completedBuilds, build) } else if buildFailedStatusFilterSet.Has(string(build.Status.Phase)) { failedBuilds = append(failedBuilds, build) } } sort.Sort(sortableBuilds(completedBuilds)) sort.Sort(sortableBuilds(failedBuilds)) purgeCompleted := []*buildapi.Build{} purgeFailed := []*buildapi.Build{} if keep >= 0 && keep < len(completedBuilds) { purgeCompleted = completedBuilds[keep:] } if keep >= 0 && keep < len(failedBuilds) { purgeFailed = failedBuilds[keep:] } for _, build := range purgeCompleted { expectedNames.Insert(build.Name) } for _, build := range purgeFailed { expectedNames.Insert(build.Name) } } resolver := NewPerBuildConfigResolver(dataSet, keep, keep) results, err := resolver.Resolve() if err != nil { t.Errorf("Unexpected error %v", err) } foundNames := util.StringSet{} for _, result := range results { foundNames.Insert(result.Name) } if len(foundNames) != len(expectedNames) || !expectedNames.HasAll(foundNames.List()...) { expectedValues := expectedNames.List() actualValues := foundNames.List() sort.Strings(expectedValues) sort.Strings(actualValues) t.Errorf("keep %v\n, expected \n\t%v\n, actual \n\t%v\n", keep, expectedValues, actualValues) } } }
func TestListFromMemory(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) prefixedKey := etcdtest.AddPrefix("pods") fakeClient.ExpectNotFoundGet(prefixedKey) cacher := newTestCacher(fakeClient) fakeClient.WaitForWatchCompletion() podFoo := makeTestPod("foo") podBar := makeTestPod("bar") podBaz := makeTestPod("baz") podFooPrime := makeTestPod("foo") podFooPrime.Spec.NodeName = "fakeNode" testCases := []*etcd.Response{ { Action: "create", Node: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podFoo)), CreatedIndex: 1, ModifiedIndex: 1, }, }, { Action: "create", Node: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podBar)), CreatedIndex: 2, ModifiedIndex: 2, }, }, { Action: "create", Node: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podBaz)), CreatedIndex: 3, ModifiedIndex: 3, }, }, { Action: "set", Node: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podFooPrime)), CreatedIndex: 1, ModifiedIndex: 4, }, PrevNode: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podFoo)), CreatedIndex: 1, ModifiedIndex: 1, }, }, { Action: "delete", Node: &etcd.Node{ CreatedIndex: 1, ModifiedIndex: 5, }, PrevNode: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Codec(), podBar)), CreatedIndex: 1, ModifiedIndex: 1, }, }, } // Propagate some data to etcd. for _, test := range testCases { fakeClient.WatchResponse <- test } if err := waitForUpToDateCache(cacher, 5); err != nil { t.Errorf("watch cache didn't propagated correctly: %v", err) } result := &api.PodList{} if err := cacher.ListFromMemory("pods/ns", result); err != nil { t.Errorf("unexpected error: %v", err) } if result.ListMeta.ResourceVersion != "5" { t.Errorf("incorrect resource version: %v", result.ListMeta.ResourceVersion) } if len(result.Items) != 2 { t.Errorf("unexpected list result: %d", len(result.Items)) } keys := util.StringSet{} for _, item := range result.Items { keys.Insert(item.ObjectMeta.Name) } if !keys.HasAll("foo", "baz") { t.Errorf("unexpected list result: %#v", result) } for _, item := range result.Items { // unset fields that are set by the infrastructure item.ObjectMeta.ResourceVersion = "" item.ObjectMeta.CreationTimestamp = util.Time{} var expected *api.Pod switch item.ObjectMeta.Name { case "foo": expected = podFooPrime case "baz": expected = podBaz default: t.Errorf("unexpected item: %v", item) } if e, a := *expected, item; !reflect.DeepEqual(e, a) { t.Errorf("expected: %#v, got: %#v", e, a) } } close(fakeClient.WatchResponse) }
func CheckSetEq(lhs, rhs util.StringSet) bool { return lhs.HasAll(rhs.List()...) && rhs.HasAll(lhs.List()...) }
func TestWatchCacheBasic(t *testing.T) { store := newWatchCache(2) // Test Add/Update/Delete. pod1 := makeTestPod("pod", 1) if err := store.Add(pod1); err != nil { t.Errorf("unexpected error: %v", err) } if item, ok, _ := store.Get(pod1); !ok { t.Errorf("didn't find pod") } else { if !api.Semantic.DeepEqual(pod1, item) { t.Errorf("expected %v, got %v", pod1, item) } } pod2 := makeTestPod("pod", 2) if err := store.Update(pod2); err != nil { t.Errorf("unexpected error: %v", err) } if item, ok, _ := store.Get(pod2); !ok { t.Errorf("didn't find pod") } else { if !api.Semantic.DeepEqual(pod2, item) { t.Errorf("expected %v, got %v", pod1, item) } } pod3 := makeTestPod("pod", 3) if err := store.Delete(pod3); err != nil { t.Errorf("unexpected error: %v", err) } if _, ok, _ := store.Get(pod3); ok { t.Errorf("found pod") } // Test List. store.Add(makeTestPod("pod1", 4)) store.Add(makeTestPod("pod2", 5)) store.Add(makeTestPod("pod3", 6)) { podNames := util.StringSet{} for _, item := range store.List() { podNames.Insert(item.(*api.Pod).ObjectMeta.Name) } if !podNames.HasAll("pod1", "pod2", "pod3") { t.Errorf("missing pods, found %v", podNames) } if len(podNames) != 3 { t.Errorf("found missing/extra items") } } // Test Replace. store.Replace([]interface{}{ makeTestPod("pod4", 7), makeTestPod("pod5", 8), }, "8") { podNames := util.StringSet{} for _, item := range store.List() { podNames.Insert(item.(*api.Pod).ObjectMeta.Name) } if !podNames.HasAll("pod4", "pod5") { t.Errorf("missing pods, found %v", podNames) } if len(podNames) != 2 { t.Errorf("found missing/extra items") } } }
func TestPerDeploymentConfigResolver(t *testing.T) { deploymentStatusOptions := []deployapi.DeploymentStatus{ deployapi.DeploymentStatusComplete, deployapi.DeploymentStatusFailed, deployapi.DeploymentStatusNew, deployapi.DeploymentStatusPending, deployapi.DeploymentStatusRunning, } deploymentConfigs := []*deployapi.DeploymentConfig{ mockDeploymentConfig("a", "deployment-config-1"), mockDeploymentConfig("b", "deployment-config-2"), } deploymentsPerStatus := 100 deployments := []*kapi.ReplicationController{} for _, deploymentConfig := range deploymentConfigs { for _, deploymentStatusOption := range deploymentStatusOptions { for i := 0; i < deploymentsPerStatus; i++ { deployment := withStatus(mockDeployment(deploymentConfig.Namespace, fmt.Sprintf("%v-%v-%v", deploymentConfig.Name, deploymentStatusOption, i), deploymentConfig), deploymentStatusOption) deployments = append(deployments, deployment) } } } now := util.Now() for i := range deployments { creationTimestamp := util.NewTime(now.Time.Add(-1 * time.Duration(i) * time.Hour)) deployments[i].CreationTimestamp = creationTimestamp } // test number to keep at varying ranges for keep := 0; keep < deploymentsPerStatus*2; keep++ { dataSet := NewDataSet(deploymentConfigs, deployments) expectedNames := util.StringSet{} deploymentCompleteStatusFilterSet := util.NewStringSet(string(deployapi.DeploymentStatusComplete)) deploymentFailedStatusFilterSet := util.NewStringSet(string(deployapi.DeploymentStatusFailed)) for _, deploymentConfig := range deploymentConfigs { deploymentItems, err := dataSet.ListDeploymentsByDeploymentConfig(deploymentConfig) if err != nil { t.Errorf("Unexpected err %v", err) } completedDeployments, failedDeployments := []*kapi.ReplicationController{}, []*kapi.ReplicationController{} for _, deployment := range deploymentItems { status := deployment.Annotations[deployapi.DeploymentStatusAnnotation] if deploymentCompleteStatusFilterSet.Has(status) { completedDeployments = append(completedDeployments, deployment) } else if deploymentFailedStatusFilterSet.Has(status) { failedDeployments = append(failedDeployments, deployment) } } sort.Sort(sortableReplicationControllers(completedDeployments)) sort.Sort(sortableReplicationControllers(failedDeployments)) purgeCompleted := []*kapi.ReplicationController{} purgeFailed := []*kapi.ReplicationController{} if keep >= 0 && keep < len(completedDeployments) { purgeCompleted = completedDeployments[keep:] } if keep >= 0 && keep < len(failedDeployments) { purgeFailed = failedDeployments[keep:] } for _, deployment := range purgeCompleted { expectedNames.Insert(deployment.Name) } for _, deployment := range purgeFailed { expectedNames.Insert(deployment.Name) } } resolver := NewPerDeploymentConfigResolver(dataSet, keep, keep) results, err := resolver.Resolve() if err != nil { t.Errorf("Unexpected error %v", err) } foundNames := util.StringSet{} for _, result := range results { foundNames.Insert(result.Name) } if len(foundNames) != len(expectedNames) || !expectedNames.HasAll(foundNames.List()...) { expectedValues := expectedNames.List() actualValues := foundNames.List() sort.Strings(expectedValues) sort.Strings(actualValues) t.Errorf("keep %v\n, expected \n\t%v\n, actual \n\t%v\n", keep, expectedValues, actualValues) } } }