tpl: Rework the partial test and benchmarks

This commit is contained in:
Bjørn Erik Pedersen 2017-10-07 16:52:35 +02:00
parent 66a169a249
commit e2e8bcbec3
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F
3 changed files with 54 additions and 100 deletions

View file

@ -36,7 +36,7 @@ func init() {
}, },
) )
ns.AddMethodMapping(ctx.getCached, ns.AddMethodMapping(ctx.IncludeCached,
[]string{"partialCached"}, []string{"partialCached"},
[][2]string{}, [][2]string{},
) )

View file

@ -88,11 +88,11 @@ func (ns *Namespace) Include(name string, contextList ...interface{}) (interface
return "", fmt.Errorf("Partial %q not found", name) return "", fmt.Errorf("Partial %q not found", name)
} }
// getCached executes and caches partial templates. An optional variant // IncludeCached executes and caches partial templates. An optional variant
// string parameter (a string slice actually, but be only use a variadic // string parameter (a string slice actually, but be only use a variadic
// argument to make it optional) can be passed so that a given partial can have // argument to make it optional) can be passed so that a given partial can have
// multiple uses. The cache is created with name+variant as the key. // multiple uses. The cache is created with name+variant as the key.
func (ns *Namespace) getCached(name string, context interface{}, variant ...string) (interface{}, error) { func (ns *Namespace) IncludeCached(name string, context interface{}, variant ...string) (interface{}, error) {
key := name key := name
if len(variant) > 0 { if len(variant) > 0 {
for i := 0; i < len(variant); i++ { for i := 0; i < len(variant); i++ {

View file

@ -19,6 +19,7 @@ import (
"path/filepath" "path/filepath"
"reflect" "reflect"
"testing" "testing"
"time"
"io/ioutil" "io/ioutil"
"log" "log"
@ -31,6 +32,7 @@ import (
"github.com/gohugoio/hugo/i18n" "github.com/gohugoio/hugo/i18n"
"github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/tpl"
"github.com/gohugoio/hugo/tpl/internal" "github.com/gohugoio/hugo/tpl/internal"
"github.com/gohugoio/hugo/tpl/partials"
"github.com/spf13/afero" "github.com/spf13/afero"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -112,117 +114,72 @@ func TestTemplateFuncsExamples(t *testing.T) {
// we have some package cycle issues to solve first. // we have some package cycle issues to solve first.
func TestPartialCached(t *testing.T) { func TestPartialCached(t *testing.T) {
t.Parallel() t.Parallel()
testCases := []struct {
name string assert := require.New(t)
partial string
tmpl string partial := `Now: {{ now.UnixNano }}`
variant string name := "testing"
}{
// name and partial should match between test cases.
{"test1", "{{ .Title }} seq: {{ shuffle (seq 1 20) }}", `{{ partialCached "test1" . }}`, ""},
{"test1", "{{ .Title }} seq: {{ shuffle (seq 1 20) }}", `{{ partialCached "test1" . "%s" }}`, "header"},
{"test1", "{{ .Title }} seq: {{ shuffle (seq 1 20) }}", `{{ partialCached "test1" . "%s" }}`, "footer"},
{"test1", "{{ .Title }} seq: {{ shuffle (seq 1 20) }}", `{{ partialCached "test1" . "%s" }}`, "header"},
}
var data struct { var data struct {
Title string
Section string
Params map[string]interface{}
} }
data.Title = "**BatMan**" config := newDepsConfig(viper.New())
data.Section = "blog"
data.Params = map[string]interface{}{"langCode": "en"}
for i, tc := range testCases { config.WithTemplate = func(templ tpl.TemplateHandler) error {
var tmp string err := templ.AddTemplate("partials/"+name, partial)
if tc.variant != "" {
tmp = fmt.Sprintf(tc.tmpl, tc.variant)
} else {
tmp = tc.tmpl
}
config := newDepsConfig(viper.New())
config.WithTemplate = func(templ tpl.TemplateHandler) error {
err := templ.AddTemplate("testroot", tmp)
if err != nil {
return err
}
err = templ.AddTemplate("partials/"+tc.name, tc.partial)
if err != nil {
return err
}
return nil
}
de, err := deps.New(config)
require.NoError(t, err)
require.NoError(t, de.LoadResources())
buf := new(bytes.Buffer)
templ := de.Tmpl.Lookup("testroot")
err = templ.Execute(buf, &data)
if err != nil { if err != nil {
t.Fatalf("[%d] error executing template: %s", i, err) return err
} }
for j := 0; j < 10; j++ { return nil
buf2 := new(bytes.Buffer) }
err := templ.Execute(buf2, nil)
if err != nil {
t.Fatalf("[%d] error executing template 2nd time: %s", i, err)
}
if !reflect.DeepEqual(buf, buf2) { de, err := deps.New(config)
t.Fatalf("[%d] cached results do not match:\nResult 1:\n%q\nResult 2:\n%q", i, buf, buf2) assert.NoError(err)
} assert.NoError(de.LoadResources())
ns := partials.New(de)
res1, err := ns.IncludeCached(name, &data)
assert.NoError(err)
for j := 0; j < 10; j++ {
time.Sleep(2 * time.Nanosecond)
res2, err := ns.IncludeCached(name, &data)
assert.NoError(err)
if !reflect.DeepEqual(res1, res2) {
t.Fatalf("cache mismatch")
}
res3, err := ns.IncludeCached(name, &data, fmt.Sprintf("variant%d", j))
assert.NoError(err)
if reflect.DeepEqual(res1, res3) {
t.Fatalf("cache mismatch")
} }
} }
} }
func BenchmarkPartial(b *testing.B) { func BenchmarkPartial(b *testing.B) {
config := newDepsConfig(viper.New()) doBenchmarkPartial(b, func(ns *partials.Namespace) error {
config.WithTemplate = func(templ tpl.TemplateHandler) error { _, err := ns.Include("bench1")
err := templ.AddTemplate("testroot", `{{ partial "bench1" . }}`) return err
if err != nil { })
return err
}
err = templ.AddTemplate("partials/bench1", `{{ shuffle (seq 1 10) }}`)
if err != nil {
return err
}
return nil
}
de, err := deps.New(config)
require.NoError(b, err)
require.NoError(b, de.LoadResources())
buf := new(bytes.Buffer)
tmpl := de.Tmpl.Lookup("testroot")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := tmpl.Execute(buf, nil); err != nil {
b.Fatalf("error executing template: %s", err)
}
buf.Reset()
}
} }
func BenchmarkPartialCached(b *testing.B) { func BenchmarkPartialCached(b *testing.B) {
doBenchmarkPartial(b, func(ns *partials.Namespace) error {
_, err := ns.IncludeCached("bench1", nil)
return err
})
}
func doBenchmarkPartial(b *testing.B, f func(ns *partials.Namespace) error) {
config := newDepsConfig(viper.New()) config := newDepsConfig(viper.New())
config.WithTemplate = func(templ tpl.TemplateHandler) error { config.WithTemplate = func(templ tpl.TemplateHandler) error {
err := templ.AddTemplate("testroot", `{{ partialCached "bench1" . }}`) err := templ.AddTemplate("partials/bench1", `{{ shuffle (seq 1 10) }}`)
if err != nil {
return err
}
err = templ.AddTemplate("partials/bench1", `{{ shuffle (seq 1 10) }}`)
if err != nil { if err != nil {
return err return err
} }
@ -234,16 +191,13 @@ func BenchmarkPartialCached(b *testing.B) {
require.NoError(b, err) require.NoError(b, err)
require.NoError(b, de.LoadResources()) require.NoError(b, de.LoadResources())
buf := new(bytes.Buffer) ns := partials.New(de)
tmpl := de.Tmpl.Lookup("testroot")
b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if err := tmpl.Execute(buf, nil); err != nil { if err := f(ns); err != nil {
b.Fatalf("error executing template: %s", err) b.Fatalf("error executing template: %s", err)
} }
buf.Reset()
} }
} }