shithub: hugo

Download patch

ref: e2e8bcbec34702a27047b91b6b007a15f1fc0797
parent: 66a169a24967681dbf91dad6e1f9fd5dd624d95e
author: Bjørn Erik Pedersen <[email protected]>
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()
 	}
 }