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>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: "\u003ci\u003e*/" "></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(), ` ( <i>*/ ) `; 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 }