github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/html/template/clone_test.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package template
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  	"text/template/parse"
    11  )
    12  
    13  func TestAddParseTree(t *testing.T) {
    14  	root := Must(New("root").Parse(`{{define "a"}} {{.}} {{template "b"}} {{.}} "></a>{{end}}`))
    15  	tree, err := parse.Parse("t", `{{define "b"}}<a href="{{end}}`, "", "", nil, nil)
    16  	if err != nil {
    17  		t.Fatal(err)
    18  	}
    19  	added := Must(root.AddParseTree("b", tree["b"]))
    20  	b := new(bytes.Buffer)
    21  	err = added.ExecuteTemplate(b, "a", "1>0")
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	if got, want := b.String(), ` 1&gt;0 <a href=" 1%3e0 "></a>`; got != want {
    26  		t.Errorf("got %q want %q", got, want)
    27  	}
    28  }
    29  
    30  func TestClone(t *testing.T) {
    31  	// The {{.}} will be executed with data "<i>*/" in different contexts.
    32  	// In the t0 template, it will be in a text context.
    33  	// In the t1 template, it will be in a URL context.
    34  	// In the t2 template, it will be in a JavaScript context.
    35  	// In the t3 template, it will be in a CSS context.
    36  	const tmpl = `{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}`
    37  	b := new(bytes.Buffer)
    38  
    39  	// Create an incomplete template t0.
    40  	t0 := Must(New("t0").Parse(tmpl))
    41  
    42  	// Clone t0 as t1.
    43  	t1 := Must(t0.Clone())
    44  	Must(t1.Parse(`{{define "lhs"}} <a href=" {{end}}`))
    45  	Must(t1.Parse(`{{define "rhs"}} "></a> {{end}}`))
    46  
    47  	// Execute t1.
    48  	b.Reset()
    49  	if err := t1.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
    50  		t.Fatal(err)
    51  	}
    52  	if got, want := b.String(), ` <a href=" %3ci%3e*/ "></a> `; got != want {
    53  		t.Errorf("t1: got %q want %q", got, want)
    54  	}
    55  
    56  	// Clone t0 as t2.
    57  	t2 := Must(t0.Clone())
    58  	Must(t2.Parse(`{{define "lhs"}} <p onclick="javascript: {{end}}`))
    59  	Must(t2.Parse(`{{define "rhs"}} "></p> {{end}}`))
    60  
    61  	// Execute t2.
    62  	b.Reset()
    63  	if err := t2.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	if got, want := b.String(), ` <p onclick="javascript: &#34;\u003ci\u003e*/&#34; "></p> `; got != want {
    67  		t.Errorf("t2: got %q want %q", got, want)
    68  	}
    69  
    70  	// Clone t0 as t3, but do not execute t3 yet.
    71  	t3 := Must(t0.Clone())
    72  	Must(t3.Parse(`{{define "lhs"}} <style> {{end}}`))
    73  	Must(t3.Parse(`{{define "rhs"}} </style> {{end}}`))
    74  
    75  	// Complete t0.
    76  	Must(t0.Parse(`{{define "lhs"}} ( {{end}}`))
    77  	Must(t0.Parse(`{{define "rhs"}} ) {{end}}`))
    78  
    79  	// Clone t0 as t4. Redefining the "lhs" template should fail.
    80  	t4 := Must(t0.Clone())
    81  	if _, err := t4.Parse(`{{define "lhs"}} FAIL {{end}}`); err == nil {
    82  		t.Error(`redefine "lhs": got nil err want non-nil`)
    83  	}
    84  
    85  	// Execute t0.
    86  	b.Reset()
    87  	if err := t0.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	if got, want := b.String(), ` ( &lt;i&gt;*/ ) `; got != want {
    91  		t.Errorf("t0: got %q want %q", got, want)
    92  	}
    93  
    94  	// Clone t0. This should fail, as t0 has already executed.
    95  	if _, err := t0.Clone(); err == nil {
    96  		t.Error(`t0.Clone(): got nil err want non-nil`)
    97  	}
    98  
    99  	// Similarly, cloning sub-templates should fail.
   100  	if _, err := t0.Lookup("a").Clone(); err == nil {
   101  		t.Error(`t0.Lookup("a").Clone(): got nil err want non-nil`)
   102  	}
   103  	if _, err := t0.Lookup("lhs").Clone(); err == nil {
   104  		t.Error(`t0.Lookup("lhs").Clone(): got nil err want non-nil`)
   105  	}
   106  
   107  	// Execute t3.
   108  	b.Reset()
   109  	if err := t3.ExecuteTemplate(b, "a", "<i>*/"); err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	if got, want := b.String(), ` <style> ZgotmplZ </style> `; got != want {
   113  		t.Errorf("t3: got %q want %q", got, want)
   114  	}
   115  }
   116  
   117  func TestTemplates(t *testing.T) {
   118  	names := []string{"t0", "a", "lhs", "rhs"}
   119  	// Some template definitions borrowed from TestClone.
   120  	const tmpl = `
   121  		{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}
   122  		{{define "lhs"}} <a href=" {{end}}
   123  		{{define "rhs"}} "></a> {{end}}`
   124  	t0 := Must(New("t0").Parse(tmpl))
   125  	templates := t0.Templates()
   126  	if len(templates) != len(names) {
   127  		t.Errorf("expected %d templates; got %d", len(names), len(templates))
   128  	}
   129  	for _, name := range names {
   130  		found := false
   131  		for _, tmpl := range templates {
   132  			if name == tmpl.text.Name() {
   133  				found = true
   134  				break
   135  			}
   136  		}
   137  		if !found {
   138  			t.Error("could not find template", name)
   139  		}
   140  	}
   141  }
   142  
   143  // This used to crash; http://golang.org/issue/3281
   144  func TestCloneCrash(t *testing.T) {
   145  	t1 := New("all")
   146  	Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
   147  	t1.Clone()
   148  }