mirror of
				https://github.com/gohugoio/hugo.git
				synced 2024-05-11 05:54:58 +00:00 
			
		
		
		
	tpl: Rework the partial test and benchmarks
This commit is contained in:
		@@ -36,7 +36,7 @@ func init() {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ns.AddMethodMapping(ctx.getCached,
 | 
							ns.AddMethodMapping(ctx.IncludeCached,
 | 
				
			||||||
			[]string{"partialCached"},
 | 
								[]string{"partialCached"},
 | 
				
			||||||
			[][2]string{},
 | 
								[][2]string{},
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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++ {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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()
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user