fiber/internal/fasttemplate/template_test.go

437 lines
12 KiB
Go

package fasttemplate
import (
"bytes"
"errors"
"io"
"testing"
)
func TestEmptyTemplate(t *testing.T) {
tpl := New("", "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "bar", "aaa": "bbb"})
if s != "" {
t.Fatalf("unexpected string returned %q. Expected empty string", s)
}
}
func TestEmptyTagStart(t *testing.T) {
expectPanic(t, func() { NewTemplate("foobar", "", "]") })
}
func TestEmptyTagEnd(t *testing.T) {
expectPanic(t, func() { NewTemplate("foobar", "[", "") })
}
func TestNoTags(t *testing.T) {
template := "foobar"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "bar", "aaa": "bbb"})
if s != template {
t.Fatalf("unexpected template value %q. Expected %q", s, template)
}
}
func TestEmptyTagName(t *testing.T) {
template := "foo[]bar"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"": "111", "aaa": "bbb"})
result := "foo111bar"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestOnlyTag(t *testing.T) {
template := "[foo]"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "111"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestStartWithTag(t *testing.T) {
template := "[foo]barbaz"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "111barbaz"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestEndWithTag(t *testing.T) {
template := "foobar[foo]"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "foobar111"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestTemplateReset(t *testing.T) {
template := "foo{bar}baz"
tpl := New(template, "{", "}")
s := tpl.ExecuteString(map[string]interface{}{"bar": "111"})
result := "foo111baz"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
template = "[xxxyyyzz"
if err := tpl.Reset(template, "[", "]"); err == nil {
t.Fatalf("expecting error for unclosed tag on %q", template)
}
template = "[xxx]yyy[zz]"
if err := tpl.Reset(template, "[", "]"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
s = tpl.ExecuteString(map[string]interface{}{"xxx": "11", "zz": "2222"})
result = "11yyy2222"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestDuplicateTags(t *testing.T) {
template := "[foo]bar[foo][foo]baz"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "111bar111111baz"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestMultipleTags(t *testing.T) {
template := "foo[foo]aa[aaa]ccc"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "foo111aabbbccc"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestLongDelimiter(t *testing.T) {
template := "foo{{{foo}}}bar"
tpl := New(template, "{{{", "}}}")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "foo111bar"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestIdenticalDelimiter(t *testing.T) {
template := "foo@foo@foo@aaa@"
tpl := New(template, "@", "@")
s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
result := "foo111foobbb"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestDlimitersWithDistinctSize(t *testing.T) {
template := "foo<?phpaaa?>bar<?phpzzz?>"
tpl := New(template, "<?php", "?>")
s := tpl.ExecuteString(map[string]interface{}{"zzz": "111", "aaa": "bbb"})
result := "foobbbbar111"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestEmptyValue(t *testing.T) {
template := "foobar[foo]"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"foo": "", "aaa": "bbb"})
result := "foobar"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestNoValue(t *testing.T) {
template := "foobar[foo]x[aaa]"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{"aaa": "bbb"})
result := "foobarxbbb"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestNoEndDelimiter(t *testing.T) {
template := "foobar[foo"
_, err := NewTemplate(template, "[", "]")
if err == nil {
t.Fatalf("expected non-nil error. got nil")
}
expectPanic(t, func() { New(template, "[", "]") })
}
func TestUnsupportedValue(t *testing.T) {
template := "foobar[foo]"
tpl := New(template, "[", "]")
expectPanic(t, func() {
tpl.ExecuteString(map[string]interface{}{"foo": 123, "aaa": "bbb"})
})
}
func TestMixedValues(t *testing.T) {
template := "foo[foo]bar[bar]baz[baz]"
tpl := New(template, "[", "]")
s := tpl.ExecuteString(map[string]interface{}{
"foo": "111",
"bar": []byte("bbb"),
"baz": TagFunc(func(w io.Writer, tag string) (int, error) { return w.Write([]byte(tag)) }),
})
result := "foo111barbbbbazbaz"
if s != result {
t.Fatalf("unexpected template value %q. Expected %q", s, result)
}
}
func TestExecuteFunc(t *testing.T) {
testExecuteFunc(t, "", "")
testExecuteFunc(t, "a", "a")
testExecuteFunc(t, "abc", "abc")
testExecuteFunc(t, "{foo}", "xxxx")
testExecuteFunc(t, "a{foo}", "axxxx")
testExecuteFunc(t, "{foo}a", "xxxxa")
testExecuteFunc(t, "a{foo}bc", "axxxxbc")
testExecuteFunc(t, "{foo}{foo}", "xxxxxxxx")
testExecuteFunc(t, "{foo}bar{foo}", "xxxxbarxxxx")
// unclosed tag
testExecuteFunc(t, "{unclosed", "{unclosed")
testExecuteFunc(t, "{{unclosed", "{{unclosed")
testExecuteFunc(t, "{un{closed", "{un{closed")
// test unknown tag
testExecuteFunc(t, "{unknown}", "zz")
testExecuteFunc(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqzzzzbarxxxx")
}
func testExecuteFunc(t *testing.T, template, expectedOutput string) {
var bb bytes.Buffer
ExecuteFunc(template, "{", "}", &bb, func(w io.Writer, tag string) (int, error) {
if tag == "foo" {
return w.Write([]byte("xxxx"))
}
return w.Write([]byte("zz"))
})
output := string(bb.Bytes())
if output != expectedOutput {
t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
}
}
func TestExecute(t *testing.T) {
testExecute(t, "", "")
testExecute(t, "a", "a")
testExecute(t, "abc", "abc")
testExecute(t, "{foo}", "xxxx")
testExecute(t, "a{foo}", "axxxx")
testExecute(t, "{foo}a", "xxxxa")
testExecute(t, "a{foo}bc", "axxxxbc")
testExecute(t, "{foo}{foo}", "xxxxxxxx")
testExecute(t, "{foo}bar{foo}", "xxxxbarxxxx")
// unclosed tag
testExecute(t, "{unclosed", "{unclosed")
testExecute(t, "{{unclosed", "{{unclosed")
testExecute(t, "{un{closed", "{un{closed")
// test unknown tag
testExecute(t, "{unknown}", "")
testExecute(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqbarxxxx")
}
func testExecute(t *testing.T, template, expectedOutput string) {
var bb bytes.Buffer
Execute(template, "{", "}", &bb, map[string]interface{}{"foo": "xxxx"})
output := string(bb.Bytes())
if output != expectedOutput {
t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
}
}
func TestExecuteStd(t *testing.T) {
testExecuteStd(t, "", "")
testExecuteStd(t, "a", "a")
testExecuteStd(t, "abc", "abc")
testExecuteStd(t, "{foo}", "xxxx")
testExecuteStd(t, "a{foo}", "axxxx")
testExecuteStd(t, "{foo}a", "xxxxa")
testExecuteStd(t, "a{foo}bc", "axxxxbc")
testExecuteStd(t, "{foo}{foo}", "xxxxxxxx")
testExecuteStd(t, "{foo}bar{foo}", "xxxxbarxxxx")
// unclosed tag
testExecuteStd(t, "{unclosed", "{unclosed")
testExecuteStd(t, "{{unclosed", "{{unclosed")
testExecuteStd(t, "{un{closed", "{un{closed")
// test unknown tag
testExecuteStd(t, "{unknown}", "{unknown}")
testExecuteStd(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxq{unexpected}{missing}barxxxx")
}
func testExecuteStd(t *testing.T, template, expectedOutput string) {
var bb bytes.Buffer
ExecuteStd(template, "{", "}", &bb, map[string]interface{}{"foo": "xxxx"})
output := string(bb.Bytes())
if output != expectedOutput {
t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
}
}
func TestExecuteString(t *testing.T) {
testExecuteString(t, "", "")
testExecuteString(t, "a", "a")
testExecuteString(t, "abc", "abc")
testExecuteString(t, "{foo}", "xxxx")
testExecuteString(t, "a{foo}", "axxxx")
testExecuteString(t, "{foo}a", "xxxxa")
testExecuteString(t, "a{foo}bc", "axxxxbc")
testExecuteString(t, "{foo}{foo}", "xxxxxxxx")
testExecuteString(t, "{foo}bar{foo}", "xxxxbarxxxx")
// unclosed tag
testExecuteString(t, "{unclosed", "{unclosed")
testExecuteString(t, "{{unclosed", "{{unclosed")
testExecuteString(t, "{un{closed", "{un{closed")
// test unknown tag
testExecuteString(t, "{unknown}", "")
testExecuteString(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqbarxxxx")
}
func testExecuteString(t *testing.T, template, expectedOutput string) {
output := ExecuteString(template, "{", "}", map[string]interface{}{"foo": "xxxx"})
if output != expectedOutput {
t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
}
}
func TestExecuteStringStd(t *testing.T) {
testExecuteStringStd(t, "", "")
testExecuteStringStd(t, "a", "a")
testExecuteStringStd(t, "abc", "abc")
testExecuteStringStd(t, "{foo}", "xxxx")
testExecuteStringStd(t, "a{foo}", "axxxx")
testExecuteStringStd(t, "{foo}a", "xxxxa")
testExecuteStringStd(t, "a{foo}bc", "axxxxbc")
testExecuteStringStd(t, "{foo}{foo}", "xxxxxxxx")
testExecuteStringStd(t, "{foo}bar{foo}", "xxxxbarxxxx")
// unclosed tag
testExecuteStringStd(t, "{unclosed", "{unclosed")
testExecuteStringStd(t, "{{unclosed", "{{unclosed")
testExecuteStringStd(t, "{un{closed", "{un{closed")
// test unknown tag
testExecuteStringStd(t, "{unknown}", "{unknown}")
testExecuteStringStd(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxq{unexpected}{missing}barxxxx")
}
func testExecuteStringStd(t *testing.T, template, expectedOutput string) {
output := ExecuteStringStd(template, "{", "}", map[string]interface{}{"foo": "xxxx"})
if output != expectedOutput {
t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
}
}
func expectPanic(t *testing.T, f func()) {
defer func() {
if r := recover(); r == nil {
t.Fatalf("missing panic")
}
}()
f()
}
func TestExecuteFuncStringWithErr(t *testing.T) {
var expectErr = errors.New("test111")
result, err := ExecuteFuncStringWithErr(`{a} is {b}'s best friend`, "{", "}", func(w io.Writer, tag string) (int, error) {
if tag == "a" {
return w.Write([]byte("Alice"))
}
return 0, expectErr
})
if err != expectErr {
t.Fatalf("error must be the same as the error returned from f, expect: %s, actual: %s", expectErr, err)
}
if result != "" {
t.Fatalf("result should be an empty string if error occurred")
}
result, err = ExecuteFuncStringWithErr(`{a} is {b}'s best friend`, "{", "}", func(w io.Writer, tag string) (int, error) {
if tag == "a" {
return w.Write([]byte("Alice"))
}
return w.Write([]byte("Bob"))
})
if err != nil {
t.Fatalf("should success but found err: %s", err)
}
if result != "Alice is Bob's best friend" {
t.Fatalf("expect: %s, but: %s", "Alice is Bob's best friend", result)
}
}
func TestTpl_ExecuteFuncStringWithErr(t *testing.T) {
var expectErr = errors.New("test111")
tpl, err := NewTemplate(`{a} is {b}'s best friend`, "{", "}")
if err != nil {
t.Fatalf("should success, but found err: %s", err)
}
result, err := tpl.ExecuteFuncStringWithErr(func(w io.Writer, tag string) (int, error) {
if tag == "a" {
return w.Write([]byte("Alice"))
}
return 0, expectErr
})
if err != expectErr {
t.Fatalf("error must be the same as the error returned from f, expect: %s, actual: %s", expectErr, err)
}
if result != "" {
t.Fatalf("result should be an empty string if error occurred")
}
result, err = tpl.ExecuteFuncStringWithErr(func(w io.Writer, tag string) (int, error) {
if tag == "a" {
return w.Write([]byte("Alice"))
}
return w.Write([]byte("Bob"))
})
if err != nil {
t.Fatalf("should success but found err: %s", err)
}
if result != "Alice is Bob's best friend" {
t.Fatalf("expect: %s, but: %s", "Alice is Bob's best friend", result)
}
}