"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "tpl/internal/go_templates/htmltemplate/clone_test.go" between
hugo-0.80.0.tar.gz and hugo-0.81.0.tar.gz

About: Hugo is a static site generator that takes a source directory of Markdown files and templates and uses these as input to create a complete website (written in Go).

clone_test.go  (hugo-0.80.0):clone_test.go  (hugo-0.81.0)
skipping to change at line 13 skipping to change at line 13
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.13,!windows // +build go1.13,!windows
package template package template
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io"
"strings" "strings"
"sync" "sync"
"testing" "testing"
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
) )
func TestAddParseTree(t *testing.T) { func TestAddParseTreeHTML(t *testing.T) {
root := Must(New("root").Parse(`{{define "a"}} {{.}} {{template "b"}} {{. }} "></a>{{end}}`)) root := Must(New("root").Parse(`{{define "a"}} {{.}} {{template "b"}} {{. }} "></a>{{end}}`))
tree, err := parse.Parse("t", `{{define "b"}}<a href="{{end}}`, "", "", n il, nil) tree, err := parse.Parse("t", `{{define "b"}}<a href="{{end}}`, "", "", n il, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
added := Must(root.AddParseTree("b", tree["b"])) added := Must(root.AddParseTree("b", tree["b"]))
b := new(bytes.Buffer) b := new(bytes.Buffer)
err = added.ExecuteTemplate(b, "a", "1>0") err = added.ExecuteTemplate(b, "a", "1>0")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
skipping to change at line 177 skipping to change at line 177
// "Further calls to Parse in the copy will add templates // "Further calls to Parse in the copy will add templates
// to the copy but not to the original." // to the copy but not to the original."
func TestCloneThenParse(t *testing.T) { func TestCloneThenParse(t *testing.T) {
t0 := Must(New("t0").Parse(`{{define "a"}}{{template "embedded"}}{{end}}` )) t0 := Must(New("t0").Parse(`{{define "a"}}{{template "embedded"}}{{end}}` ))
t1 := Must(t0.Clone()) t1 := Must(t0.Clone())
Must(t1.Parse(`{{define "embedded"}}t1{{end}}`)) Must(t1.Parse(`{{define "embedded"}}t1{{end}}`))
if len(t0.Templates())+1 != len(t1.Templates()) { if len(t0.Templates())+1 != len(t1.Templates()) {
t.Error("adding a template to a clone added it to the original") t.Error("adding a template to a clone added it to the original")
} }
// double check that the embedded template isn't available in the origina l // double check that the embedded template isn't available in the origina l
err := t0.ExecuteTemplate(ioutil.Discard, "a", nil) err := t0.ExecuteTemplate(io.Discard, "a", nil)
if err == nil { if err == nil {
t.Error("expected 'no such template' error") t.Error("expected 'no such template' error")
} }
} }
// https://golang.org/issue/5980 // https://golang.org/issue/5980
func TestFuncMapWorksAfterClone(t *testing.T) { func TestFuncMapWorksAfterClone(t *testing.T) {
funcs := FuncMap{"customFunc": func() (string, error) { funcs := FuncMap{"customFunc": func() (string, error) {
return "", errors.New("issue5980") return "", errors.New("issue5980")
}} }}
// get the expected error output (no clone) // get the expected error output (no clone)
uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}")) uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
wantErr := uncloned.Execute(ioutil.Discard, nil) wantErr := uncloned.Execute(io.Discard, nil)
// toClone must be the same as uncloned. It has to be recreated from scra tch, // toClone must be the same as uncloned. It has to be recreated from scra tch,
// since cloning cannot occur after execution. // since cloning cannot occur after execution.
toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}")) toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
cloned := Must(toClone.Clone()) cloned := Must(toClone.Clone())
gotErr := cloned.Execute(ioutil.Discard, nil) gotErr := cloned.Execute(io.Discard, nil)
if wantErr.Error() != gotErr.Error() { if wantErr.Error() != gotErr.Error() {
t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr) t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr)
} }
} }
// https://golang.org/issue/16101 // https://golang.org/issue/16101
func TestTemplateCloneExecuteRace(t *testing.T) { func TestTemplateCloneExecuteRace(t *testing.T) {
const ( const (
input = `<title>{{block "a" .}}a{{end}}</title><body>{{block "b " .}}b{{end}}<body>` input = `<title>{{block "a" .}}a{{end}}</title><body>{{block "b " .}}b{{end}}<body>`
skipping to change at line 219 skipping to change at line 219
) )
outer := Must(New("outer").Parse(input)) outer := Must(New("outer").Parse(input))
tmpl := Must(Must(outer.Clone()).Parse(overlay)) tmpl := Must(Must(outer.Clone()).Parse(overlay))
var wg sync.WaitGroup var wg sync.WaitGroup
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
if err := tmpl.Execute(ioutil.Discard, "data"); e rr != nil { if err := tmpl.Execute(io.Discard, "data"); err ! = nil {
panic(err) panic(err)
} }
} }
}() }()
} }
wg.Wait() wg.Wait()
} }
func TestTemplateCloneLookup(t *testing.T) { func TestTemplateCloneLookup(t *testing.T) {
// Template.escape makes an assumption that the template associated // Template.escape makes an assumption that the template associated
skipping to change at line 243 skipping to change at line 243
if tmpl.Lookup(tmpl.Name()) != tmpl { if tmpl.Lookup(tmpl.Name()) != tmpl {
t.Error("after Clone, tmpl.Lookup(tmpl.Name()) != tmpl") t.Error("after Clone, tmpl.Lookup(tmpl.Name()) != tmpl")
} }
} }
func TestCloneGrowth(t *testing.T) { func TestCloneGrowth(t *testing.T) {
tmpl := Must(New("root").Parse(`<title>{{block "B". }}Arg{{end}}</title>` )) tmpl := Must(New("root").Parse(`<title>{{block "B". }}Arg{{end}}</title>` ))
tmpl = Must(tmpl.Clone()) tmpl = Must(tmpl.Clone())
Must(tmpl.Parse(`{{define "B"}}Text{{end}}`)) Must(tmpl.Parse(`{{define "B"}}Text{{end}}`))
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
tmpl.Execute(ioutil.Discard, nil) tmpl.Execute(io.Discard, nil)
} }
if len(tmpl.DefinedTemplates()) > 200 { if len(tmpl.DefinedTemplates()) > 200 {
t.Fatalf("too many templates: %v", len(tmpl.DefinedTemplates())) t.Fatalf("too many templates: %v", len(tmpl.DefinedTemplates()))
} }
} }
// https://golang.org/issue/17735 // https://golang.org/issue/17735
func TestCloneRedefinedName(t *testing.T) { func TestCloneRedefinedName(t *testing.T) {
const base = ` const base = `
{{ define "a" -}}<title>{{ template "b" . -}}</title>{{ end -}} {{ define "a" -}}<title>{{ template "b" . -}}</title>{{ end -}}
{{ define "b" }}{{ end -}} {{ define "b" }}{{ end -}}
` `
const page = `{{ template "a" . }}` const page = `{{ template "a" . }}`
t1 := Must(New("a").Parse(base)) t1 := Must(New("a").Parse(base))
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
t2 := Must(t1.Clone()) t2 := Must(t1.Clone())
t2 = Must(t2.New(fmt.Sprintf("%d", i)).Parse(page)) t2 = Must(t2.New(fmt.Sprintf("%d", i)).Parse(page))
err := t2.Execute(ioutil.Discard, nil) err := t2.Execute(io.Discard, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
} }
// Issue 24791. // Issue 24791.
func TestClonePipe(t *testing.T) { func TestClonePipe(t *testing.T) {
a := Must(New("a").Parse(`{{define "a"}}{{range $v := .A}}{{$v}}{{end}}{{ end}}`)) a := Must(New("a").Parse(`{{define "a"}}{{range $v := .A}}{{$v}}{{end}}{{ end}}`))
data := struct{ A []string }{A: []string{"hi"}} data := struct{ A []string }{A: []string{"hi"}}
 End of changes. 8 change blocks. 
8 lines changed or deleted 8 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)