diff options
Diffstat (limited to 'src/pkg/html/template/js_test.go')
-rw-r--r-- | src/pkg/html/template/js_test.go | 401 |
1 files changed, 0 insertions, 401 deletions
diff --git a/src/pkg/html/template/js_test.go b/src/pkg/html/template/js_test.go deleted file mode 100644 index 311e1d2c4..000000000 --- a/src/pkg/html/template/js_test.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package template - -import ( - "bytes" - "math" - "strings" - "testing" -) - -func TestNextJsCtx(t *testing.T) { - tests := []struct { - jsCtx jsCtx - s string - }{ - // Statement terminators precede regexps. - {jsCtxRegexp, ";"}, - // This is not airtight. - // ({ valueOf: function () { return 1 } } / 2) - // is valid JavaScript but in practice, devs do not do this. - // A block followed by a statement starting with a RegExp is - // much more common: - // while (x) {...} /foo/.test(x) || panic() - {jsCtxRegexp, "}"}, - // But member, call, grouping, and array expression terminators - // precede div ops. - {jsCtxDivOp, ")"}, - {jsCtxDivOp, "]"}, - // At the start of a primary expression, array, or expression - // statement, expect a regexp. - {jsCtxRegexp, "("}, - {jsCtxRegexp, "["}, - {jsCtxRegexp, "{"}, - // Assignment operators precede regexps as do all exclusively - // prefix and binary operators. - {jsCtxRegexp, "="}, - {jsCtxRegexp, "+="}, - {jsCtxRegexp, "*="}, - {jsCtxRegexp, "*"}, - {jsCtxRegexp, "!"}, - // Whether the + or - is infix or prefix, it cannot precede a - // div op. - {jsCtxRegexp, "+"}, - {jsCtxRegexp, "-"}, - // An incr/decr op precedes a div operator. - // This is not airtight. In (g = ++/h/i) a regexp follows a - // pre-increment operator, but in practice devs do not try to - // increment or decrement regular expressions. - // (g++/h/i) where ++ is a postfix operator on g is much more - // common. - {jsCtxDivOp, "--"}, - {jsCtxDivOp, "++"}, - {jsCtxDivOp, "x--"}, - // When we have many dashes or pluses, then they are grouped - // left to right. - {jsCtxRegexp, "x---"}, // A postfix -- then a -. - // return followed by a slash returns the regexp literal or the - // slash starts a regexp literal in an expression statement that - // is dead code. - {jsCtxRegexp, "return"}, - {jsCtxRegexp, "return "}, - {jsCtxRegexp, "return\t"}, - {jsCtxRegexp, "return\n"}, - {jsCtxRegexp, "return\u2028"}, - // Identifiers can be divided and cannot validly be preceded by - // a regular expressions. Semicolon insertion cannot happen - // between an identifier and a regular expression on a new line - // because the one token lookahead for semicolon insertion has - // to conclude that it could be a div binary op and treat it as - // such. - {jsCtxDivOp, "x"}, - {jsCtxDivOp, "x "}, - {jsCtxDivOp, "x\t"}, - {jsCtxDivOp, "x\n"}, - {jsCtxDivOp, "x\u2028"}, - {jsCtxDivOp, "preturn"}, - // Numbers precede div ops. - {jsCtxDivOp, "0"}, - // Dots that are part of a number are div preceders. - {jsCtxDivOp, "0."}, - } - - for _, test := range tests { - if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx { - t.Errorf("want %s got %q", test.jsCtx, test.s) - } - if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx { - t.Errorf("want %s got %q", test.jsCtx, test.s) - } - } - - if nextJSCtx([]byte(" "), jsCtxRegexp) != jsCtxRegexp { - t.Error("Blank tokens") - } - - if nextJSCtx([]byte(" "), jsCtxDivOp) != jsCtxDivOp { - t.Error("Blank tokens") - } -} - -func TestJSValEscaper(t *testing.T) { - tests := []struct { - x interface{} - js string - }{ - {int(42), " 42 "}, - {uint(42), " 42 "}, - {int16(42), " 42 "}, - {uint16(42), " 42 "}, - {int32(-42), " -42 "}, - {uint32(42), " 42 "}, - {int16(-42), " -42 "}, - {uint16(42), " 42 "}, - {int64(-42), " -42 "}, - {uint64(42), " 42 "}, - {uint64(1) << 53, " 9007199254740992 "}, - // ulp(1 << 53) > 1 so this loses precision in JS - // but it is still a representable integer literal. - {uint64(1)<<53 + 1, " 9007199254740993 "}, - {float32(1.0), " 1 "}, - {float32(-1.0), " -1 "}, - {float32(0.5), " 0.5 "}, - {float32(-0.5), " -0.5 "}, - {float32(1.0) / float32(256), " 0.00390625 "}, - {float32(0), " 0 "}, - {math.Copysign(0, -1), " -0 "}, - {float64(1.0), " 1 "}, - {float64(-1.0), " -1 "}, - {float64(0.5), " 0.5 "}, - {float64(-0.5), " -0.5 "}, - {float64(0), " 0 "}, - {math.Copysign(0, -1), " -0 "}, - {"", `""`}, - {"foo", `"foo"`}, - // Newlines. - {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, - // "\v" == "v" on IE 6 so use "\x0b" instead. - {"\t\x0b", `"\u0009\u000b"`}, - {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, - {[]interface{}{}, "[]"}, - {[]interface{}{42, "foo", nil}, `[42,"foo",null]`}, - {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`}, - {"<!--", `"\u003c!--"`}, - {"-->", `"--\u003e"`}, - {"<![CDATA[", `"\u003c![CDATA["`}, - {"]]>", `"]]\u003e"`}, - {"</script", `"\u003c/script"`}, - {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E" - } - - for _, test := range tests { - if js := jsValEscaper(test.x); js != test.js { - t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js) - } - // Make sure that escaping corner cases are not broken - // by nesting. - a := []interface{}{test.x} - want := "[" + strings.TrimSpace(test.js) + "]" - if js := jsValEscaper(a); js != want { - t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js) - } - } -} - -func TestJSStrEscaper(t *testing.T) { - tests := []struct { - x interface{} - esc string - }{ - {"", ``}, - {"foo", `foo`}, - {"\u0000", `\0`}, - {"\t", `\t`}, - {"\n", `\n`}, - {"\r", `\r`}, - {"\u2028", `\u2028`}, - {"\u2029", `\u2029`}, - {"\\", `\\`}, - {"\\n", `\\n`}, - {"foo\r\nbar", `foo\r\nbar`}, - // Preserve attribute boundaries. - {`"`, `\x22`}, - {`'`, `\x27`}, - // Allow embedding in HTML without further escaping. - {`&`, `\x26amp;`}, - // Prevent breaking out of text node and element boundaries. - {"</script>", `\x3c\/script\x3e`}, - {"<![CDATA[", `\x3c![CDATA[`}, - {"]]>", `]]\x3e`}, - // http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span - // "The text in style, script, title, and textarea elements - // must not have an escaping text span start that is not - // followed by an escaping text span end." - // Furthermore, spoofing an escaping text span end could lead - // to different interpretation of a </script> sequence otherwise - // masked by the escaping text span, and spoofing a start could - // allow regular text content to be interpreted as script - // allowing script execution via a combination of a JS string - // injection followed by an HTML text injection. - {"<!--", `\x3c!--`}, - {"-->", `--\x3e`}, - // From http://code.google.com/p/doctype/wiki/ArticleUtf7 - {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-", - `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`, - }, - // Invalid UTF-8 sequence - {"foo\xA0bar", "foo\xA0bar"}, - // Invalid unicode scalar value. - {"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"}, - } - - for _, test := range tests { - esc := jsStrEscaper(test.x) - if esc != test.esc { - t.Errorf("%q: want %q got %q", test.x, test.esc, esc) - } - } -} - -func TestJSRegexpEscaper(t *testing.T) { - tests := []struct { - x interface{} - esc string - }{ - {"", `(?:)`}, - {"foo", `foo`}, - {"\u0000", `\0`}, - {"\t", `\t`}, - {"\n", `\n`}, - {"\r", `\r`}, - {"\u2028", `\u2028`}, - {"\u2029", `\u2029`}, - {"\\", `\\`}, - {"\\n", `\\n`}, - {"foo\r\nbar", `foo\r\nbar`}, - // Preserve attribute boundaries. - {`"`, `\x22`}, - {`'`, `\x27`}, - // Allow embedding in HTML without further escaping. - {`&`, `\x26amp;`}, - // Prevent breaking out of text node and element boundaries. - {"</script>", `\x3c\/script\x3e`}, - {"<![CDATA[", `\x3c!\[CDATA\[`}, - {"]]>", `\]\]\x3e`}, - // Escaping text spans. - {"<!--", `\x3c!\-\-`}, - {"-->", `\-\-\x3e`}, - {"*", `\*`}, - {"+", `\x2b`}, - {"?", `\?`}, - {"[](){}", `\[\]\(\)\{\}`}, - {"$foo|x.y", `\$foo\|x\.y`}, - {"x^y", `x\^y`}, - } - - for _, test := range tests { - esc := jsRegexpEscaper(test.x) - if esc != test.esc { - t.Errorf("%q: want %q got %q", test.x, test.esc, esc) - } - } -} - -func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) { - input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" + - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - ` !"#$%&'()*+,-./` + - `0123456789:;<=>?` + - `@ABCDEFGHIJKLMNO` + - `PQRSTUVWXYZ[\]^_` + - "`abcdefghijklmno" + - "pqrstuvwxyz{|}~\x7f" + - "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E") - - tests := []struct { - name string - escaper func(...interface{}) string - escaped string - }{ - { - "jsStrEscaper", - jsStrEscaper, - "\\0\x01\x02\x03\x04\x05\x06\x07" + - "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + - "\x10\x11\x12\x13\x14\x15\x16\x17" + - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - ` !\x22#$%\x26\x27()*\x2b,-.\/` + - `0123456789:;\x3c=\x3e?` + - `@ABCDEFGHIJKLMNO` + - `PQRSTUVWXYZ[\\]^_` + - "`abcdefghijklmno" + - "pqrstuvwxyz{|}~\x7f" + - "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", - }, - { - "jsRegexpEscaper", - jsRegexpEscaper, - "\\0\x01\x02\x03\x04\x05\x06\x07" + - "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + - "\x10\x11\x12\x13\x14\x15\x16\x17" + - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` + - `0123456789:;\x3c=\x3e\?` + - `@ABCDEFGHIJKLMNO` + - `PQRSTUVWXYZ\[\\\]\^_` + - "`abcdefghijklmno" + - `pqrstuvwxyz\{\|\}~` + "\u007f" + - "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", - }, - } - - for _, test := range tests { - if s := test.escaper(input); s != test.escaped { - t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s) - continue - } - - // Escape it rune by rune to make sure that any - // fast-path checking does not break escaping. - var buf bytes.Buffer - for _, c := range input { - buf.WriteString(test.escaper(string(c))) - } - - if s := buf.String(); s != test.escaped { - t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s) - continue - } - } -} - -func BenchmarkJSValEscaperWithNum(b *testing.B) { - for i := 0; i < b.N; i++ { - jsValEscaper(3.141592654) - } -} - -func BenchmarkJSValEscaperWithStr(b *testing.B) { - for i := 0; i < b.N; i++ { - jsValEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>") - } -} - -func BenchmarkJSValEscaperWithStrNoSpecials(b *testing.B) { - for i := 0; i < b.N; i++ { - jsValEscaper("The quick, brown fox jumps over the lazy dog") - } -} - -func BenchmarkJSValEscaperWithObj(b *testing.B) { - o := struct { - S string - N int - }{ - "The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>\u2028", - 42, - } - for i := 0; i < b.N; i++ { - jsValEscaper(o) - } -} - -func BenchmarkJSValEscaperWithObjNoSpecials(b *testing.B) { - o := struct { - S string - N int - }{ - "The quick, brown fox jumps over the lazy dog", - 42, - } - for i := 0; i < b.N; i++ { - jsValEscaper(o) - } -} - -func BenchmarkJSStrEscaperNoSpecials(b *testing.B) { - for i := 0; i < b.N; i++ { - jsStrEscaper("The quick, brown fox jumps over the lazy dog.") - } -} - -func BenchmarkJSStrEscaper(b *testing.B) { - for i := 0; i < b.N; i++ { - jsStrEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>") - } -} - -func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) { - for i := 0; i < b.N; i++ { - jsRegexpEscaper("The quick, brown fox jumps over the lazy dog") - } -} - -func BenchmarkJSRegexpEscaper(b *testing.B) { - for i := 0; i < b.N; i++ { - jsRegexpEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>") - } -} |