Unit tests

This commit is contained in:
Zvi Cahana
2023-11-24 00:58:16 +02:00
parent 3ccee0f62c
commit 566c259359
4 changed files with 278 additions and 6 deletions

View File

@@ -62,10 +62,16 @@ func Test_parseArgs_new(t *testing.T) {
want: UnsupportedOp{fmt.Errorf("'-d' needs arguments")}},
{name: "delete - current context",
args: []string{"-d", "."},
want: DeleteOp{[]string{"."}}},
want: DeleteOp{[]string{"."}, false}},
{name: "delete - multiple contexts",
args: []string{"-d", ".", "a", "b"},
want: DeleteOp{[]string{".", "a", "b"}}},
want: DeleteOp{[]string{".", "a", "b"}, false}},
{name: "delete cascading- current context",
args: []string{"-D", "."},
want: DeleteOp{[]string{"."}, true}},
{name: "delete cascading - multiple contexts",
args: []string{"-D", ".", "a", "b"},
want: DeleteOp{[]string{".", "a", "b"}, true}},
{name: "rename context",
args: []string{"a=b"},
want: RenameOp{"a", "b"}},

View File

@@ -0,0 +1,124 @@
package kubeconfig
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/ahmetb/kubectx/internal/testutil"
)
func TestKubeconfig_ClusterOfContext_ctxNotFound(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(testutil.Ctx("c1")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
_, err := kc.ClusterOfContext("c2")
if err == nil {
t.Fatal("expected err")
}
}
func TestKubeconfig_ClusterOfContext(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(
testutil.Ctx("c1").Cluster("c1c1"),
testutil.Ctx("c2").Cluster("c2c2")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
v1, err := kc.ClusterOfContext("c1")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := `c1c1`; v1 != expected {
t.Fatalf("c1: expected=\"%s\" got=\"%s\"", expected, v1)
}
v2, err := kc.ClusterOfContext("c2")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := `c2c2`; v2 != expected {
t.Fatalf("c2: expected=\"%s\" got=\"%s\"", expected, v2)
}
}
func TestKubeconfig_DeleteClusterEntry_errors(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`[1, 2, 3]`))
_ = kc.Parse()
err := kc.DeleteClusterEntry("foo")
if err == nil {
t.Fatal("supposed to fail on non-mapping nodes")
}
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`a: b`))
_ = kc.Parse()
err = kc.DeleteClusterEntry("foo")
if err == nil {
t.Fatal("supposed to fail if clusters key does not exist")
}
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`clusters: "some string"`))
_ = kc.Parse()
err = kc.DeleteClusterEntry("foo")
if err == nil {
t.Fatal("supposed to fail if clusters key is not an array")
}
}
func TestKubeconfig_DeleteClusterEntry(t *testing.T) {
test := WithMockKubeconfigLoader(
testutil.KC().WithClusters(
testutil.Cluster("c1"),
testutil.Cluster("c2"),
testutil.Cluster("c3")).ToYAML(t))
kc := new(Kubeconfig).WithLoader(test)
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
if err := kc.DeleteClusterEntry("c1"); err != nil {
t.Fatal(err)
}
if err := kc.Save(); err != nil {
t.Fatal(err)
}
expected := testutil.KC().WithClusters(
testutil.Cluster("c2"),
testutil.Cluster("c3")).ToYAML(t)
out := test.Output()
if diff := cmp.Diff(expected, out); diff != "" {
t.Fatalf("diff: %s", diff)
}
}
func TestKubeconfig_CountClusterReferences_errors(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(
testutil.Ctx("c1").Cluster("c1c1"),
testutil.Ctx("c2").Cluster("c2c2"),
testutil.Ctx("c3").Cluster("c1c1")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
count1, err := kc.CountClusterReferences("c1c1")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := 2; count1 != expected {
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count1)
}
count2, err := kc.CountClusterReferences("c2c2")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := 1; count2 != expected {
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count2)
}
}

View File

@@ -0,0 +1,124 @@
package kubeconfig
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/ahmetb/kubectx/internal/testutil"
)
func TestKubeconfig_UserOfContext_ctxNotFound(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(testutil.Ctx("c1")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
_, err := kc.UserOfContext("c2")
if err == nil {
t.Fatal("expected err")
}
}
func TestKubeconfig_UserOfContext(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(
testutil.Ctx("c1").User("c1u1"),
testutil.Ctx("c2").User("c2u2")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
v1, err := kc.UserOfContext("c1")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := `c1u1`; v1 != expected {
t.Fatalf("c1: expected=\"%s\" got=\"%s\"", expected, v1)
}
v2, err := kc.UserOfContext("c2")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := `c2u2`; v2 != expected {
t.Fatalf("c2: expected=\"%s\" got=\"%s\"", expected, v2)
}
}
func TestKubeconfig_DeleteUserEntry_errors(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`[1, 2, 3]`))
_ = kc.Parse()
err := kc.DeleteUserEntry("foo")
if err == nil {
t.Fatal("supposed to fail on non-mapping nodes")
}
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`a: b`))
_ = kc.Parse()
err = kc.DeleteUserEntry("foo")
if err == nil {
t.Fatal("supposed to fail if users key does not exist")
}
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`users: "some string"`))
_ = kc.Parse()
err = kc.DeleteUserEntry("foo")
if err == nil {
t.Fatal("supposed to fail if users key is not an array")
}
}
func TestKubeconfig_DeleteUserEntry(t *testing.T) {
test := WithMockKubeconfigLoader(
testutil.KC().WithUsers(
testutil.User("u1"),
testutil.User("u2"),
testutil.User("u3")).ToYAML(t))
kc := new(Kubeconfig).WithLoader(test)
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
if err := kc.DeleteUserEntry("u1"); err != nil {
t.Fatal(err)
}
if err := kc.Save(); err != nil {
t.Fatal(err)
}
expected := testutil.KC().WithUsers(
testutil.User("u2"),
testutil.User("u3")).ToYAML(t)
out := test.Output()
if diff := cmp.Diff(expected, out); diff != "" {
t.Fatalf("diff: %s", diff)
}
}
func TestKubeconfig_CountUserReferences_errors(t *testing.T) {
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
WithCtxs(
testutil.Ctx("c1").User("c1u1"),
testutil.Ctx("c2").User("c2u2"),
testutil.Ctx("c3").User("c1u1")).ToYAML(t)))
if err := kc.Parse(); err != nil {
t.Fatal(err)
}
count1, err := kc.CountUserReferences("c1u1")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := 2; count1 != expected {
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count1)
}
count2, err := kc.CountUserReferences("c2u2")
if err != nil {
t.Fatal("unexpected err", err)
}
if expected := 1; count2 != expected {
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count2)
}
}

View File

@@ -21,15 +21,31 @@ import (
"gopkg.in/yaml.v3"
)
type Context struct {
type ContextObj struct {
Name string `yaml:"name,omitempty"`
Context struct {
Namespace string `yaml:"namespace,omitempty"`
User string `yaml:"user,omitempty"`
Cluster string `yaml:"cluster,omitempty"`
} `yaml:"context,omitempty"`
}
func Ctx(name string) *Context { return &Context{Name: name} }
func (c *Context) Ns(ns string) *Context { c.Context.Namespace = ns; return c }
func Ctx(name string) *ContextObj { return &ContextObj{Name: name} }
func (c *ContextObj) Ns(ns string) *ContextObj { c.Context.Namespace = ns; return c }
func (c *ContextObj) User(user string) *ContextObj { c.Context.User = user; return c }
func (c *ContextObj) Cluster(cluster string) *ContextObj { c.Context.Cluster = cluster; return c }
type UserObj struct {
Name string `yaml:"name,omitempty"`
}
func User(name string) *UserObj { return &UserObj{Name: name} }
type ClusterObj struct {
Name string `yaml:"name,omitempty"`
}
func Cluster(name string) *ClusterObj { return &ClusterObj{Name: name} }
type Kubeconfig map[string]interface{}
@@ -41,7 +57,9 @@ func KC() *Kubeconfig {
func (k *Kubeconfig) Set(key string, v interface{}) *Kubeconfig { (*k)[key] = v; return k }
func (k *Kubeconfig) WithCurrentCtx(s string) *Kubeconfig { (*k)["current-context"] = s; return k }
func (k *Kubeconfig) WithCtxs(c ...*Context) *Kubeconfig { (*k)["contexts"] = c; return k }
func (k *Kubeconfig) WithCtxs(c ...*ContextObj) *Kubeconfig { (*k)["contexts"] = c; return k }
func (k *Kubeconfig) WithUsers(u ...*UserObj) *Kubeconfig { (*k)["users"] = u; return k }
func (k *Kubeconfig) WithClusters(c ...*ClusterObj) *Kubeconfig { (*k)["clusters"] = c; return k }
func (k *Kubeconfig) ToYAML(t *testing.T) string {
t.Helper()