handler: tests for exec.Cmd and templating
This commit is contained in:
parent
315a334732
commit
26485ab1e8
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_runTemplate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
Template *template.Template
|
||||
Env TemplateEnv
|
||||
Expected string
|
||||
ShouldError bool
|
||||
HandlerFunc func(t *testing.T, expected, actual string) bool
|
||||
}{
|
||||
{
|
||||
Name: "Empty",
|
||||
Template: s2t(""),
|
||||
},
|
||||
{
|
||||
Name: "TextOnly",
|
||||
Template: s2t("hello, this is a text only template"),
|
||||
Expected: "hello, this is a text only template",
|
||||
},
|
||||
{
|
||||
Name: "WithEvent",
|
||||
Template: s2t("{{.Event.Instance}}:{{.Event.State}}:{{.Event.Type}}"),
|
||||
Expected: "foo_instance:MASTER:INSTANCE",
|
||||
Env: TemplateEnv{
|
||||
Event: MessageEvent{
|
||||
Instance: "foo_instance",
|
||||
Type: "INSTANCE",
|
||||
State: "MASTER",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "WithCxt",
|
||||
Template: s2t("{{.Cxt.key1}}:{{.Cxt.key2.subkey1}}:{{.Cxt.UpCase.Key}}"),
|
||||
Expected: "value1:value2:value3",
|
||||
Env: TemplateEnv{
|
||||
Cxt: map[string]any{
|
||||
"key1": "value1",
|
||||
"key2": map[string]string{
|
||||
"subkey1": "value2",
|
||||
},
|
||||
"UpCase": map[string]string{
|
||||
"Key": "value3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "WithCxtAndEvent",
|
||||
Template: s2t("{{.Event.Instance}}->{{.Cxt.key1}}:{{.Cxt.key2.subkey1}}:{{.Cxt.UpCase.Key}}"),
|
||||
Expected: "baz_instance->value1:value2:value3",
|
||||
Env: TemplateEnv{
|
||||
Cxt: map[string]any{
|
||||
"key1": "value1",
|
||||
"key2": map[string]string{
|
||||
"subkey1": "value2",
|
||||
},
|
||||
"UpCase": map[string]string{
|
||||
"Key": "value3",
|
||||
},
|
||||
},
|
||||
Event: MessageEvent{
|
||||
Instance: "baz_instance",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range cases {
|
||||
test := test // Avoid closure capture by ref
|
||||
tname := fmt.Sprintf("%s@%d:%d", test.Name, i+1, len(cases))
|
||||
|
||||
t.Run(tname, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if test.HandlerFunc == nil {
|
||||
test.HandlerFunc = Noop[string]
|
||||
if test.Expected != "" {
|
||||
test.HandlerFunc = ExpectEqual[string]
|
||||
if test.ShouldError {
|
||||
test.HandlerFunc = ExpectNotEqual[string]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual, err := runTemplate(test.Template, &test.Env)
|
||||
if test.ShouldError && err != nil {
|
||||
return
|
||||
} else if assert.NoError(t, err) {
|
||||
test.HandlerFunc(t, test.Expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_mkCmd(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
Cmdline string
|
||||
Expected *exec.Cmd
|
||||
ShouldError bool
|
||||
HandlerFunc func(t *testing.T, expected, actual *exec.Cmd) bool
|
||||
}{
|
||||
{
|
||||
Name: "Empty",
|
||||
Cmdline: "",
|
||||
ShouldError: true,
|
||||
},
|
||||
{
|
||||
Name: "CmdOnly",
|
||||
Cmdline: "/bin/echo",
|
||||
Expected: exec.Command("/bin/echo"),
|
||||
},
|
||||
{
|
||||
Name: "WithArgsSimple",
|
||||
Cmdline: "/bin/echo hello, world!",
|
||||
Expected: exec.Command("/bin/echo", "hello,", "world!"),
|
||||
},
|
||||
{
|
||||
Name: "WithArgsEscape",
|
||||
Cmdline: `/bin/echo \$ESCAPED $VAR`,
|
||||
Expected: exec.Command("/bin/echo", `$ESCAPED`, "$VAR"),
|
||||
},
|
||||
{
|
||||
Name: "WithArgsQuoted",
|
||||
Cmdline: `/bin/echo "hello, world" ... 'these have spaces'`,
|
||||
Expected: exec.Command("/bin/echo", "hello, world", "...", "these have spaces"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range cases {
|
||||
test := test // Avoid closure capture by ref
|
||||
tname := fmt.Sprintf("%s@%d:%d", test.Name, i+1, len(cases))
|
||||
|
||||
t.Run(tname, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if test.HandlerFunc == nil {
|
||||
test.HandlerFunc = Noop[*exec.Cmd]
|
||||
if test.Expected != nil {
|
||||
test.HandlerFunc = ExpectEqual[*exec.Cmd]
|
||||
if test.ShouldError {
|
||||
test.HandlerFunc = ExpectNotEqual[*exec.Cmd]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual, err := mkCmd(test.Cmdline)
|
||||
if test.ShouldError && err != nil {
|
||||
return
|
||||
} else if assert.NoError(t, err) {
|
||||
test.HandlerFunc(t, test.Expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExpectEqual[T any](t *testing.T, expected, actual T) bool {
|
||||
return assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func ExpectNotEqual[T any](t *testing.T, expected, actual T) bool {
|
||||
return assert.NotEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func Noop[T any](_ *testing.T, _, _ T) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func s2t(s string) *template.Template {
|
||||
return template.Must(template.New("TestHandler").Parse(s))
|
||||
}
|
Loading…
Reference in New Issue