PR c++/86342 - -Wdeprecated-copy and system headers.
[official-gcc.git] / libgo / go / html / template / content_test.go
blobcc092f50c0c1e4df2f36a8f32fdcb40191b44633
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.
5 package template
7 import (
8 "bytes"
9 "fmt"
10 "strings"
11 "testing"
14 func TestTypedContent(t *testing.T) {
15 data := []interface{}{
16 `<b> "foo%" O'Reilly &bar;`,
17 CSS(`a[href =~ "//example.com"]#foo`),
18 HTML(`Hello, <b>World</b> &amp;tc!`),
19 HTMLAttr(` dir="ltr"`),
20 JS(`c && alert("Hello, World!");`),
21 JSStr(`Hello, World & O'Reilly\x21`),
22 URL(`greeting=H%69,&addressee=(World)`),
23 Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`),
24 URL(`,foo/,`),
27 // For each content sensitive escaper, see how it does on
28 // each of the typed strings above.
29 tests := []struct {
30 // A template containing a single {{.}}.
31 input string
32 want []string
35 `<style>{{.}} { color: blue }</style>`,
36 []string{
37 `ZgotmplZ`,
38 // Allowed but not escaped.
39 `a[href =~ "//example.com"]#foo`,
40 `ZgotmplZ`,
41 `ZgotmplZ`,
42 `ZgotmplZ`,
43 `ZgotmplZ`,
44 `ZgotmplZ`,
45 `ZgotmplZ`,
46 `ZgotmplZ`,
50 `<div style="{{.}}">`,
51 []string{
52 `ZgotmplZ`,
53 // Allowed and HTML escaped.
54 `a[href =~ &#34;//example.com&#34;]#foo`,
55 `ZgotmplZ`,
56 `ZgotmplZ`,
57 `ZgotmplZ`,
58 `ZgotmplZ`,
59 `ZgotmplZ`,
60 `ZgotmplZ`,
61 `ZgotmplZ`,
65 `{{.}}`,
66 []string{
67 `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
68 `a[href =~ &#34;//example.com&#34;]#foo`,
69 // Not escaped.
70 `Hello, <b>World</b> &amp;tc!`,
71 ` dir=&#34;ltr&#34;`,
72 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
73 `Hello, World &amp; O&#39;Reilly\x21`,
74 `greeting=H%69,&amp;addressee=(World)`,
75 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
76 `,foo/,`,
80 `<a{{.}}>`,
81 []string{
82 `ZgotmplZ`,
83 `ZgotmplZ`,
84 `ZgotmplZ`,
85 // Allowed and HTML escaped.
86 ` dir="ltr"`,
87 `ZgotmplZ`,
88 `ZgotmplZ`,
89 `ZgotmplZ`,
90 `ZgotmplZ`,
91 `ZgotmplZ`,
95 `<a title={{.}}>`,
96 []string{
97 `&lt;b&gt;&#32;&#34;foo%&#34;&#32;O&#39;Reilly&#32;&amp;bar;`,
98 `a[href&#32;&#61;~&#32;&#34;//example.com&#34;]#foo`,
99 // Tags stripped, spaces escaped, entity not re-escaped.
100 `Hello,&#32;World&#32;&amp;tc!`,
101 `&#32;dir&#61;&#34;ltr&#34;`,
102 `c&#32;&amp;&amp;&#32;alert(&#34;Hello,&#32;World!&#34;);`,
103 `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\x21`,
104 `greeting&#61;H%69,&amp;addressee&#61;(World)`,
105 `greeting&#61;H%69,&amp;addressee&#61;(World)&#32;2x,&#32;https://golang.org/favicon.ico&#32;500.5w`,
106 `,foo/,`,
110 `<a title='{{.}}'>`,
111 []string{
112 `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
113 `a[href =~ &#34;//example.com&#34;]#foo`,
114 // Tags stripped, entity not re-escaped.
115 `Hello, World &amp;tc!`,
116 ` dir=&#34;ltr&#34;`,
117 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
118 `Hello, World &amp; O&#39;Reilly\x21`,
119 `greeting=H%69,&amp;addressee=(World)`,
120 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
121 `,foo/,`,
125 `<textarea>{{.}}</textarea>`,
126 []string{
127 `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
128 `a[href =~ &#34;//example.com&#34;]#foo`,
129 // Angle brackets escaped to prevent injection of close tags, entity not re-escaped.
130 `Hello, &lt;b&gt;World&lt;/b&gt; &amp;tc!`,
131 ` dir=&#34;ltr&#34;`,
132 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
133 `Hello, World &amp; O&#39;Reilly\x21`,
134 `greeting=H%69,&amp;addressee=(World)`,
135 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
136 `,foo/,`,
140 `<script>alert({{.}})</script>`,
141 []string{
142 `"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`,
143 `"a[href =~ \"//example.com\"]#foo"`,
144 `"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`,
145 `" dir=\"ltr\""`,
146 // Not escaped.
147 `c && alert("Hello, World!");`,
148 // Escape sequence not over-escaped.
149 `"Hello, World & O'Reilly\x21"`,
150 `"greeting=H%69,\u0026addressee=(World)"`,
151 `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
152 `",foo/,"`,
156 `<button onclick="alert({{.}})">`,
157 []string{
158 `&#34;\u003cb\u003e \&#34;foo%\&#34; O&#39;Reilly \u0026bar;&#34;`,
159 `&#34;a[href =~ \&#34;//example.com\&#34;]#foo&#34;`,
160 `&#34;Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!&#34;`,
161 `&#34; dir=\&#34;ltr\&#34;&#34;`,
162 // Not JS escaped but HTML escaped.
163 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
164 // Escape sequence not over-escaped.
165 `&#34;Hello, World &amp; O&#39;Reilly\x21&#34;`,
166 `&#34;greeting=H%69,\u0026addressee=(World)&#34;`,
167 `&#34;greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w&#34;`,
168 `&#34;,foo/,&#34;`,
172 `<script>alert("{{.}}")</script>`,
173 []string{
174 `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
175 `a[href =~ \x22\/\/example.com\x22]#foo`,
176 `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
177 ` dir=\x22ltr\x22`,
178 `c \x26\x26 alert(\x22Hello, World!\x22);`,
179 // Escape sequence not over-escaped.
180 `Hello, World \x26 O\x27Reilly\x21`,
181 `greeting=H%69,\x26addressee=(World)`,
182 `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
183 `,foo\/,`,
187 `<script type="text/javascript">alert("{{.}}")</script>`,
188 []string{
189 `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
190 `a[href =~ \x22\/\/example.com\x22]#foo`,
191 `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
192 ` dir=\x22ltr\x22`,
193 `c \x26\x26 alert(\x22Hello, World!\x22);`,
194 // Escape sequence not over-escaped.
195 `Hello, World \x26 O\x27Reilly\x21`,
196 `greeting=H%69,\x26addressee=(World)`,
197 `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
198 `,foo\/,`,
202 `<script type="text/javascript">alert({{.}})</script>`,
203 []string{
204 `"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`,
205 `"a[href =~ \"//example.com\"]#foo"`,
206 `"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`,
207 `" dir=\"ltr\""`,
208 // Not escaped.
209 `c && alert("Hello, World!");`,
210 // Escape sequence not over-escaped.
211 `"Hello, World & O'Reilly\x21"`,
212 `"greeting=H%69,\u0026addressee=(World)"`,
213 `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
214 `",foo/,"`,
218 // Not treated as JS. The output is same as for <div>{{.}}</div>
219 `<script type="text/template">{{.}}</script>`,
220 []string{
221 `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
222 `a[href =~ &#34;//example.com&#34;]#foo`,
223 // Not escaped.
224 `Hello, <b>World</b> &amp;tc!`,
225 ` dir=&#34;ltr&#34;`,
226 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
227 `Hello, World &amp; O&#39;Reilly\x21`,
228 `greeting=H%69,&amp;addressee=(World)`,
229 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
230 `,foo/,`,
234 `<button onclick='alert("{{.}}")'>`,
235 []string{
236 `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
237 `a[href =~ \x22\/\/example.com\x22]#foo`,
238 `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
239 ` dir=\x22ltr\x22`,
240 `c \x26\x26 alert(\x22Hello, World!\x22);`,
241 // Escape sequence not over-escaped.
242 `Hello, World \x26 O\x27Reilly\x21`,
243 `greeting=H%69,\x26addressee=(World)`,
244 `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
245 `,foo\/,`,
249 `<a href="?q={{.}}">`,
250 []string{
251 `%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
252 `a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
253 `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
254 `%20dir%3d%22ltr%22`,
255 `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
256 `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
257 // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
258 `greeting=H%69,&amp;addressee=%28World%29`,
259 `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`,
260 `,foo/,`,
264 `<style>body { background: url('?img={{.}}') }</style>`,
265 []string{
266 `%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
267 `a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
268 `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
269 `%20dir%3d%22ltr%22`,
270 `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
271 `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
272 // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
273 `greeting=H%69,&addressee=%28World%29`,
274 `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`,
275 `,foo/,`,
279 `<img srcset="{{.}}">`,
280 []string{
281 `#ZgotmplZ`,
282 `#ZgotmplZ`,
283 // Commas are not esacped
284 `Hello,#ZgotmplZ`,
285 // Leading spaces are not percent escapes.
286 ` dir=%22ltr%22`,
287 // Spaces after commas are not percent escaped.
288 `#ZgotmplZ, World!%22%29;`,
289 `Hello,#ZgotmplZ`,
290 `greeting=H%69%2c&amp;addressee=%28World%29`,
291 // Metadata is not escaped.
292 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
293 `%2cfoo/%2c`,
297 `<img srcset={{.}}>`,
298 []string{
299 `#ZgotmplZ`,
300 `#ZgotmplZ`,
301 `Hello,#ZgotmplZ`,
302 // Spaces are HTML escaped not %-escaped
303 `&#32;dir&#61;%22ltr%22`,
304 `#ZgotmplZ,&#32;World!%22%29;`,
305 `Hello,#ZgotmplZ`,
306 `greeting&#61;H%69%2c&amp;addressee&#61;%28World%29`,
307 `greeting&#61;H%69,&amp;addressee&#61;(World)&#32;2x,&#32;https://golang.org/favicon.ico&#32;500.5w`,
308 // Commas are escaped.
309 `%2cfoo/%2c`,
313 `<img srcset="{{.}} 2x, https://golang.org/ 500.5w">`,
314 []string{
315 `#ZgotmplZ`,
316 `#ZgotmplZ`,
317 `Hello,#ZgotmplZ`,
318 ` dir=%22ltr%22`,
319 `#ZgotmplZ, World!%22%29;`,
320 `Hello,#ZgotmplZ`,
321 `greeting=H%69%2c&amp;addressee=%28World%29`,
322 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
323 `%2cfoo/%2c`,
327 `<img srcset="http://godoc.org/ {{.}}, https://golang.org/ 500.5w">`,
328 []string{
329 `#ZgotmplZ`,
330 `#ZgotmplZ`,
331 `Hello,#ZgotmplZ`,
332 ` dir=%22ltr%22`,
333 `#ZgotmplZ, World!%22%29;`,
334 `Hello,#ZgotmplZ`,
335 `greeting=H%69%2c&amp;addressee=%28World%29`,
336 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
337 `%2cfoo/%2c`,
341 `<img srcset="http://godoc.org/?q={{.}} 2x, https://golang.org/ 500.5w">`,
342 []string{
343 `#ZgotmplZ`,
344 `#ZgotmplZ`,
345 `Hello,#ZgotmplZ`,
346 ` dir=%22ltr%22`,
347 `#ZgotmplZ, World!%22%29;`,
348 `Hello,#ZgotmplZ`,
349 `greeting=H%69%2c&amp;addressee=%28World%29`,
350 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
351 `%2cfoo/%2c`,
355 `<img srcset="http://godoc.org/ 2x, {{.}} 500.5w">`,
356 []string{
357 `#ZgotmplZ`,
358 `#ZgotmplZ`,
359 `Hello,#ZgotmplZ`,
360 ` dir=%22ltr%22`,
361 `#ZgotmplZ, World!%22%29;`,
362 `Hello,#ZgotmplZ`,
363 `greeting=H%69%2c&amp;addressee=%28World%29`,
364 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
365 `%2cfoo/%2c`,
369 `<img srcset="http://godoc.org/ 2x, https://golang.org/ {{.}}">`,
370 []string{
371 `#ZgotmplZ`,
372 `#ZgotmplZ`,
373 `Hello,#ZgotmplZ`,
374 ` dir=%22ltr%22`,
375 `#ZgotmplZ, World!%22%29;`,
376 `Hello,#ZgotmplZ`,
377 `greeting=H%69%2c&amp;addressee=%28World%29`,
378 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
379 `%2cfoo/%2c`,
384 for _, test := range tests {
385 tmpl := Must(New("x").Parse(test.input))
386 pre := strings.Index(test.input, "{{.}}")
387 post := len(test.input) - (pre + 5)
388 var b bytes.Buffer
389 for i, x := range data {
390 b.Reset()
391 if err := tmpl.Execute(&b, x); err != nil {
392 t.Errorf("%q with %v: %s", test.input, x, err)
393 continue
395 if want, got := test.want[i], b.String()[pre:b.Len()-post]; want != got {
396 t.Errorf("%q with %v:\nwant\n\t%q,\ngot\n\t%q\n", test.input, x, want, got)
397 continue
403 // Test that we print using the String method. Was issue 3073.
404 type stringer struct {
405 v int
408 func (s *stringer) String() string {
409 return fmt.Sprintf("string=%d", s.v)
412 type errorer struct {
413 v int
416 func (s *errorer) Error() string {
417 return fmt.Sprintf("error=%d", s.v)
420 func TestStringer(t *testing.T) {
421 s := &stringer{3}
422 b := new(bytes.Buffer)
423 tmpl := Must(New("x").Parse("{{.}}"))
424 if err := tmpl.Execute(b, s); err != nil {
425 t.Fatal(err)
427 var expect = "string=3"
428 if b.String() != expect {
429 t.Errorf("expected %q got %q", expect, b.String())
431 e := &errorer{7}
432 b.Reset()
433 if err := tmpl.Execute(b, e); err != nil {
434 t.Fatal(err)
436 expect = "error=7"
437 if b.String() != expect {
438 t.Errorf("expected %q got %q", expect, b.String())
442 // https://golang.org/issue/5982
443 func TestEscapingNilNonemptyInterfaces(t *testing.T) {
444 tmpl := Must(New("x").Parse("{{.E}}"))
446 got := new(bytes.Buffer)
447 testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
448 tmpl.Execute(got, testData)
450 // Use this data instead of just hard-coding "&lt;nil&gt;" to avoid
451 // dependencies on the html escaper and the behavior of fmt w.r.t. nil.
452 want := new(bytes.Buffer)
453 data := struct{ E string }{E: fmt.Sprint(nil)}
454 tmpl.Execute(want, data)
456 if !bytes.Equal(want.Bytes(), got.Bytes()) {
457 t.Errorf("expected %q got %q", string(want.Bytes()), string(got.Bytes()))