443 lines
7.1 KiB
Go
443 lines
7.1 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Authors of K9s
|
|
|
|
package render
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/derailed/k9s/internal/client"
|
|
"github.com/derailed/k9s/internal/model1"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
)
|
|
|
|
func TestTableGenericHydrate(t *testing.T) {
|
|
raw := load(t, "p1")
|
|
tt := metav1beta1.Table{
|
|
ColumnDefinitions: []metav1beta1.TableColumnDefinition{
|
|
{Name: "c1"},
|
|
{Name: "c2"},
|
|
},
|
|
Rows: []metav1beta1.TableRow{
|
|
{
|
|
Cells: []any{"fred", 10},
|
|
Object: runtime.RawExtension{Object: raw},
|
|
},
|
|
{
|
|
Cells: []any{"blee", 20},
|
|
Object: runtime.RawExtension{Object: raw},
|
|
},
|
|
},
|
|
}
|
|
rr := make([]model1.Row, 2)
|
|
var re Table
|
|
re.SetTable("blee", &tt)
|
|
|
|
require.NoError(t, model1.GenericHydrate("blee", &tt, rr, &re))
|
|
assert.Len(t, rr, 2)
|
|
assert.Len(t, rr[0].Fields, 2)
|
|
}
|
|
|
|
func TestTableHydrate(t *testing.T) {
|
|
oo := []runtime.Object{
|
|
&PodWithMetrics{Raw: load(t, "p1")},
|
|
}
|
|
rr := make([]model1.Row, 1)
|
|
|
|
re := NewPod()
|
|
require.NoError(t, model1.Hydrate("blee", oo, rr, re))
|
|
assert.Len(t, rr, 1)
|
|
assert.Len(t, rr[0].Fields, 25)
|
|
}
|
|
|
|
func TestToAge(t *testing.T) {
|
|
uu := map[string]struct {
|
|
t time.Time
|
|
e string
|
|
}{
|
|
"zero": {
|
|
t: time.Time{},
|
|
e: UnknownValue,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, uc.e, ToAge(metav1.Time{Time: uc.t}))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestToAgeHuman(t *testing.T) {
|
|
uu := map[string]struct {
|
|
t, e string
|
|
}{
|
|
"blank": {
|
|
t: "",
|
|
e: UnknownValue,
|
|
},
|
|
"good": {
|
|
t: time.Now().Add(-10 * time.Second).Format(time.RFC3339Nano),
|
|
e: "10s",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, u.e, toAgeHuman(u.t))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJoin(t *testing.T) {
|
|
uu := map[string]struct {
|
|
i []string
|
|
e string
|
|
}{
|
|
"zero": {[]string{}, ""},
|
|
"std": {[]string{"a", "b", "c"}, "a,b,c"},
|
|
"blank": {[]string{"", "", ""}, ""},
|
|
"sparse": {[]string{"a", "", "c"}, "a,c"},
|
|
"withBlank": {[]string{"", "a", "c"}, "a,c"},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, uc.e, join(uc.i, ","))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoolPtrToStr(t *testing.T) {
|
|
tv, fv := true, false
|
|
|
|
uu := []struct {
|
|
p *bool
|
|
e string
|
|
}{
|
|
{nil, "false"},
|
|
{&tv, "true"},
|
|
{&fv, "false"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, boolPtrToStr(u.p))
|
|
}
|
|
}
|
|
|
|
func TestNamespaced(t *testing.T) {
|
|
uu := []struct {
|
|
p, ns, n string
|
|
}{
|
|
{"fred/blee", "fred", "blee"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
ns, n := client.Namespaced(u.p)
|
|
assert.Equal(t, u.ns, ns)
|
|
assert.Equal(t, u.n, n)
|
|
}
|
|
}
|
|
|
|
func TestMissing(t *testing.T) {
|
|
uu := []struct {
|
|
i, e string
|
|
}{
|
|
{"fred", "fred"},
|
|
{"", MissingValue},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, missing(u.i))
|
|
}
|
|
}
|
|
|
|
func TestBoolToStr(t *testing.T) {
|
|
uu := []struct {
|
|
i bool
|
|
e string
|
|
}{
|
|
{true, "true"},
|
|
{false, "false"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, boolToStr(u.i))
|
|
}
|
|
}
|
|
|
|
func TestNa(t *testing.T) {
|
|
uu := []struct {
|
|
i, e string
|
|
}{
|
|
{"fred", "fred"},
|
|
{"", NAValue},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, na(u.i))
|
|
}
|
|
}
|
|
|
|
func TestTruncate(t *testing.T) {
|
|
uu := map[string]struct {
|
|
data string
|
|
size int
|
|
e string
|
|
}{
|
|
"same": {
|
|
data: "fred",
|
|
size: 4,
|
|
e: "fred",
|
|
},
|
|
"small": {
|
|
data: "fred",
|
|
size: 10,
|
|
e: "fred",
|
|
},
|
|
"larger": {
|
|
data: "fred",
|
|
size: 3,
|
|
e: "fr…",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, u.e, Truncate(u.data, u.size))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestToSelector(t *testing.T) {
|
|
uu := map[string]struct {
|
|
m map[string]string
|
|
e []string
|
|
}{
|
|
"cool": {
|
|
map[string]string{"app": "fred", "env": "test"},
|
|
[]string{"app=fred,env=test", "env=test,app=fred"},
|
|
},
|
|
"empty": {
|
|
map[string]string{},
|
|
[]string{""},
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
s := toSelector(uc.m)
|
|
var match bool
|
|
for _, e := range uc.e {
|
|
if e == s {
|
|
match = true
|
|
}
|
|
}
|
|
assert.True(t, match)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBlank(t *testing.T) {
|
|
uu := map[string]struct {
|
|
a []string
|
|
e bool
|
|
}{
|
|
"full": {
|
|
a: []string{"fred", "blee"},
|
|
},
|
|
"empty": {
|
|
e: true,
|
|
},
|
|
"blank": {
|
|
a: []string{"fred", ""},
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, uc.e, blank(uc.a))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMetaFQN(t *testing.T) {
|
|
uu := map[string]struct {
|
|
m metav1.ObjectMeta
|
|
e string
|
|
}{
|
|
"full": {metav1.ObjectMeta{Namespace: "fred", Name: "blee"}, "fred/blee"},
|
|
"nons": {metav1.ObjectMeta{Name: "blee"}, "-/blee"},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, uc.e, client.MetaFQN(&uc.m))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFQN(t *testing.T) {
|
|
uu := map[string]struct {
|
|
ns, n string
|
|
e string
|
|
}{
|
|
"full": {ns: "fred", n: "blee", e: "fred/blee"},
|
|
"nons": {n: "blee", e: "blee"},
|
|
}
|
|
|
|
for k := range uu {
|
|
uc := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, uc.e, client.FQN(uc.ns, uc.n))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapToStr(t *testing.T) {
|
|
uu := []struct {
|
|
i map[string]string
|
|
e string
|
|
}{
|
|
{map[string]string{"blee": "duh", "aa": "bb"}, "aa=bb,blee=duh"},
|
|
{map[string]string{}, ""},
|
|
}
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, mapToStr(u.i))
|
|
}
|
|
}
|
|
|
|
func BenchmarkMapToStr(b *testing.B) {
|
|
ll := map[string]string{
|
|
"blee": "duh",
|
|
"aa": "bb",
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for range b.N {
|
|
mapToStr(ll)
|
|
}
|
|
}
|
|
|
|
func TestRunesToNum(t *testing.T) {
|
|
uu := map[string]struct {
|
|
rr []rune
|
|
e int64
|
|
}{
|
|
"0": {
|
|
rr: []rune(""),
|
|
e: 0,
|
|
},
|
|
"100": {
|
|
rr: []rune("100"),
|
|
e: 100,
|
|
},
|
|
"64": {
|
|
rr: []rune("64"),
|
|
e: 64,
|
|
},
|
|
"52640": {
|
|
rr: []rune("52640"),
|
|
e: 52640,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, u.e, runesToNum(u.rr))
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkRunesToNum(b *testing.B) {
|
|
rr := []rune("5465")
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for range b.N {
|
|
runesToNum(rr)
|
|
}
|
|
}
|
|
|
|
func TestToMc(t *testing.T) {
|
|
uu := []struct {
|
|
v int64
|
|
e string
|
|
}{
|
|
{0, "0"},
|
|
{2, "2"},
|
|
{1_000, "1000"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, toMc(u.v))
|
|
}
|
|
}
|
|
|
|
func TestToMi(t *testing.T) {
|
|
uu := []struct {
|
|
v int64
|
|
e string
|
|
}{
|
|
{0, "0"},
|
|
{2 * client.MegaByte, "2"},
|
|
{1_000 * client.MegaByte, "1000"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, toMi(u.v))
|
|
}
|
|
}
|
|
|
|
func TestIntToStr(t *testing.T) {
|
|
uu := []struct {
|
|
v int
|
|
e string
|
|
}{
|
|
{0, "0"},
|
|
{10, "10"},
|
|
}
|
|
|
|
for _, u := range uu {
|
|
assert.Equal(t, u.e, IntToStr(u.v))
|
|
}
|
|
}
|
|
|
|
func BenchmarkIntToStr(b *testing.B) {
|
|
v := 10
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for range b.N {
|
|
IntToStr(v)
|
|
}
|
|
}
|
|
|
|
// Helpers...
|
|
|
|
func load(t *testing.T, n string) *unstructured.Unstructured {
|
|
raw, err := os.ReadFile(fmt.Sprintf("testdata/%s.json", n))
|
|
require.NoError(t, err)
|
|
var o unstructured.Unstructured
|
|
err = json.Unmarshal(raw, &o)
|
|
require.NoError(t, err)
|
|
return &o
|
|
}
|