mirror of
https://github.com/danog/liquid.git
synced 2024-11-30 08:18:59 +01:00
1a2066b87e
This commit addresses two issues: 1. For variadic functions 'convertCallArguments' was allocating exactly 'len(args)' arguments, which might be less than required, as a result zero/default filling loop would panic with out of bounds error. 2. Even if we correctly allocate a proper amount of arguments, zero/default filling loop doesn't handle special variadic function type case, when last argument has a slice type and reflect API expects plain values as arguments. But actually we don't need that, because it's okay to omit variadic values altogether, hence the total amount of allocated arguments is max(len(args), rt.NumIn()-1).
79 lines
2.2 KiB
Go
79 lines
2.2 KiB
Go
package values
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCall(t *testing.T) {
|
|
fn := func(a, b string) string {
|
|
return a + "," + b + "."
|
|
}
|
|
value, err := Call(reflect.ValueOf(fn), []interface{}{5, 10})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "5,10.", value)
|
|
|
|
// extra arguments (variadic)
|
|
fnVaridic := func(a string, b ...string) string {
|
|
return a + "," + strings.Join(b, ",") + "."
|
|
}
|
|
value, err = Call(reflect.ValueOf(fnVaridic), []interface{}{5, 10})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "5,10.", value)
|
|
value, err = Call(reflect.ValueOf(fnVaridic), []interface{}{5, 10, 15, 20})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "5,10,15,20.", value)
|
|
|
|
// extra arguments (non variadic)
|
|
_, err = Call(reflect.ValueOf(fn), []interface{}{5, 10, 20})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "wrong number of arguments")
|
|
require.Contains(t, err.Error(), "given 3")
|
|
require.Contains(t, err.Error(), "expected 2")
|
|
|
|
// error return
|
|
fn2 := func(int) (int, error) { return 0, fmt.Errorf("expected error") }
|
|
_, err = Call(reflect.ValueOf(fn2), []interface{}{2})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "expected error")
|
|
}
|
|
|
|
func TestCall_optional(t *testing.T) {
|
|
fn := func(a string, b func(string) string) string {
|
|
return a + "," + b("default") + "."
|
|
}
|
|
value, err := Call(reflect.ValueOf(fn), []interface{}{5})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "5,default.", value)
|
|
|
|
value, err = Call(reflect.ValueOf(fn), []interface{}{5, 10})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "5,10.", value)
|
|
}
|
|
|
|
func TestCall_variadic(t *testing.T) {
|
|
fn := func(sep func(string) string, args ...string) string {
|
|
return "[" + strings.Join(args, sep(",")) + "]"
|
|
}
|
|
|
|
value, err := Call(reflect.ValueOf(fn), []interface{}{",", "a"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "[a]", value)
|
|
|
|
value, err = Call(reflect.ValueOf(fn), []interface{}{",", "a", "b"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "[a,b]", value)
|
|
|
|
value, err = Call(reflect.ValueOf(fn), []interface{}{","})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "[]", value)
|
|
|
|
value, err = Call(reflect.ValueOf(fn), []interface{}{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "[]", value)
|
|
}
|