Ctrl K
ComunidadGuías…

internal/topology/helpers_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package topology

import (
	"os"
	"regexp"
	"strconv"
	"testing"

	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	"github.com/sophotechlabs/spinoza/internal/api"
)

func replicated(ready int64, wanted any) *unstructured.Unstructured {
	spec := map[string]any{}
	if wanted != nil {
		spec["replicas"] = wanted
	}
	return &unstructured.Unstructured{Object: map[string]any{
		"spec":   spec,
		"status": map[string]any{"readyReplicas": ready},
	}}
}

func scheduled(ready, wanted int64) *unstructured.Unstructured {
	return &unstructured.Unstructured{Object: map[string]any{
		"status": map[string]any{"numberReady": ready, "desiredNumberScheduled": wanted},
	}}
}

func phased(phase, ready string) *unstructured.Unstructured {
	return &unstructured.Unstructured{Object: map[string]any{
		"status": map[string]any{
			"phase":      phase,
			"conditions": []any{map[string]any{"type": "Ready", "status": ready}},
		},
	}}
}

func conditioned(entries ...any) *unstructured.Unstructured {
	return &unstructured.Unstructured{Object: map[string]any{
		"status": map[string]any{"conditions": entries},
	}}
}

func condition(kind, status string) map[string]any {
	return map[string]any{"type": kind, "status": status}
}

func TestTheNodeBudgetIsTheCanvasCap(t *testing.T) {
	source, err := os.ReadFile("../../frontend/src/lib/graphState.ts")
	if err != nil {
		t.Fatalf("read the graph state: %v", err)
	}
	found := regexp.MustCompile(`MAX_NODES = (\d+)`).FindSubmatch(source)
	if found == nil {
		t.Fatal("the graph state no longer declares MAX_NODES; the two limits cannot be compared")
	}
	refuses, err := strconv.Atoi(string(found[1]))
	if err != nil {
		t.Fatalf("MAX_NODES is not a number: %v", err)
	}
	if refuses != nodeBudget {
		t.Fatalf("the canvas refuses above %d but the builder aims under %d; they move together or not at all", refuses, nodeBudget)
	}
}

func TestOnlyThreeKindsEverFold(t *testing.T) {
	for _, kind := range []string{kindPod, kindReplicaSet, kindJob} {
		if !foldableKinds[kind] {
			t.Fatalf("%s no longer folds", kind)
		}
	}
	if len(foldableKinds) != 3 {
		t.Fatalf("%d kinds fold, want the three the rule names", len(foldableKinds))
	}
	for _, kind := range []string{kindDeployment, kindStatefulSet, kindDaemonSet, kindCronJob} {
		if foldableKinds[kind] {
			t.Fatalf("%s folds into its owner; only pods, replica sets and jobs do", kind)
		}
	}
}

func TestEveryListedResourceHasACategory(t *testing.T) {
	cases := []struct {
		name     string
		group    string
		resource string
		want     string
	}{
		{name: "pods", resource: "pods", want: categoryPod},
		{name: "services", resource: "services", want: categoryService},
		{name: "replication controllers", resource: "replicationcontrollers", want: categoryWorkload},
		{name: "deployments", group: "apps", resource: "deployments", want: categoryWorkload},
		{name: "replica sets", group: "apps", resource: "replicasets", want: categoryWorkload},
		{name: "stateful sets", group: "apps", resource: "statefulsets", want: categoryWorkload},
		{name: "daemon sets", group: "apps", resource: "daemonsets", want: categoryWorkload},
		{name: "jobs", group: "batch", resource: "jobs", want: categoryWorkload},
		{name: "cron jobs", group: "batch", resource: "cronjobs", want: categoryWorkload},
		{name: "ingresses", group: "networking.k8s.io", resource: "ingresses", want: categoryIngress},
		{name: "autoscalers", group: "autoscaling", resource: "horizontalpodautoscalers", want: categoryAutoscaler},
		{name: "config maps are never listed", resource: "configmaps", want: ""},
		{name: "secrets are never listed", resource: "secrets", want: ""},
		{name: "nodes are never listed", resource: "nodes", want: ""},
		{name: "an unknown custom resource", group: "argoproj.io", resource: "rollouts", want: ""},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			desc := api.ResourceDescriptor{Group: tc.group, Resource: tc.resource}
			if got := categoryFor(desc); got != tc.want {
				t.Fatalf("category = %q, want %q", got, tc.want)
			}
		})
	}
}

func TestAnAPIVersionSplitsIntoGroupAndVersion(t *testing.T) {
	cases := []struct {
		name        string
		apiVersion  string
		wantGroup   string
		wantVersion string
	}{
		{name: "a grouped kind", apiVersion: "apps/v1", wantGroup: "apps", wantVersion: "v1"},
		{name: "the core group", apiVersion: "v1", wantGroup: "", wantVersion: "v1"},
		{name: "a dotted group", apiVersion: "argoproj.io/v1alpha1", wantGroup: "argoproj.io", wantVersion: "v1alpha1"},
		{name: "nothing at all", apiVersion: "", wantGroup: "", wantVersion: ""},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := groupOf(tc.apiVersion); got != tc.wantGroup {
				t.Fatalf("group = %q, want %q", got, tc.wantGroup)
			}
			if got := versionOf(tc.apiVersion); got != tc.wantVersion {
				t.Fatalf("version = %q, want %q", got, tc.wantVersion)
			}
		})
	}
}

func TestAnAbsentReplicaCountMeansOne(t *testing.T) {
	cases := []struct {
		name    string
		wanted  any
		replica int64
	}{
		{name: "a count it states", wanted: int64(3), replica: 3},
		{name: "deliberately scaled to zero", wanted: int64(0), replica: 0},
		{name: "no count at all", wanted: nil, replica: 1},
		{name: "a count of the wrong type", wanted: "two", replica: 1},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := wantedReplicas(replicated(0, tc.wanted)); got != tc.replica {
				t.Fatalf("wanted = %d, want %d", got, tc.replica)
			}
		})
	}
}

func TestAReplicaSummaryReadsReadyOverWanted(t *testing.T) {
	if got := replicaSummary(2, 3); got != "2/3" {
		t.Fatalf("summary = %q, want 2/3", got)
	}
}

func TestReadinessPerKind(t *testing.T) {
	cases := []struct {
		name  string
		kind  string
		obj   *unstructured.Unstructured
		ready string
	}{
		{name: "a full deployment", kind: kindDeployment, obj: replicated(3, int64(3)), ready: readyTrue},
		{name: "a deployment short of replicas", kind: kindDeployment, obj: replicated(1, int64(3)), ready: readyFalse},
		{name: "a deployment scaled to zero", kind: kindDeployment, obj: replicated(0, int64(0)), ready: readyTrue},
		{name: "a deployment that states no count", kind: kindDeployment, obj: replicated(0, nil), ready: readyFalse},
		{name: "a stateful set short of replicas", kind: kindStatefulSet, obj: replicated(0, int64(1)), ready: readyFalse},
		{name: "a full daemon set", kind: kindDaemonSet, obj: scheduled(2, 2), ready: readyTrue},
		{name: "a daemon set missing a node", kind: kindDaemonSet, obj: scheduled(1, 2), ready: readyFalse},
		{name: "a running pod", kind: kindPod, obj: phased("Running", readyTrue), ready: readyTrue},
		{name: "a pod that is not ready", kind: kindPod, obj: phased("Running", readyFalse), ready: readyFalse},
		{name: "a pod that finished", kind: kindPod, obj: phased("Succeeded", readyFalse), ready: readyTrue},
		{name: "a pod that failed", kind: kindPod, obj: phased("Failed", readyTrue), ready: readyFalse},
		{name: "a pending pod", kind: kindPod, obj: phased("Pending", ""), ready: readyFalse},
		{name: "a job still running", kind: kindJob, obj: conditioned(), ready: readyTrue},
		{name: "a job that failed", kind: kindJob, obj: conditioned(condition("Failed", readyTrue)), ready: readyFalse},
		{name: "a cron job says nothing", kind: kindCronJob, obj: conditioned(), ready: readyUnknown},
		{name: "a custom resource that is ready", kind: "Rollout", obj: conditioned(condition("Ready", readyTrue)), ready: readyTrue},
		{name: "a custom resource that is not", kind: "Rollout", obj: conditioned(condition("Ready", readyFalse)), ready: readyFalse},
		{name: "a custom resource with no conditions", kind: "Rollout", obj: conditioned(), ready: readyUnknown},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := readyOf(tc.obj, tc.kind); got != tc.ready {
				t.Fatalf("ready = %q, want %q", got, tc.ready)
			}
		})
	}
}

func TestTheStatusLinePerKind(t *testing.T) {
	cases := []struct {
		name   string
		kind   string
		obj    *unstructured.Unstructured
		status string
	}{
		{name: "a deployment counts replicas", kind: kindDeployment, obj: replicated(1, int64(3)), status: "1/3"},
		{name: "a deployment with no count wants one", kind: kindDeployment, obj: replicated(0, nil), status: "0/1"},
		{name: "a daemon set counts nodes", kind: kindDaemonSet, obj: scheduled(1, 4), status: "1/4"},
		{name: "a pod states its phase", kind: kindPod, obj: phased("Running", readyTrue), status: "Running"},
		{name: "a custom resource summarizes its condition", kind: "Rollout", obj: conditioned(condition("Ready", readyTrue)), status: "Ready"},
		{name: "a custom resource with nothing to say", kind: "Rollout", obj: conditioned(), status: ""},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := statusOf(tc.obj, tc.kind); got != tc.status {
				t.Fatalf("status = %q, want %q", got, tc.status)
			}
		})
	}
}

func TestAConditionIsOnlyTrueWhenItSaysSo(t *testing.T) {
	cases := []struct {
		name string
		obj  *unstructured.Unstructured
		want bool
	}{
		{name: "the condition is true", obj: conditioned(condition("Failed", readyTrue)), want: true},
		{name: "the condition is false", obj: conditioned(condition("Failed", readyFalse)), want: false},
		{name: "another condition is true", obj: conditioned(condition("Complete", readyTrue)), want: false},
		{name: "no conditions at all", obj: conditioned(), want: false},
		{name: "a condition that is not a map", obj: conditioned("not-a-map"), want: false},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := conditionTrue(tc.obj, "Failed"); got != tc.want {
				t.Fatalf("failed = %v, want %v", got, tc.want)
			}
		})
	}
}

func TestAPlaceholderIsBrokenOnlyWhenItIsMissing(t *testing.T) {
	if got := readyForPlaceholder(statusMissing); got != readyFalse {
		t.Fatalf("ready = %q, want False for something an object names but nothing provides", got)
	}
	if got := readyForPlaceholder(""); got != readyUnknown {
		t.Fatalf("ready = %q, want Unknown for something that was simply never listed", got)
	}
}

func TestASelectorPicksOnlyWhatMatchesEveryPair(t *testing.T) {
	cases := []struct {
		name     string
		selector map[string]string
		labels   map[string]string
		want     bool
	}{
		{name: "one pair that matches", selector: map[string]string{"app": "web"}, labels: map[string]string{"app": "web"}, want: true},
		{name: "one pair that does not", selector: map[string]string{"app": "web"}, labels: map[string]string{"app": "api"}, want: false},
		{name: "every pair matches", selector: map[string]string{"app": "web", "tier": "front"}, labels: map[string]string{"app": "web", "tier": "front", "extra": "ok"}, want: true},
		{name: "one pair of several does not", selector: map[string]string{"app": "web", "tier": "front"}, labels: map[string]string{"app": "web"}, want: false},
		{name: "the pod carries no labels", selector: map[string]string{"app": "web"}, labels: nil, want: false},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := selects(tc.selector, tc.labels); got != tc.want {
				t.Fatalf("selects = %v, want %v", got, tc.want)
			}
		})
	}
}

func TestASelectorKeepsOnlyItsStringPairs(t *testing.T) {
	raw := map[string]any{"app": "web", "port": int64(80), "on": true}

	result := stringsOf(raw, true)

	expected := map[string]string{"app": "web"}
	if len(result) != len(expected) || result["app"] != expected["app"] {
		t.Fatalf("selector = %v, want %v: a non-string value cannot match a label", result, expected)
	}
	if stringsOf(nil, false) != nil {
		t.Fatal("a spec with no selector at all should read as no selector")
	}
}

func TestAnIngressNamesEveryBackendOnce(t *testing.T) {
	obj := &unstructured.Unstructured{Object: map[string]any{"spec": map[string]any{
		"defaultBackend": map[string]any{"service": map[string]any{"name": "fallback"}},
		"rules": []any{
			map[string]any{"http": map[string]any{"paths": []any{
				map[string]any{"backend": map[string]any{"service": map[string]any{"name": "web"}}},
				map[string]any{"backend": map[string]any{"service": map[string]any{"name": "web"}}},
				map[string]any{"backend": map[string]any{"resource": map[string]any{"name": "bucket"}}},
				map[string]any{"backend": map[string]any{}},
				"not-a-map",
			}}},
			map[string]any{"http": map[string]any{}},
			"not-a-map",
		},
	}}}

	result := backendServices(obj)

	expected := []string{"fallback", "web"}
	if len(result) != len(expected) {
		t.Fatalf("backends = %v, want %v", result, expected)
	}
	for i, want := range expected {
		if result[i] != want {
			t.Fatalf("backend %d = %q, want %q", i, result[i], want)
		}
	}
}

func TestAnIngressWithNoBackendsNamesNothing(t *testing.T) {
	obj := &unstructured.Unstructured{Object: map[string]any{"spec": map[string]any{}}}

	if got := backendServices(obj); len(got) != 0 {
		t.Fatalf("backends = %v, want none", got)
	}
}

func TestAPodTemplateNamesEveryConfigItMounts(t *testing.T) {
	spec := map[string]any{
		"volumes": []any{
			map[string]any{"configMap": map[string]any{"name": "settings"}},
			map[string]any{"secret": map[string]any{"secretName": "tls"}},
			map[string]any{"projected": map[string]any{"sources": []any{
				map[string]any{"configMap": map[string]any{"name": "bundle"}},
				map[string]any{"secret": map[string]any{"name": "signing"}},
			}}},
			map[string]any{"name": "identity", "projected": map[string]any{"sources": []any{
				map[string]any{"serviceAccountToken": map[string]any{"path": "token"}},
				map[string]any{"configMap": map[string]any{"name": "identity-policy"}},
			}}},
			map[string]any{"emptyDir": map[string]any{}},
			"not-a-map",
		},
		"imagePullSecrets": []any{map[string]any{"name": "registry"}, "not-a-map"},
		"initContainers": []any{map[string]any{
			"envFrom": []any{map[string]any{"configMapRef": map[string]any{"name": "shared"}}},
		}},
		"containers": []any{"not-a-map", map[string]any{
			"envFrom": []any{
				map[string]any{"secretRef": map[string]any{"name": "tls"}},
				map[string]any{},
				"not-a-map",
			},
			"env": []any{
				map[string]any{"valueFrom": map[string]any{"configMapKeyRef": map[string]any{"name": "settings"}}},
				map[string]any{"valueFrom": map[string]any{"secretKeyRef": map[string]any{"name": "token"}}},
				map[string]any{"value": "literal"},
				"not-a-map",
			},
		}},
		"ephemeralContainers": []any{map[string]any{
			"envFrom": []any{map[string]any{"configMapRef": map[string]any{"name": "debug"}}},
		}},
	}

	result := configRefs(spec)

	expected := []configRef{
		{kind: kindConfigMap, name: "bundle"},
		{kind: kindConfigMap, name: "debug"},
		{kind: kindConfigMap, name: "identity-policy"},
		{kind: kindConfigMap, name: "settings"},
		{kind: kindConfigMap, name: "shared"},
		{kind: kindSecret, name: "registry"},
		{kind: kindSecret, name: "signing"},
		{kind: kindSecret, name: "tls"},
		{kind: kindSecret, name: "token"},
	}
	if len(result) != len(expected) {
		t.Fatalf("refs = %v, want %v", result, expected)
	}
	for i, want := range expected {
		if result[i] != want {
			t.Fatalf("ref %d = %v, want %v", i, result[i], want)
		}
	}
}

func TestTheVolumeTheKubeletInjectsIsRecognised(t *testing.T) {
	cases := []struct {
		name   string
		volume map[string]any
		want   bool
	}{
		{
			name: "the injected token volume",
			volume: map[string]any{
				"name": "kube-api-access-x9k2p",
				"projected": map[string]any{"sources": []any{
					map[string]any{"serviceAccountToken": map[string]any{"path": "token"}},
					map[string]any{"configMap": map[string]any{"name": "kube-root-ca.crt"}},
				}},
			},
			want: true,
		},
		{
			name: "a projection the author wrote",
			volume: map[string]any{
				"name": "bundle",
				"projected": map[string]any{"sources": []any{
					map[string]any{"configMap": map[string]any{"name": "bundle"}},
				}},
			},
			want: false,
		},
		{name: "no sources at all", volume: map[string]any{"name": "kube-api-access-empty"}, want: false},
		{
			name: "a source that is not a map",
			volume: map[string]any{
				"name":      "kube-api-access-broken",
				"projected": map[string]any{"sources": []any{"not-a-map"}},
			},
			want: false,
		},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := injectedByKubelet(tc.volume); got != tc.want {
				t.Fatalf("injected = %v, want %v", got, tc.want)
			}
		})
	}
}

func TestReachingIntoAShapeThatIsNotThere(t *testing.T) {
	object := map[string]any{"spec": map[string]any{"list": []any{"one"}, "leaf": "text"}}

	cases := []struct {
		name string
		keys []string
		want bool
	}{
		{name: "a map that is there", keys: []string{"spec"}, want: true},
		{name: "a key that is missing", keys: []string{"status"}, want: false},
		{name: "a key that holds a string", keys: []string{"spec", "leaf"}, want: false},
		{name: "a path through a missing key", keys: []string{"status", "conditions"}, want: false},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if found := mapAt(object, tc.keys...) != nil; found != tc.want {
				t.Fatalf("found = %v, want %v", found, tc.want)
			}
		})
	}

	if got := sliceAt(object, "spec", "list"); len(got) != 1 {
		t.Fatalf("list = %v, want the one entry", got)
	}
	if got := sliceAt(object, "spec", "missing"); got != nil {
		t.Fatalf("list = %v, want nothing", got)
	}
	if got := sliceAt(object, "status", "conditions"); got != nil {
		t.Fatalf("list = %v, want nothing when the path does not exist", got)
	}
}

func TestAnOpenSetIgnoresWhatIsNotAnID(t *testing.T) {
	result := setOf([]string{"one", "", "two"})

	if len(result) != 2 {
		t.Fatalf("open = %v, want the two real ids", result)
	}
	if result[""] {
		t.Fatal("an empty entry became an id")
	}
}

func TestWhatIsVisibleDependsOnEveryOwnerAboveIt(t *testing.T) {
	parents := map[string]string{"pod": "replicas", "replicas": "deployment"}

	cases := []struct {
		name     string
		expanded map[string]bool
		want     bool
	}{
		{name: "nothing open", expanded: map[string]bool{}, want: false},
		{name: "only the deployment open", expanded: map[string]bool{"deployment": true}, want: false},
		{name: "only the replica set open", expanded: map[string]bool{"replicas": true}, want: false},
		{name: "both open", expanded: map[string]bool{"replicas": true, "deployment": true}, want: true},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := shown("pod", parents, tc.expanded); got != tc.want {
				t.Fatalf("shown = %v, want %v", got, tc.want)
			}
		})
	}
	if !shown("deployment", parents, map[string]bool{}) {
		t.Fatal("a node nobody owns is always drawn")
	}
}

func TestAHiddenNodeAnchorsToTheNearestOwnerThatIsDrawn(t *testing.T) {
	parents := map[string]string{"pod": "replicas", "replicas": "deployment"}

	cases := []struct {
		name    string
		visible map[string]bool
		want    string
	}{
		{name: "the deployment is drawn", visible: map[string]bool{"deployment": true}, want: "deployment"},
		{name: "the replica set is drawn", visible: map[string]bool{"replicas": true}, want: "replicas"},
		{name: "nothing above it is drawn", visible: map[string]bool{}, want: ""},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := anchorOf("pod", parents, tc.visible); got != tc.want {
				t.Fatalf("anchor = %q, want %q", got, tc.want)
			}
		})
	}
	if got := anchorOf("deployment", parents, map[string]bool{}); got != "" {
		t.Fatalf("anchor = %q, want nothing for a node nobody owns", got)
	}
}

func TestAFoldDeepEnoughToBeACycleStopsWalking(t *testing.T) {
	parents := map[string]string{"left": "right", "right": "left"}
	open := map[string]bool{"left": true, "right": true}

	if shown("left", parents, open) {
		t.Fatal("a cycle where every owner is open must still stop rather than walk forever")
	}
	if got := anchorOf("left", parents, map[string]bool{}); got != "" {
		t.Fatalf("anchor = %q, want nothing: a cycle has no owner that is drawn", got)
	}
}