OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [html/] [template/] [js_test.go] - Blame information for rev 775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
        "math"
10
        "strings"
11
        "testing"
12
)
13
 
14
func TestNextJsCtx(t *testing.T) {
15
        tests := []struct {
16
                jsCtx jsCtx
17
                s     string
18
        }{
19
                // Statement terminators precede regexps.
20
                {jsCtxRegexp, ";"},
21
                // This is not airtight.
22
                //     ({ valueOf: function () { return 1 } } / 2)
23
                // is valid JavaScript but in practice, devs do not do this.
24
                // A block followed by a statement starting with a RegExp is
25
                // much more common:
26
                //     while (x) {...} /foo/.test(x) || panic()
27
                {jsCtxRegexp, "}"},
28
                // But member, call, grouping, and array expression terminators
29
                // precede div ops.
30
                {jsCtxDivOp, ")"},
31
                {jsCtxDivOp, "]"},
32
                // At the start of a primary expression, array, or expression
33
                // statement, expect a regexp.
34
                {jsCtxRegexp, "("},
35
                {jsCtxRegexp, "["},
36
                {jsCtxRegexp, "{"},
37
                // Assignment operators precede regexps as do all exclusively
38
                // prefix and binary operators.
39
                {jsCtxRegexp, "="},
40
                {jsCtxRegexp, "+="},
41
                {jsCtxRegexp, "*="},
42
                {jsCtxRegexp, "*"},
43
                {jsCtxRegexp, "!"},
44
                // Whether the + or - is infix or prefix, it cannot precede a
45
                // div op.
46
                {jsCtxRegexp, "+"},
47
                {jsCtxRegexp, "-"},
48
                // An incr/decr op precedes a div operator.
49
                // This is not airtight. In (g = ++/h/i) a regexp follows a
50
                // pre-increment operator, but in practice devs do not try to
51
                // increment or decrement regular expressions.
52
                // (g++/h/i) where ++ is a postfix operator on g is much more
53
                // common.
54
                {jsCtxDivOp, "--"},
55
                {jsCtxDivOp, "++"},
56
                {jsCtxDivOp, "x--"},
57
                // When we have many dashes or pluses, then they are grouped
58
                // left to right.
59
                {jsCtxRegexp, "x---"}, // A postfix -- then a -.
60
                // return followed by a slash returns the regexp literal or the
61
                // slash starts a regexp literal in an expression statement that
62
                // is dead code.
63
                {jsCtxRegexp, "return"},
64
                {jsCtxRegexp, "return "},
65
                {jsCtxRegexp, "return\t"},
66
                {jsCtxRegexp, "return\n"},
67
                {jsCtxRegexp, "return\u2028"},
68
                // Identifiers can be divided and cannot validly be preceded by
69
                // a regular expressions. Semicolon insertion cannot happen
70
                // between an identifier and a regular expression on a new line
71
                // because the one token lookahead for semicolon insertion has
72
                // to conclude that it could be a div binary op and treat it as
73
                // such.
74
                {jsCtxDivOp, "x"},
75
                {jsCtxDivOp, "x "},
76
                {jsCtxDivOp, "x\t"},
77
                {jsCtxDivOp, "x\n"},
78
                {jsCtxDivOp, "x\u2028"},
79
                {jsCtxDivOp, "preturn"},
80
                // Numbers precede div ops.
81
                {jsCtxDivOp, "0"},
82
                // Dots that are part of a number are div preceders.
83
                {jsCtxDivOp, "0."},
84
        }
85
 
86
        for _, test := range tests {
87
                if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
88
                        t.Errorf("want %s got %q", test.jsCtx, test.s)
89
                }
90
                if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
91
                        t.Errorf("want %s got %q", test.jsCtx, test.s)
92
                }
93
        }
94
 
95
        if nextJSCtx([]byte("   "), jsCtxRegexp) != jsCtxRegexp {
96
                t.Error("Blank tokens")
97
        }
98
 
99
        if nextJSCtx([]byte("   "), jsCtxDivOp) != jsCtxDivOp {
100
                t.Error("Blank tokens")
101
        }
102
}
103
 
104
func TestJSValEscaper(t *testing.T) {
105
        tests := []struct {
106
                x  interface{}
107
                js string
108
        }{
109
                {int(42), " 42 "},
110
                {uint(42), " 42 "},
111
                {int16(42), " 42 "},
112
                {uint16(42), " 42 "},
113
                {int32(-42), " -42 "},
114
                {uint32(42), " 42 "},
115
                {int16(-42), " -42 "},
116
                {uint16(42), " 42 "},
117
                {int64(-42), " -42 "},
118
                {uint64(42), " 42 "},
119
                {uint64(1) << 53, " 9007199254740992 "},
120
                // ulp(1 << 53) > 1 so this loses precision in JS
121
                // but it is still a representable integer literal.
122
                {uint64(1)<<53 + 1, " 9007199254740993 "},
123
                {float32(1.0), " 1 "},
124
                {float32(-1.0), " -1 "},
125
                {float32(0.5), " 0.5 "},
126
                {float32(-0.5), " -0.5 "},
127
                {float32(1.0) / float32(256), " 0.00390625 "},
128
                {float32(0), " 0 "},
129
                {math.Copysign(0, -1), " -0 "},
130
                {float64(1.0), " 1 "},
131
                {float64(-1.0), " -1 "},
132
                {float64(0.5), " 0.5 "},
133
                {float64(-0.5), " -0.5 "},
134
                {float64(0), " 0 "},
135
                {math.Copysign(0, -1), " -0 "},
136
                {"", `""`},
137
                {"foo", `"foo"`},
138
                // Newlines.
139
                {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
140
                // "\v" == "v" on IE 6 so use "\x0b" instead.
141
                {"\t\x0b", `"\u0009\u000b"`},
142
                {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
143
                {[]interface{}{}, "[]"},
144
                {[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
145
                {[]string{""}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
146
                {"", `"--\u003e"`},
148
                {"
149
                {"]]>", `"]]\u003e"`},
150
                {"
151
                {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
152
        }
153
 
154
        for _, test := range tests {
155
                if js := jsValEscaper(test.x); js != test.js {
156
                        t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
157
                }
158
                // Make sure that escaping corner cases are not broken
159
                // by nesting.
160
                a := []interface{}{test.x}
161
                want := "[" + strings.TrimSpace(test.js) + "]"
162
                if js := jsValEscaper(a); js != want {
163
                        t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js)
164
                }
165
        }
166
}
167
 
168
func TestJSStrEscaper(t *testing.T) {
169
        tests := []struct {
170
                x   interface{}
171
                esc string
172
        }{
173
                {"", ``},
174
                {"foo", `foo`},
175
                {"\u0000", `\0`},
176
                {"\t", `\t`},
177
                {"\n", `\n`},
178
                {"\r", `\r`},
179
                {"\u2028", `\u2028`},
180
                {"\u2029", `\u2029`},
181
                {"\\", `\\`},
182
                {"\\n", `\\n`},
183
                {"foo\r\nbar", `foo\r\nbar`},
184
                // Preserve attribute boundaries.
185
                {`"`, `\x22`},
186
                {`'`, `\x27`},
187
                // Allow embedding in HTML without further escaping.
188
                {`&`, `\x26amp;`},
189
                // Prevent breaking out of text node and element boundaries.
190
                {"", `\x3c\/script\x3e`},
191
                {"
192
                {"]]>", `]]\x3e`},
193
                // http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
194
                //   "The text in style, script, title, and textarea elements
195
                //   must not have an escaping text span start that is not
196
                //   followed by an escaping text span end."
197
                // Furthermore, spoofing an escaping text span end could lead
198
                // to different interpretation of a  sequence otherwise
199
                // masked by the escaping text span, and spoofing a start could
200
                // allow regular text content to be interpreted as script
201
                // allowing script execution via a combination of a JS string
202
                // injection followed by an HTML text injection.
203
                {"", `--\x3e`},
205
                // From http://code.google.com/p/doctype/wiki/ArticleUtf7
206
                {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
207
                        `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
208
                },
209
                // Invalid UTF-8 sequence
210
                {"foo\xA0bar", "foo\xA0bar"},
211
                // Invalid unicode scalar value.
212
                {"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"},
213
        }
214
 
215
        for _, test := range tests {
216
                esc := jsStrEscaper(test.x)
217
                if esc != test.esc {
218
                        t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
219
                }
220
        }
221
}
222
 
223
func TestJSRegexpEscaper(t *testing.T) {
224
        tests := []struct {
225
                x   interface{}
226
                esc string
227
        }{
228
                {"", `(?:)`},
229
                {"foo", `foo`},
230
                {"\u0000", `\0`},
231
                {"\t", `\t`},
232
                {"\n", `\n`},
233
                {"\r", `\r`},
234
                {"\u2028", `\u2028`},
235
                {"\u2029", `\u2029`},
236
                {"\\", `\\`},
237
                {"\\n", `\\n`},
238
                {"foo\r\nbar", `foo\r\nbar`},
239
                // Preserve attribute boundaries.
240
                {`"`, `\x22`},
241
                {`'`, `\x27`},
242
                // Allow embedding in HTML without further escaping.
243
                {`&`, `\x26amp;`},
244
                // Prevent breaking out of text node and element boundaries.
245
                {"", `\x3c\/script\x3e`},
246
                {"
247
                {"]]>", `\]\]\x3e`},
248
                // Escaping text spans.
249
                {"", `\-\-\x3e`},
251
                {"*", `\*`},
252
                {"+", `\x2b`},
253
                {"?", `\?`},
254
                {"[](){}", `\[\]\(\)\{\}`},
255
                {"$foo|x.y", `\$foo\|x\.y`},
256
                {"x^y", `x\^y`},
257
        }
258
 
259
        for _, test := range tests {
260
                esc := jsRegexpEscaper(test.x)
261
                if esc != test.esc {
262
                        t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
263
                }
264
        }
265
}
266
 
267
func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
268
        input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
269
                "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
270
                ` !"#$%&'()*+,-./` +
271
                `0123456789:;<=>?` +
272
                `@ABCDEFGHIJKLMNO` +
273
                `PQRSTUVWXYZ[\]^_` +
274
                "`abcdefghijklmno" +
275
                "pqrstuvwxyz{|}~\x7f" +
276
                "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
277
 
278
        tests := []struct {
279
                name    string
280
                escaper func(...interface{}) string
281
                escaped string
282
        }{
283
                {
284
                        "jsStrEscaper",
285
                        jsStrEscaper,
286
                        "\\0\x01\x02\x03\x04\x05\x06\x07" +
287
                                "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
288
                                "\x10\x11\x12\x13\x14\x15\x16\x17" +
289
                                "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
290
                                ` !\x22#$%\x26\x27()*\x2b,-.\/` +
291
                                `0123456789:;\x3c=\x3e?` +
292
                                `@ABCDEFGHIJKLMNO` +
293
                                `PQRSTUVWXYZ[\\]^_` +
294
                                "`abcdefghijklmno" +
295
                                "pqrstuvwxyz{|}~\x7f" +
296
                                "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
297
                },
298
                {
299
                        "jsRegexpEscaper",
300
                        jsRegexpEscaper,
301
                        "\\0\x01\x02\x03\x04\x05\x06\x07" +
302
                                "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
303
                                "\x10\x11\x12\x13\x14\x15\x16\x17" +
304
                                "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
305
                                ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
306
                                `0123456789:;\x3c=\x3e\?` +
307
                                `@ABCDEFGHIJKLMNO` +
308
                                `PQRSTUVWXYZ\[\\\]\^_` +
309
                                "`abcdefghijklmno" +
310
                                `pqrstuvwxyz\{\|\}~` + "\u007f" +
311
                                "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
312
                },
313
        }
314
 
315
        for _, test := range tests {
316
                if s := test.escaper(input); s != test.escaped {
317
                        t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
318
                        continue
319
                }
320
 
321
                // Escape it rune by rune to make sure that any
322
                // fast-path checking does not break escaping.
323
                var buf bytes.Buffer
324
                for _, c := range input {
325
                        buf.WriteString(test.escaper(string(c)))
326
                }
327
 
328
                if s := buf.String(); s != test.escaped {
329
                        t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
330
                        continue
331
                }
332
        }
333
}
334
 
335
func BenchmarkJSValEscaperWithNum(b *testing.B) {
336
        for i := 0; i < b.N; i++ {
337
                jsValEscaper(3.141592654)
338
        }
339
}
340
 
341
func BenchmarkJSValEscaperWithStr(b *testing.B) {
342
        for i := 0; i < b.N; i++ {
343
                jsValEscaper("The quick,\r\nbrown fox jumps\u2028over the dog")
344
        }
345
}
346
 
347
func BenchmarkJSValEscaperWithStrNoSpecials(b *testing.B) {
348
        for i := 0; i < b.N; i++ {
349
                jsValEscaper("The quick, brown fox jumps over the lazy dog")
350
        }
351
}
352
 
353
func BenchmarkJSValEscaperWithObj(b *testing.B) {
354
        o := struct {
355
                S string
356
                N int
357
        }{
358
                "The quick,\r\nbrown fox jumps\u2028over the dog\u2028",
359
                42,
360
        }
361
        for i := 0; i < b.N; i++ {
362
                jsValEscaper(o)
363
        }
364
}
365
 
366
func BenchmarkJSValEscaperWithObjNoSpecials(b *testing.B) {
367
        o := struct {
368
                S string
369
                N int
370
        }{
371
                "The quick, brown fox jumps over the lazy dog",
372
                42,
373
        }
374
        for i := 0; i < b.N; i++ {
375
                jsValEscaper(o)
376
        }
377
}
378
 
379
func BenchmarkJSStrEscaperNoSpecials(b *testing.B) {
380
        for i := 0; i < b.N; i++ {
381
                jsStrEscaper("The quick, brown fox jumps over the lazy dog.")
382
        }
383
}
384
 
385
func BenchmarkJSStrEscaper(b *testing.B) {
386
        for i := 0; i < b.N; i++ {
387
                jsStrEscaper("The quick,\r\nbrown fox jumps\u2028over the dog")
388
        }
389
}
390
 
391
func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) {
392
        for i := 0; i < b.N; i++ {
393
                jsRegexpEscaper("The quick, brown fox jumps over the lazy dog")
394
        }
395
}
396
 
397
func BenchmarkJSRegexpEscaper(b *testing.B) {
398
        for i := 0; i < b.N; i++ {
399
                jsRegexpEscaper("The quick,\r\nbrown fox jumps\u2028over the dog")
400
        }
401
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.