authelia/internal/templates/funcs_test.go

661 lines
19 KiB
Go
Raw Permalink Normal View History

package templates
import (
"crypto/sha1" //nolint:gosec
"crypto/sha256"
"crypto/sha512"
"hash"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFuncGetEnv(t *testing.T) {
testCases := []struct {
name string
have map[string]string
expected map[string]string
}{
{"ShouldGetEnv",
map[string]string{
"AN_ENV": "a",
"ANOTHER_ENV": "b",
},
map[string]string{
"AN_ENV": "a",
"ANOTHER_ENV": "b",
},
},
{"ShouldNotGetSecretEnv",
map[string]string{
"AUTHELIA_ENV_SECRET": "a",
"ANOTHER_ENV": "b",
},
map[string]string{
"AUTHELIA_ENV_SECRET": "",
"ANOTHER_ENV": "b",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
for key, value := range tc.have {
t.Setenv(key, value)
}
for key, expected := range tc.expected {
assert.Equal(t, expected, FuncGetEnv(key))
}
})
}
}
func TestFuncExpandEnv(t *testing.T) {
testCases := []struct {
name string
env map[string]string
have string
expected string
}{
{"ShouldExpandEnv",
map[string]string{
"AN_ENV": "a",
"ANOTHER_ENV": "b",
},
"This is ${AN_ENV} and ${ANOTHER_ENV}",
"This is a and b",
},
{"ShouldNotExpandSecretEnv",
map[string]string{
"AUTHELIA_ENV_SECRET": "a",
"X_AUTHELIA_ENV_SECRET": "a",
"ANOTHER_ENV": "b",
},
"This is ${AUTHELIA_ENV_SECRET} and ${ANOTHER_ENV} without ${X_AUTHELIA_ENV_SECRET}",
"This is and b without ",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
for key, value := range tc.env {
t.Setenv(key, value)
}
assert.Equal(t, tc.expected, FuncExpandEnv(tc.have))
})
}
}
func TestFuncHashSum(t *testing.T) {
testCases := []struct {
name string
new func() hash.Hash
have []string
expected []string
}{
{"ShouldHashSHA1", sha1.New, []string{"abc", "123", "authelia"}, []string{"616263da39a3ee5e6b4b0d3255bfef95601890afd80709", "313233da39a3ee5e6b4b0d3255bfef95601890afd80709", "61757468656c6961da39a3ee5e6b4b0d3255bfef95601890afd80709"}},
{"ShouldHashSHA256", sha256.New, []string{"abc", "123", "authelia"}, []string{"616263e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "313233e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "61757468656c6961e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}},
{"ShouldHashSHA512", sha512.New, []string{"abc", "123", "authelia"}, []string{"616263cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "313233cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "61757468656c6961cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
require.Equal(t, len(tc.have), len(tc.expected))
h := FuncHashSum(tc.new)
for i := 0; i < len(tc.have); i++ {
assert.Equal(t, tc.expected[i], h(tc.have[i]))
}
})
}
}
func TestFuncStringReplace(t *testing.T) {
testCases := []struct {
name string
have string
old, new string
expected string
}{
{"ShouldReplaceSingle", "ABC123", "123", "456", "ABC456"},
{"ShouldReplaceMultiple", "123ABC123123", "123", "456", "456ABC456456"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringReplace(tc.old, tc.new, tc.have))
})
}
}
func TestFuncStringContains(t *testing.T) {
testCases := []struct {
name string
have string
substr string
expected bool
}{
{"ShouldMatchNormal", "abc123", "c12", true},
{"ShouldNotMatchWrongCase", "abc123", "C12", false},
{"ShouldNotMatchNotContains", "abc123", "xyz", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringContains(tc.substr, tc.have))
})
}
}
func TestFuncStringHasPrefix(t *testing.T) {
testCases := []struct {
name string
have string
substr string
expected bool
}{
{"ShouldMatchNormal", "abc123", "abc", true},
{"ShouldNotMatchWrongCase", "abc123", "ABC", false},
{"ShouldNotMatchNotPrefix", "abc123", "123", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringHasPrefix(tc.substr, tc.have))
})
}
}
func TestFuncStringHasSuffix(t *testing.T) {
testCases := []struct {
name string
have string
substr string
expected bool
}{
{"ShouldMatchNormal", "abc123xyz", "xyz", true},
{"ShouldNotMatchWrongCase", "abc123xyz", "XYZ", false},
{"ShouldNotMatchNotSuffix", "abc123xyz", "123", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringHasSuffix(tc.substr, tc.have))
})
}
}
func TestFuncStringTrimAll(t *testing.T) {
testCases := []struct {
name string
have string
cutset string
expected string
}{
{"ShouldTrimSuffix", "abc123xyz", "xyz", "abc123"},
{"ShouldTrimPrefix", "xyzabc123", "xyz", "abc123"},
{"ShouldNotTrimMiddle", "abcxyz123", "xyz", "abcxyz123"},
{"ShouldNotTrimWrongCase", "xyzabcxyz123xyz", "XYZ", "xyzabcxyz123xyz"},
{"ShouldNotTrimWrongChars", "abc123xyz", "456", "abc123xyz"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringTrimAll(tc.cutset, tc.have))
})
}
}
func TestFuncStringTrimPrefix(t *testing.T) {
testCases := []struct {
name string
have string
cutset string
expected string
}{
{"ShouldNotTrimSuffix", "abc123xyz", "xyz", "abc123xyz"},
{"ShouldTrimPrefix", "xyzabc123", "xyz", "abc123"},
{"ShouldNotTrimMiddle", "abcxyz123", "xyz", "abcxyz123"},
{"ShouldNotTrimWrongCase", "xyzabcxyz123xyz", "XYZ", "xyzabcxyz123xyz"},
{"ShouldNotTrimWrongChars", "abc123xyz", "456", "abc123xyz"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringTrimPrefix(tc.cutset, tc.have))
})
}
}
func TestFuncStringTrimSuffix(t *testing.T) {
testCases := []struct {
name string
have string
cutset string
expected string
}{
{"ShouldTrimSuffix", "abc123xyz", "xyz", "abc123"},
{"ShouldNotTrimPrefix", "xyzabc123", "xyz", "xyzabc123"},
{"ShouldNotTrimMiddle", "abcxyz123", "xyz", "abcxyz123"},
{"ShouldNotTrimWrongCase", "xyzabcxyz123xyz", "XYZ", "xyzabcxyz123xyz"},
{"ShouldNotTrimWrongChars", "abc123xyz", "456", "abc123xyz"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringTrimSuffix(tc.cutset, tc.have))
})
}
}
func TestFuncElemsJoin(t *testing.T) {
testCases := []struct {
name string
have any
sep string
expected string
}{
{"ShouldNotJoinNonElements", "abc123xyz", "xyz", "abc123xyz"},
{"ShouldJoinStrings", []string{"abc", "123"}, "xyz", "abcxyz123"},
{"ShouldJoinInts", []int{1, 2, 3}, ",", "1,2,3"},
{"ShouldJoinBooleans", []bool{true, false, true}, ".", "true.false.true"},
{"ShouldJoinBytes", [][]byte{[]byte("abc"), []byte("123"), []byte("a")}, "$", "abc$123$a"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncElemsJoin(tc.sep, tc.have))
})
}
}
func TestFuncIterate(t *testing.T) {
testCases := []struct {
name string
have uint
expected []uint
}{
{"ShouldGiveZeroResults", 0, nil},
{"ShouldGive10Results", 10, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncIterate(&tc.have))
})
}
}
func TestFuncStringsSplit(t *testing.T) {
testCases := []struct {
name string
have string
sep string
expected map[string]string
}{
{"ShouldSplit", "abc,123,456", ",", map[string]string{"_0": "abc", "_1": "123", "_2": "456"}},
{"ShouldNotSplit", "abc,123,456", "$", map[string]string{"_0": "abc,123,456"}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringSplit(tc.sep, tc.have))
})
}
}
func TestFuncStringSplitList(t *testing.T) {
testCases := []struct {
name string
have string
sep string
expected []string
}{
{"ShouldSplit", "abc,123,456", ",", []string{"abc", "123", "456"}},
{"ShouldNotSplit", "abc,123,456", "$", []string{"abc,123,456"}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringSplitList(tc.sep, tc.have))
})
}
}
func TestFuncKeys(t *testing.T) {
testCases := []struct {
name string
have []map[string]any
expected []string
}{
{"ShouldProvideKeysSingle", []map[string]any{{"a": "v", "b": "v", "z": "v"}}, []string{"a", "b", "z"}},
{"ShouldProvideKeysMultiple", []map[string]any{{"a": "v", "b": "v", "z": "v"}, {"h": "v"}}, []string{"a", "b", "z", "h"}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
keys := FuncKeys(tc.have...)
assert.Len(t, keys, len(tc.expected))
for _, expected := range tc.expected {
assert.Contains(t, keys, expected)
}
})
}
}
func TestFuncSortAlpha(t *testing.T) {
testCases := []struct {
name string
have any
expected []string
}{
{"ShouldSortStrings", []string{"a", "c", "b"}, []string{"a", "b", "c"}},
{"ShouldSortIntegers", []int{2, 3, 1}, []string{"1", "2", "3"}},
{"ShouldSortSingleValue", 1, []string{"1"}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncSortAlpha(tc.have))
})
}
}
func TestFuncBEnc(t *testing.T) {
testCases := []struct {
name string
have string
expected32 string
expected64 string
}{
{"ShouldEncodeEmptyString", "", "", ""},
{"ShouldEncodeString", "abc", "MFRGG===", "YWJj"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Run("Base32", func(t *testing.T) {
assert.Equal(t, tc.expected32, FuncB32Enc(tc.have))
})
t.Run("Base64", func(t *testing.T) {
assert.Equal(t, tc.expected64, FuncB64Enc(tc.have))
})
})
}
}
func TestFuncBDec(t *testing.T) {
testCases := []struct {
name string
have string
err32, expected32 string
err64, expected64 string
}{
{"ShouldDecodeEmptyString", "", "", "", "", ""},
{"ShouldDecodeBase32", "MFRGG===", "", "abc", "illegal base64 data at input byte 5", ""},
{"ShouldDecodeBase64", "YWJj", "illegal base32 data at input byte 3", "", "", "abc"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var (
actual string
err error
)
t.Run("Base32", func(t *testing.T) {
actual, err = FuncB32Dec(tc.have)
if tc.err32 != "" {
assert.Equal(t, "", actual)
assert.EqualError(t, err, tc.err32)
} else {
assert.Equal(t, tc.expected32, actual)
assert.NoError(t, err)
}
})
t.Run("Base64", func(t *testing.T) {
actual, err = FuncB64Dec(tc.have)
if tc.err64 != "" {
assert.Equal(t, "", actual)
assert.EqualError(t, err, tc.err64)
} else {
assert.Equal(t, tc.expected64, actual)
assert.NoError(t, err)
}
})
})
}
}
func TestFuncStringQuote(t *testing.T) {
testCases := []struct {
name string
have []any
expected string
}{
{"ShouldQuoteSingleValue", []any{"abc"}, `"abc"`},
{"ShouldQuoteMultiValue", []any{"abc", 123}, `"abc" "123"`},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringQuote(tc.have...))
})
}
}
func TestFuncStringSQuote(t *testing.T) {
testCases := []struct {
name string
have []any
expected string
}{
{"ShouldQuoteSingleValue", []any{"abc"}, `'abc'`},
{"ShouldQuoteMultiValue", []any{"abc", 123}, `'abc' '123'`},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncStringSQuote(tc.have...))
})
}
}
func TestFuncTypeOf(t *testing.T) {
astring := "typeOfExample"
anint := 5
astringslice := []string{astring}
anintslice := []int{anint}
testCases := []struct {
name string
have any
expected string
expectedKind string
}{
{"String", astring, "string", "string"},
{"StringPtr", &astring, "*string", "ptr"},
{"StringSlice", astringslice, "[]string", "slice"},
{"StringSlicePtr", &astringslice, "*[]string", "ptr"},
{"Integer", anint, "int", "int"},
{"IntegerPtr", &anint, "*int", "ptr"},
{"IntegerSlice", anintslice, "[]int", "slice"},
{"IntegerSlicePtr", &anintslice, "*[]int", "ptr"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncTypeOf(tc.have))
assert.Equal(t, tc.expectedKind, FuncKindOf(tc.have))
})
}
}
func TestFuncTypeIs(t *testing.T) {
astring := "typeIsExample"
anint := 10
astringslice := []string{astring}
anintslice := []int{anint}
testCases := []struct {
name string
is string
have any
expected bool
expectedLike bool
expectedKind bool
}{
{"ShouldMatchStringAsString", "string", astring, true, true, true},
{"ShouldMatchStringPtrAsString", "string", &astring, false, true, false},
{"ShouldNotMatchStringAsInt", "int", astring, false, false, false},
{"ShouldNotMatchStringSliceAsStringSlice", "[]string", astringslice, true, true, false},
{"ShouldNotMatchStringSlicePtrAsStringSlice", "[]string", &astringslice, false, true, false},
{"ShouldNotMatchStringSlicePtrAsStringSlicePtr", "*[]string", &astringslice, true, true, false},
{"ShouldNotMatchStringSliceAsString", "string", astringslice, false, false, false},
{"ShouldMatchIntAsInt", "int", anint, true, true, true},
{"ShouldMatchIntPtrAsInt", "int", &anint, false, true, false},
{"ShouldNotMatchIntAsString", "string", anint, false, false, false},
{"ShouldMatchIntegerSliceAsIntSlice", "[]int", anintslice, true, true, false},
{"ShouldMatchIntegerSlicePtrAsIntSlice", "[]int", &anintslice, false, true, false},
{"ShouldMatchIntegerSlicePtrAsIntSlicePtr", "*[]int", &anintslice, true, true, false},
{"ShouldNotMatchIntegerSliceAsInt", "int", anintslice, false, false, false},
{"ShouldMatchKindSlice", "slice", anintslice, false, false, true},
{"ShouldMatchKindPtr", "ptr", &anintslice, false, false, true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncTypeIs(tc.is, tc.have))
assert.Equal(t, tc.expectedLike, FuncTypeIsLike(tc.is, tc.have))
assert.Equal(t, tc.expectedKind, FuncKindIs(tc.is, tc.have))
})
}
}
func TestFuncList(t *testing.T) {
assert.Equal(t, []any{"a", "b", "c"}, FuncList("a", "b", "c"))
assert.Equal(t, []any{1, 2, 3}, FuncList(1, 2, 3))
}
func TestFuncDict(t *testing.T) {
assert.Equal(t, map[string]any{"a": 1}, FuncDict("a", 1))
assert.Equal(t, map[string]any{"a": 1, "b": ""}, FuncDict("a", 1, "b"))
assert.Equal(t, map[string]any{"1": 1, "b": 2}, FuncDict(1, 1, "b", 2))
assert.Equal(t, map[string]any{"true": 1, "b": 2}, FuncDict(true, 1, "b", 2))
assert.Equal(t, map[string]any{"a": 2, "b": 3}, FuncDict("a", 1, "a", 2, "b", 3))
}
func TestFuncGet(t *testing.T) {
assert.Equal(t, 123, FuncGet(map[string]any{"abc": 123}, "abc"))
assert.Equal(t, "", FuncGet(map[string]any{"abc": 123}, "123"))
}
func TestFuncSet(t *testing.T) {
assert.Equal(t, map[string]any{"abc": 123, "123": true}, FuncSet(map[string]any{"abc": 123}, "123", true))
assert.Equal(t, map[string]any{"abc": true}, FuncSet(map[string]any{"abc": 123}, "abc", true))
}
func TestFuncDefault(t *testing.T) {
testCases := []struct {
name string
value []any
have any
expected any
}{
{"ShouldDefaultEmptyString", []any{""}, "default", "default"},
{"ShouldNotDefaultString", []any{"not default"}, "default", "not default"},
{"ShouldDefaultEmptyInteger", []any{0}, 1, 1},
{"ShouldNotDefaultInteger", []any{20}, 1, 20},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncDefault(tc.have, tc.value...))
})
}
}
func TestFuncEmpty(t *testing.T) {
var nilv *string
testCases := []struct {
name string
value any
expected bool
}{
{"ShouldBeEmptyNil", nilv, true},
{"ShouldBeEmptyNilNil", nil, true},
{"ShouldBeEmptyString", "", true},
{"ShouldNotBeEmptyString", "abc", false},
{"ShouldBeEmptyArray", []string{}, true},
{"ShouldNotBeEmptyArray", []string{"abc"}, false},
{"ShouldBeEmptyInteger", 0, true},
{"ShouldNotBeEmptyInteger", 1, false},
{"ShouldBeEmptyInteger8", int8(0), true},
{"ShouldNotBeEmptyInteger8", int8(1), false},
{"ShouldBeEmptyInteger16", int16(0), true},
{"ShouldNotBeEmptyInteger16", int16(1), false},
{"ShouldBeEmptyInteger32", int32(0), true},
{"ShouldNotBeEmptyInteger32", int32(1), false},
{"ShouldBeEmptyInteger64", int64(0), true},
{"ShouldNotBeEmptyInteger64", int64(1), false},
{"ShouldBeEmptyUnsignedInteger", uint(0), true},
{"ShouldNotBeEmptyUnsignedInteger", uint(1), false},
{"ShouldBeEmptyUnsignedInteger8", uint8(0), true},
{"ShouldNotBeEmptyUnsignedInteger8", uint8(1), false},
{"ShouldBeEmptyUnsignedInteger16", uint16(0), true},
{"ShouldNotBeEmptyUnsignedInteger16", uint16(1), false},
{"ShouldBeEmptyUnsignedInteger32", uint32(0), true},
{"ShouldNotBeEmptyUnsignedInteger32", uint32(1), false},
{"ShouldBeEmptyUnsignedInteger64", uint64(0), true},
{"ShouldNotBeEmptyUnsignedInteger64", uint64(1), false},
{"ShouldBeEmptyComplex64", complex64(complex(0, 0)), true},
{"ShouldNotBeEmptyComplex64", complex64(complex(100000, 7.5)), false},
{"ShouldBeEmptyComplex128", complex128(complex(0, 0)), true},
{"ShouldNotBeEmptyComplex128", complex128(complex(100000, 7.5)), false},
{"ShouldBeEmptyFloat32", float32(0), true},
{"ShouldNotBeEmptyFloat32", float32(1), false},
{"ShouldBeEmptyFloat64", float64(0), true},
{"ShouldNotBeEmptyFloat64", float64(1), false},
{"ShouldBeEmptyBoolean", false, true},
{"ShouldNotBeEmptyBoolean", true, false},
{"ShouldNotBeEmptyStruct", struct{}{}, false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, FuncEmpty(tc.value))
})
}
}
func TestFuncIndent(t *testing.T) {
testCases := []struct {
name string
have string
indent int
expected []string
}{
{"ShouldIndentZeroMultiLine", "abc\n123", 0, []string{"abc\n123", "\nabc\n123"}},
{"ShouldIndentOneMultiLine", "abc\n123", 1, []string{" abc\n 123", "\n abc\n 123"}},
{"ShouldIndentOneSingleLine", "abc", 1, []string{" abc", "\n abc"}},
{"ShouldIndentZeroSingleLine", "abc", 0, []string{"abc", "\nabc"}},
}
for _, tc := range testCases {
for i, f := range []func(i int, v string) string{FuncIndent, FuncNewlineIndent} {
assert.Equal(t, tc.expected[i], f(tc.indent, tc.have))
}
}
}