ref: e2e8bcbec34702a27047b91b6b007a15f1fc0797
parent: 66a169a24967681dbf91dad6e1f9fd5dd624d95e
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Sat Oct 7 12:52:35 EDT 2017
tpl: Rework the partial test and benchmarks
--- a/tpl/partials/init.go
+++ b/tpl/partials/init.go
@@ -36,7 +36,7 @@
},
)
- ns.AddMethodMapping(ctx.getCached,
+ ns.AddMethodMapping(ctx.IncludeCached,
[]string{"partialCached"}, [][2]string{},)
--- a/tpl/partials/partials.go
+++ b/tpl/partials/partials.go
@@ -88,11 +88,11 @@
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
// 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.
-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
if len(variant) > 0 { for i := 0; i < len(variant); i++ {--- a/tpl/tplimpl/template_funcs_test.go
+++ b/tpl/tplimpl/template_funcs_test.go
@@ -19,6 +19,7 @@
"path/filepath"
"reflect"
"testing"
+ "time"
"io/ioutil"
"log"
@@ -31,6 +32,7 @@
"github.com/gohugoio/hugo/i18n"
"github.com/gohugoio/hugo/tpl"
"github.com/gohugoio/hugo/tpl/internal"
+ "github.com/gohugoio/hugo/tpl/partials"
"github.com/spf13/afero"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
@@ -112,120 +114,75 @@
// we have some package cycle issues to solve first.
func TestPartialCached(t *testing.T) {t.Parallel()
- testCases := []struct {- name string
- partial string
- tmpl string
- variant string
- }{- // 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 {- Title string
- Section string
- Params map[string]interface{}- }
+ assert := require.New(t)
- data.Title = "**BatMan**"
- data.Section = "blog"
- data.Params = map[string]interface{}{"langCode": "en"}+ partial := `Now: {{ now.UnixNano }}`+ name := "testing"
- for i, tc := range testCases {- var tmp string
- 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 {- t.Fatalf("[%d] error executing template: %s", i, err)- }
-
- for j := 0; j < 10; j++ {- 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) {- t.Fatalf("[%d] cached results do not match:\nResult 1:\n%q\nResult 2:\n%q", i, buf, buf2)- }
- }
+ var data struct {}
-}
-func BenchmarkPartial(b *testing.B) {config := newDepsConfig(viper.New())
+
config.WithTemplate = func(templ tpl.TemplateHandler) error {- err := templ.AddTemplate("testroot", `{{ partial "bench1" . }}`)+ err := templ.AddTemplate("partials/"+name, partial) 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())
+ assert.NoError(err)
+ assert.NoError(de.LoadResources())
- buf := new(bytes.Buffer)
- tmpl := de.Tmpl.Lookup("testroot")+ ns := partials.New(de)
- 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)+ 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")}
- buf.Reset()
+
+ 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) {+ doBenchmarkPartial(b, func(ns *partials.Namespace) error {+ _, err := ns.Include("bench1")+ return err
+ })
+}
+
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.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 {- return err
- }
return nil
}
@@ -234,16 +191,13 @@
require.NoError(b, err)
require.NoError(b, de.LoadResources())
- buf := new(bytes.Buffer)
- tmpl := de.Tmpl.Lookup("testroot")+ ns := partials.New(de)
- b.ReportAllocs()
b.ResetTimer()
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)}
- buf.Reset()
}
}
--
⑨